ETH Price: $2,719.71 (+3.50%)

Transaction Decoder

Block:
22385123 at Apr-30-2025 11:25:59 PM +UTC
Transaction Fee:
0.00110480701828298 ETH $3.00
Gas Used:
390,332 Gas / 2.830429015 Gwei

Emitted Events:

66 SErc20Delegator.AccrueInterest( cashPrior=647710547438, interestAccumulated=408606286, borrowIndex=1380628873501593941, totalBorrows=2938341879902 )
67 Unitroller.0x730ec20a857394345ba1d81394d16c333202df6c655e85f7cf16c65954def57e( 0x730ec20a857394345ba1d81394d16c333202df6c655e85f7cf16c65954def57e, 0x0000000000000000000000003774e825d567125988fb293e926064b6faa71dab, 0x00000000000000000000000094599741aada66a4687c4a533f4b91c208b5db4b, 00000000000000000000000000000000000000000000000000fd6727b4d52496, 00000000000000000000000009087e082aac24559dd84703e6d2053f1ee7de2a )
68 FiatTokenProxy.0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef( 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef, 0x0000000000000000000000003774e825d567125988fb293e926064b6faa71dab, 0x00000000000000000000000094599741aada66a4687c4a533f4b91c208b5db4b, 0000000000000000000000000000000000000000000000000000000048bef607 )
69 SErc20Delegator.Borrow( borrower=[Sender] 0x94599741aada66a4687c4a533f4b91c208b5db4b, borrowAmount=1220474375, accountBorrows=2220979704, totalBorrows=2939562354277 )

Account State Difference:

  Address   Before After State Difference Code
0x3774E825...6FAa71DAB
0x94599741...208B5Db4b
0.057262141146774777 Eth
Nonce: 156
0.056157334128491797 Eth
Nonce: 157
0.00110480701828298
(beaverbuild)
10.244844651002277708 Eth10.245820481002277708 Eth0.00097583
0xA0b86991...E3606eB48
0xe2e17b2C...e39bA2602

Execution Trace

SErc20Delegator.borrow( borrowAmount=1220474375 ) => ( 0 )
  • SErc20Delegate.borrow( borrowAmount=1220474375 ) => ( 0 )
    • FiatTokenProxy.70a08231( )
      • FiatTokenV2_2.balanceOf( account=0x3774E825d567125988Fb293e926064B6FAa71DAB ) => ( 647710547438 )
      • JumpRateModelV2.getBorrowRate( cash=647710547438, borrows=2937933273616, reserves=235251636 ) => ( 33847529494 )
      • Unitroller.da3d454c( )
        • Comptroller.borrowAllowed( sToken=0x3774E825d567125988Fb293e926064B6FAa71DAB, borrower=0x94599741aAda66A4687c4a533f4B91C208B5Db4b, borrowAmount=1220474375 ) => ( 0 )
          • StrikeAggregatorPriceOracleV2.getUnderlyingPrice( sToken=0x3774E825d567125988Fb293e926064B6FAa71DAB ) => ( 999930750000000000000000000000 )
            • SErc20Delegator.STATICCALL( )
            • SErc20Delegator.STATICCALL( )
            • SErc20Delegator.STATICCALL( )
            • FiatTokenProxy.STATICCALL( )
              • FiatTokenV2_2.DELEGATECALL( )
              • FiatTokenProxy.STATICCALL( )
                • FiatTokenV2_2.DELEGATECALL( )
                • EACAggregatorProxy.STATICCALL( )
                  • AccessControlledOCR2Aggregator.STATICCALL( )
                  • EACAggregatorProxy.STATICCALL( )
                    • AccessControlledOCR2Aggregator.STATICCALL( )
                    • FiatTokenProxy.STATICCALL( )
                      • FiatTokenV2_2.DELEGATECALL( )
                      • SErc20Delegator.getAccountSnapshot( account=0x94599741aAda66A4687c4a533f4B91C208B5Db4b ) => ( 0, 228058637, 0, 21545950302083082 )
                        • SErc20Delegator.delegateToImplementation( data=0xC37F68E200000000000000000000000094599741AADA66A4687C4A533F4B91C208B5DB4B ) => ( 0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000D97E60D0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004C8BED7A1A980A )
                          • SErc20Delegate.getAccountSnapshot( account=0x94599741aAda66A4687c4a533f4B91C208B5Db4b ) => ( 0, 228058637, 0, 21545950302083082 )
                          • StrikeAggregatorPriceOracleV2.getUnderlyingPrice( sToken=0x9d1C2A187cf908aEd8CFAe2353Ef72F06223d54D ) => ( 941588280000000000000000000000000 )
                            • SErc20Delegator.STATICCALL( )
                            • SErc20Delegator.STATICCALL( )
                            • SErc20Delegator.STATICCALL( )
                            • WBTC.STATICCALL( )
                            • WBTC.STATICCALL( )
                            • EACAggregatorProxy.STATICCALL( )
                              • AccessControlledOCR2Aggregator.STATICCALL( )
                              • EACAggregatorProxy.STATICCALL( )
                                • AccessControlledOCR2Aggregator.STATICCALL( )
                                • WBTC.STATICCALL( )
                                • SErc20Delegator.getAccountSnapshot( account=0x94599741aAda66A4687c4a533f4B91C208B5Db4b ) => ( 0, 0, 1000505329, 250543904454967 )
                                  • SErc20Delegator.delegateToImplementation( data=0xC37F68E200000000000000000000000094599741AADA66A4687C4A533F4B91C208B5DB4B ) => ( 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003BA27FF10000000000000000000000000000000000000000000000000000E3DE4C6CF937 )
                                    • SErc20Delegate.getAccountSnapshot( account=0x94599741aAda66A4687c4a533f4B91C208B5Db4b ) => ( 0, 0, 1000505329, 250543904454967 )
                                    • StrikeAggregatorPriceOracleV2.getUnderlyingPrice( sToken=0x3774E825d567125988Fb293e926064B6FAa71DAB ) => ( 999930750000000000000000000000 )
                                      • SErc20Delegator.STATICCALL( )
                                      • SErc20Delegator.STATICCALL( )
                                      • SErc20Delegator.STATICCALL( )
                                      • FiatTokenProxy.STATICCALL( )
                                        • FiatTokenV2_2.DELEGATECALL( )
                                        • FiatTokenProxy.STATICCALL( )
                                          • FiatTokenV2_2.DELEGATECALL( )
                                          • EACAggregatorProxy.STATICCALL( )
                                            • AccessControlledOCR2Aggregator.STATICCALL( )
                                            • EACAggregatorProxy.STATICCALL( )
                                              • AccessControlledOCR2Aggregator.STATICCALL( )
                                              • FiatTokenProxy.STATICCALL( )
                                                • FiatTokenV2_2.DELEGATECALL( )
                                                • SErc20Delegator.STATICCALL( )
                                                • SErc20Delegator.STATICCALL( )
                                                • SErc20Delegator.borrowBalanceStored( account=0x94599741aAda66A4687c4a533f4B91C208B5Db4b ) => ( 1000505329 )
                                                  • SErc20Delegator.delegateToImplementation( data=0x95DD919300000000000000000000000094599741AADA66A4687C4A533F4B91C208B5DB4B ) => ( 0x000000000000000000000000000000000000000000000000000000003BA27FF1 )
                                                    • SErc20Delegate.borrowBalanceStored( account=0x94599741aAda66A4687c4a533f4B91C208B5Db4b ) => ( 1000505329 )
                                                    • FiatTokenProxy.70a08231( )
                                                      • FiatTokenV2_2.balanceOf( account=0x3774E825d567125988Fb293e926064B6FAa71DAB ) => ( 647710547438 )
                                                      • FiatTokenProxy.a9059cbb( )
                                                        • FiatTokenV2_2.transfer( to=0x94599741aAda66A4687c4a533f4B91C208B5Db4b, value=1220474375 ) => ( True )
                                                        • Unitroller.5c778605( )
                                                          • Comptroller.borrowVerify( sToken=0x3774E825d567125988Fb293e926064B6FAa71DAB, borrower=0x94599741aAda66A4687c4a533f4B91C208B5Db4b, borrowAmount=1220474375 )
                                                            File 1 of 14: SErc20Delegator
                                                            1
                                                            {"ComptrollerInterface.sol":{"content":"pragma solidity ^0.5.16;\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 sTokens) external returns (uint[] memory);\n function exitMarket(address sToken) external returns (uint);\n\n
                                                                 /*** Policy Hooks ***/\n\n function mintAllowed(address sToken, address minter, uint mintAmount) external returns (uint);\n function
                                                                mintVerify(address sToken, address minter, uint mintAmount, uint mintTokens) external;\n\n function redeemAllowed(address sToken, address
                                                                redeemer, uint redeemTokens) external returns (uint);\n function redeemVerify(address sToken, address redeemer, uint redeemAmount, uint
                                                                redeemTokens) external;\n\n function borrowAllowed(address sToken, address borrower, uint borrowAmount) external returns (uint);\n function
                                                                borrowVerify(address sToken, address borrower, uint borrowAmount) external;\n\n function repayBorrowAllowed(\n address sToken,\n
                                                                address payer,\n address borrower,\n uint repayAmount) external returns (uint);\n function repayBorrowVerify(\n address
                                                                sToken,\n address payer,\n address borrower,\n uint repayAmount,\n uint borrowerIndex) external;\n\n function
                                                                liquidateBorrowAllowed(\n address sTokenBorrowed,\n address sTokenCollateral,\n address liquidator,\n address borrower
                                                                ,\n uint repayAmount) external returns (uint);\n function liquidateBorrowVerify(\n address sTokenBorrowed,\n address
                                                                sTokenCollateral,\n address liquidator,\n address borrower,\n uint repayAmount,\n uint seizeTokens) external;\n\n
                                                                function seizeAllowed(\n address sTokenCollateral,\n address sTokenBorrowed,\n address liquidator,\n address borrower
                                                                ,\n uint seizeTokens) external returns (uint);\n function seizeVerify(\n address sTokenCollateral,\n address sTokenBorrowed
                                                                ,\n address liquidator,\n address borrower,\n uint seizeTokens) external;\n\n function transferAllowed(address sToken,
                                                                address src, address dst, uint transferTokens) external returns (uint);\n function transferVerify(address sToken, address src, address dst, uint
                                                                transferTokens) external;\n\n /*** Liquidity/Liquidation Calculations ***/\n\n function liquidateCalculateSeizeTokens(\n address
                                                                sTokenBorrowed,\n address sTokenCollateral,\n uint repayAmount) external view returns (uint, uint);\n}\n"},"InterestRateModel.sol"
                                                                :{"content":"pragma solidity ^0.5.16;\n\n/**\n * @title Strike\u0027s InterestRateModel Interface\n * @author Strike\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 amount of
                                                                reserves the market has\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\n */\n function getBorrowRate(uint
                                                                cash, uint borrows, uint reserves) external view returns (uint);\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 amount 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(uint cash, uint borrows,
                                                                uint reserves, uint reserveFactorMantissa) external view returns (uint);\n\n}\n"},"SErc20Delegator.sol":{"content":"pragma solidity ^0.5.16
                                                                ;\n\nimport \"./STokenInterfaces.sol\";\n\n/**\n * @title Strike\u0027s SErc20Delegator Contract\n * @notice STokens which wrap an EIP-20
                                                                underlying and delegate to an implementation\n * @author Strike\n */\ncontract SErc20Delegator is STokenInterface, SErc20Interface,
                                                                SDelegatorInterface {\n /**\n * @notice Construct a new money market\n * @param underlying_ The address of the underlying asset\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 * @param implementation_ The address of the implementation the contract delegates to\n * @param becomeImplementationData The
                                                                encoded args for becomeImplementation\n */\n constructor(address underlying_,\n ComptrollerInterface comptroller_,\n
                                                                 InterestRateModel interestRateModel_,\n uint initialExchangeRateMantissa_,\n string memory name_,\n
                                                                 string memory symbol_,\n uint8 decimals_,\n address payable admin_,\n address implementation_,\n
                                                                 bytes memory becomeImplementationData) public {\n // Creator of the contract is admin during initialization\n admin =
                                                                msg.sender;\n\n // First delegate gets to initialize the delegator (i.e. storage contract)\n delegateTo(implementation_, abi
                                                                .encodeWithSignature(\"initialize(address,address,address,uint256,string,string,uint8)\",\n
                                                                 underlying_,\n comptroller_,\n
                                                                 interestRateModel_,\n initialExchangeRateMantissa_,\n
                                                                 name_,\n symbol_,\n
                                                                 decimals_));\n\n // New implementations always get set via the settor (post-initialize)\n _setImplementation
                                                                (implementation_, false, becomeImplementationData);\n\n // Set the proper admin now that initialization is done\n admin = admin_;\n
                                                                 }\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(address
                                                                implementation_, bool allowResign, bytes memory becomeImplementationData) public {\n require(msg.sender == admin, \"SErc20Delegator
                                                                ::_setImplementation: Caller must be admin\");\n\n if (allowResign) {\n delegateToImplementation(abi.encodeWithSignature
                                                                (\"_resignImplementation()\"));\n }\n\n address oldImplementation = implementation;\n implementation = implementation_;\n\n
                                                                 delegateToImplementation(abi.encodeWithSignature(\"_becomeImplementation(bytes)\", becomeImplementationData));\n\n emit
                                                                NewImplementation(oldImplementation, implementation);\n }\n\n /**\n * @notice Sender supplies assets into the market and receives sTokens
                                                                in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param mintAmount The amount of the
                                                                underlying asset to supply\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function mint(uint
                                                                mintAmount) external returns (uint) {\n mintAmount; // Shh\n delegateAndReturn();\n }\n\n /**\n * @notice Sender redeems
                                                                sTokens in exchange for the underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param
                                                                redeemTokens The number of sTokens to redeem into underlying\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details
                                                                )\n */\n function redeem(uint redeemTokens) external returns (uint) {\n redeemTokens; // Shh\n delegateAndReturn();\n }\n\n
                                                                 /**\n * @notice Sender redeems sTokens 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(uint redeemAmount) external returns (uint) {\n
                                                                redeemAmount; // Shh\n delegateAndReturn();\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(uint borrowAmount) external returns (uint) {\n borrowAmount; // Shh\n
                                                                delegateAndReturn();\n }\n\n /**\n * @notice Sender repays their own borrow\n * @param repayAmount The amount to repay\n *
                                                                @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function repayBorrow(uint repayAmount) external
                                                                returns (uint) {\n repayAmount; // Shh\n delegateAndReturn();\n }\n\n /**\n * @notice Sender repays a borrow belonging to
                                                                borrower\n * @param borrower the account with the debt being payed off\n * @param repayAmount The amount to repay\n * @return uint 0
                                                                =success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function repayBorrowBehalf(address borrower, uint repayAmount)
                                                                external returns (uint) {\n borrower; repayAmount; // Shh\n delegateAndReturn();\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
                                                                sToken to be liquidated\n * @param sTokenCollateral 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 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n
                                                                 function liquidateBorrow(address borrower, uint repayAmount, STokenInterface sTokenCollateral) external returns (uint) {\n borrower;
                                                                repayAmount; sTokenCollateral; // Shh\n delegateAndReturn();\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, uint amount) external returns (bool) {\n dst; amount; // Shh\n
                                                                 delegateAndReturn();\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(address src, address dst, uint256 amount) external returns (bool) {\n src;
                                                                dst; amount; // Shh\n delegateAndReturn();\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 spender; amount; // Shh\n delegateAndReturn();\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 (uint) {\n owner; spender; // Shh\n delegateToViewAndReturn
                                                                ();\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 (uint) {\n owner; // Shh\n
                                                                 delegateToViewAndReturn();\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 (uint) {\n owner; // Shh\n delegateAndReturn();\n }\n\n /**\n
                                                                * @notice Get a snapshot of the account\u0027s 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) external view returns (uint, uint, uint, uint) {\n
                                                                account; // Shh\n delegateToViewAndReturn();\n }\n\n /**\n * @notice Returns the current per-block borrow interest rate for this
                                                                sToken\n * @return The borrow interest rate per block, scaled by 1e18\n */\n function borrowRatePerBlock() external view returns (uint)
                                                                {\n delegateToViewAndReturn();\n }\n\n /**\n * @notice Returns the current per-block supply interest rate for this sToken\n *
                                                                @return The supply interest rate per block, scaled by 1e18\n */\n function supplyRatePerBlock() external view returns (uint) {\n
                                                                delegateToViewAndReturn();\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 returns (uint) {\n delegateAndReturn();\n }\n\n /**\n
                                                                * @notice Accrue interest to updated borrowIndex and then calculate account\u0027s 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 returns (uint) {\n account; // Shh\n delegateAndReturn();\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 (uint) {\n account; // Shh\n
                                                                 delegateToViewAndReturn();\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 returns (uint) {\n delegateAndReturn();\n
                                                                }\n\n /**\n * @notice Calculates the exchange rate from the underlying to the SToken\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 (uint) {\n delegateToViewAndReturn();\n }\n\n /**\n * @notice Get cash balance of this sToken in the underlying
                                                                asset\n * @return The quantity of underlying asset owned by this contract\n */\n function getCash() external view returns (uint) {\n
                                                                 delegateToViewAndReturn();\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 (uint) {\n delegateAndReturn();\n }\n\n /**\n * @notice Transfers collateral
                                                                tokens (this market) to the liquidator.\n * @dev Will fail unless called by another sToken during the process of liquidation.\n * Its
                                                                absolutely critical to use msg.sender as the borrowed sToken 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 sTokens to seize\n * @return
                                                                uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function seize(address liquidator, address borrower, uint
                                                                seizeTokens) external returns (uint) {\n liquidator; borrower; seizeTokens; // Shh\n delegateAndReturn();\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 (uint) {\n newPendingAdmin; // Shh\n delegateAndReturn();\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 (uint) {\n newComptroller; // Shh\n delegateAndReturn();\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(uint
                                                                newReserveFactorMantissa) external returns (uint) {\n newReserveFactorMantissa; // Shh\n delegateAndReturn();\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 (uint) {\n delegateAndReturn();\n }\n\n /**\n * @notice Accrues interest and adds reserves by transferring from
                                                                admin\n * @param addAmount Amount of reserves to add\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n
                                                                 */\n function _addReserves(uint addAmount) external returns (uint) {\n addAmount; // Shh\n delegateAndReturn();\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(uint reduceAmount)
                                                                external returns (uint) {\n reduceAmount; // Shh\n delegateAndReturn();\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 (uint) {\n
                                                                newInterestRateModel; // Shh\n delegateAndReturn();\n }\n\n /**\n * @notice Internal method to delegate execution to another
                                                                contract\n * @dev It returns to the external caller whatever the implementation returns or forwards reverts\n * @param callee The contract
                                                                to delegatecall\n * @param data The raw data to delegatecall\n * @return The returned bytes from the delegatecall\n */\n function
                                                                delegateTo(address callee, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returnData) = callee
                                                                .delegatecall(data);\n assembly {\n if eq(success, 0) {\n revert(add(returnData, 0x20), returndatasize)\n
                                                                 }\n }\n return returnData;\n }\n\n /**\n * @notice Delegates execution to the implementation contract\n * @dev It
                                                                returns to the external caller whatever the implementation returns or forwards reverts\n * @param data The raw data to delegatecall\n *
                                                                @return The returned bytes from the delegatecall\n */\n function delegateToImplementation(bytes memory data) public returns (bytes memory)
                                                                {\n return delegateTo(implementation, data);\n }\n\n /**\n * @notice Delegates execution to an implementation contract\n *
                                                                @dev It returns to the external caller whatever the implementation returns or forwards reverts\n * There are an additional 2 prefix uints from
                                                                the wrapper returndata, which we ignore since we make an extra hop.\n * @param data The raw data to delegatecall\n * @return The returned
                                                                bytes from the delegatecall\n */\n function delegateToViewImplementation(bytes memory data) public view returns (bytes memory) {\n
                                                                (bool success, bytes memory returnData) = address(this).staticcall(abi.encodeWithSignature(\"delegateToImplementation(bytes)\", data));\n
                                                                assembly {\n if eq(success, 0) {\n revert(add(returnData, 0x20), returndatasize)\n }\n }\n
                                                                return abi.decode(returnData, (bytes));\n }\n\n function delegateToViewAndReturn() private view returns (bytes memory) {\n (bool
                                                                success, ) = address(this).staticcall(abi.encodeWithSignature(\"delegateToImplementation(bytes)\", msg.data));\n\n assembly {\n
                                                                let free_mem_ptr := mload(0x40)\n returndatacopy(free_mem_ptr, 0, returndatasize)\n\n switch success\n case 0 {
                                                                revert(free_mem_ptr, returndatasize) }\n default { return(add(free_mem_ptr, 0x40), returndatasize) }\n }\n }\n\n function
                                                                delegateAndReturn() private returns (bytes memory) {\n (bool success, ) = implementation.delegatecall(msg.data);\n\n assembly {\n
                                                                 let free_mem_ptr := mload(0x40)\n returndatacopy(free_mem_ptr, 0, returndatasize)\n\n switch success\n
                                                                case 0 { revert(free_mem_ptr, returndatasize) }\n default { return(free_mem_ptr, returndatasize) }\n }\n }\n\n /**\n *
                                                                @notice Delegates execution to an implementation contract\n * @dev It returns to the external caller whatever the implementation returns or
                                                                forwards reverts\n */\n function () external payable {\n require(msg.value == 0,\"SErc20Delegator:fallback: cannot send value to
                                                                fallback\");\n\n // delegate all other functions to current implementation\n delegateAndReturn();\n }\n}\n"},"STokenInterfaces
                                                                .sol":{"content":"pragma solidity ^0.5.16;\n\nimport \"./ComptrollerInterface.sol\";\nimport \"./InterestRateModel.sol\";\n\ncontract STokenStorage
                                                                {\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 uint internal constant borrowRateMaxMantissa = 0.0005e16;\n\n /**\n * @notice
                                                                Maximum fraction of interest that can be set aside for reserves\n */\n uint 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-sToken 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 STokens (used when
                                                                totalSupply = 0)\n */\n uint internal initialExchangeRateMantissa;\n\n /**\n * @notice Fraction of interest currently set aside for
                                                                reserves\n */\n uint public reserveFactorMantissa;\n\n /**\n * @notice Block number that interest was last accrued at\n */\n
                                                                uint public accrualBlockNumber;\n\n /**\n * @notice Accumulator of the total earned interest rate since the opening of the market\n */\n
                                                                 uint public borrowIndex;\n\n /**\n * @notice Total amount of outstanding borrows of the underlying in this market\n */\n uint
                                                                public totalBorrows;\n\n /**\n * @notice Total amount of reserves of the underlying held in this market\n */\n uint public
                                                                totalReserves;\n\n /**\n * @notice Total number of tokens in circulation\n */\n uint public totalSupply;\n\n /**\n * @notice
                                                                Official record of token balances for each account\n */\n mapping (address =\u003e uint) internal accountTokens;\n\n /**\n * @notice
                                                                Approved token transfer amounts on behalf of others\n */\n mapping (address =\u003e mapping (address =\u003e uint)) 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 uint principal;\n uint interestIndex;\n }\n\n /**\n * @notice
                                                                Mapping of account addresses to outstanding borrow balances\n */\n mapping(address =\u003e BorrowSnapshot) internal accountBorrows
                                                                ;\n}\n\ncontract STokenInterface is STokenStorage {\n /**\n * @notice Indicator that this is a SToken contract (for inspection)\n */\n
                                                                 bool public constant isSToken = true;\n\n\n /*** Market Events ***/\n\n /**\n * @notice Event emitted when interest is accrued\n
                                                                */\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\n\n /**\n * @notice Event
                                                                emitted when tokens are minted\n */\n event Mint(address minter, uint mintAmount, uint mintTokens);\n\n /**\n * @notice Event emitted
                                                                when tokens are redeemed\n */\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens);\n\n /**\n * @notice Event
                                                                emitted when underlying is borrowed\n */\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\n\n
                                                                 /**\n * @notice Event emitted when a borrow is repaid\n */\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint
                                                                accountBorrows, uint totalBorrows);\n\n /**\n * @notice Event emitted when a borrow is liquidated\n */\n event LiquidateBorrow
                                                                (address liquidator, address borrower, uint repayAmount, address sTokenCollateral, uint 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(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\n\n
                                                                 /**\n * @notice Event emitted when the reserves are added\n */\n event ReservesAdded(address benefactor, uint addAmount, uint
                                                                newTotalReserves);\n\n /**\n * @notice Event emitted when the reserves are reduced\n */\n event ReservesReduced(address admin, uint
                                                                reduceAmount, uint newTotalReserves);\n\n /**\n * @notice EIP20 Transfer event\n */\n event Transfer(address indexed from, address
                                                                indexed to, uint amount);\n\n /**\n * @notice EIP20 Approval event\n */\n event Approval(address indexed owner, address indexed
                                                                spender, uint amount);\n\n /**\n * @notice Failure event\n */\n event Failure(uint error, uint info, uint detail);\n\n\n /*** User
                                                                Interface ***/\n\n function transfer(address dst, uint amount) external returns (bool);\n function transferFrom(address src, address dst,
                                                                uint amount) external returns (bool);\n function approve(address spender, uint amount) external returns (bool);\n function allowance(address
                                                                owner, address spender) external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n function
                                                                balanceOfUnderlying(address owner) external returns (uint);\n function getAccountSnapshot(address account) external view returns (uint, uint,
                                                                uint, uint);\n function borrowRatePerBlock() external view returns (uint);\n function supplyRatePerBlock() external view returns (uint);\n
                                                                 function totalBorrowsCurrent() external returns (uint);\n function borrowBalanceCurrent(address account) external returns (uint);\n function
                                                                borrowBalanceStored(address account) public view returns (uint);\n function exchangeRateCurrent() public returns (uint);\n function
                                                                exchangeRateStored() public view returns (uint);\n function getCash() external view returns (uint);\n function accrueInterest() public
                                                                returns (uint);\n function seize(address liquidator, address borrower, uint seizeTokens) external returns (uint);\n\n\n /*** Admin Functions
                                                                ***/\n\n function _setPendingAdmin(address payable newPendingAdmin) external returns (uint);\n function _acceptAdmin() external returns (uint
                                                                );\n function _setComptroller(ComptrollerInterface newComptroller) public returns (uint);\n function _setReserveFactor(uint
                                                                newReserveFactorMantissa) external returns (uint);\n function _reduceReserves(uint reduceAmount) external returns (uint);\n function
                                                                _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint);\n}\n\ncontract SErc20Storage {\n /**\n * @notice
                                                                Underlying asset for this SToken\n */\n address public underlying;\n}\n\ncontract SErc20Interface is SErc20Storage {\n\n /*** User
                                                                Interface ***/\n\n function mint(uint mintAmount) external returns (uint);\n function redeem(uint redeemTokens) external returns (uint);\n
                                                                 function redeemUnderlying(uint redeemAmount) external returns (uint);\n function borrow(uint borrowAmount) external returns (uint);\n
                                                                function repayBorrow(uint repayAmount) external returns (uint);\n function repayBorrowBehalf(address borrower, uint repayAmount) external
                                                                returns (uint);\n function liquidateBorrow(address borrower, uint repayAmount, STokenInterface sTokenCollateral) external returns (uint);\n\n\n
                                                                 /*** Admin Functions ***/\n\n function _addReserves(uint addAmount) external returns (uint);\n}\n\ncontract SDelegationStorage {\n /**\n
                                                                 * @notice Implementation address for this contract\n */\n address public implementation;\n}\n\ncontract SDelegatorInterface is
                                                                SDelegationStorage {\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(address implementation_, bool allowResign, bytes memory becomeImplementationData)
                                                                public;\n}\n\ncontract SDelegateInterface is SDelegationStorage {\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"}}
                                                            XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

                                                            File 2 of 14: Unitroller
                                                            1
                                                            {"CarefulMath.sol":{"content":"pragma solidity ^0.5.16;\n\n/**\n * @title Careful Math\n * @author Strike\n * @notice Derived from
                                                                OpenZeppelin\u0027s SafeMath library\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\n
                                                                */\ncontract CarefulMath {\n\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(uint a, uint b) internal pure returns (MathError, uint) {\n if (a == 0) {\n return
                                                                (MathError.NO_ERROR, 0);\n }\n\n uint 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(uint a, uint b) internal pure returns (MathError, uint) {\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(uint a, uint b) internal pure returns
                                                                (MathError, uint) {\n if (b \u003c= 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(uint
                                                                a, uint b) internal pure returns (MathError, uint) {\n uint c = a + b;\n\n if (c \u003e= 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(uint a, uint b, uint c) internal pure returns (MathError, uint) {\n (MathError err0, uint sum) =
                                                                addUInt(a, b);\n\n if (err0 != MathError.NO_ERROR) {\n return (err0, 0);\n }\n\n return subUInt(sum, c);\n
                                                                }\n}"},"ComptrollerInterface.sol":{"content":"pragma solidity ^0.5.16;\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 sTokens) external returns (uint[] memory);\n function exitMarket(address sToken) external returns (uint);\n\n
                                                                 /*** Policy Hooks ***/\n\n function mintAllowed(address sToken, address minter, uint mintAmount) external returns (uint);\n function
                                                                mintVerify(address sToken, address minter, uint mintAmount, uint mintTokens) external;\n\n function redeemAllowed(address sToken, address
                                                                redeemer, uint redeemTokens) external returns (uint);\n function redeemVerify(address sToken, address redeemer, uint redeemAmount, uint
                                                                redeemTokens) external;\n\n function borrowAllowed(address sToken, address borrower, uint borrowAmount) external returns (uint);\n function
                                                                borrowVerify(address sToken, address borrower, uint borrowAmount) external;\n\n function repayBorrowAllowed(\n address sToken,\n
                                                                address payer,\n address borrower,\n uint repayAmount) external returns (uint);\n function repayBorrowVerify(\n address
                                                                sToken,\n address payer,\n address borrower,\n uint repayAmount,\n uint borrowerIndex) external;\n\n function
                                                                liquidateBorrowAllowed(\n address sTokenBorrowed,\n address sTokenCollateral,\n address liquidator,\n address borrower
                                                                ,\n uint repayAmount) external returns (uint);\n function liquidateBorrowVerify(\n address sTokenBorrowed,\n address
                                                                sTokenCollateral,\n address liquidator,\n address borrower,\n uint repayAmount,\n uint seizeTokens) external;\n\n
                                                                function seizeAllowed(\n address sTokenCollateral,\n address sTokenBorrowed,\n address liquidator,\n address borrower
                                                                ,\n uint seizeTokens) external returns (uint);\n function seizeVerify(\n address sTokenCollateral,\n address sTokenBorrowed
                                                                ,\n address liquidator,\n address borrower,\n uint seizeTokens) external;\n\n function transferAllowed(address sToken,
                                                                address src, address dst, uint transferTokens) external returns (uint);\n function transferVerify(address sToken, address src, address dst, uint
                                                                transferTokens) external;\n\n /*** Liquidity/Liquidation Calculations ***/\n\n function liquidateCalculateSeizeTokens(\n address
                                                                sTokenBorrowed,\n address sTokenCollateral,\n uint repayAmount) external view returns (uint, uint);\n}\n"},"ComptrollerStorage.sol"
                                                                :{"content":"pragma solidity ^0.5.16;\n\nimport \"./SToken.sol\";\nimport \"./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 /**\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
                                                                uint public closeFactorMantissa;\n\n /**\n * @notice Multiplier representing the discount on collateral that a liquidator receives\n
                                                                */\n uint public liquidationIncentiveMantissa;\n\n /**\n * @notice Max number of assets a single account can participate in (borrow or
                                                                use as collateral)\n */\n uint public maxAssets;\n\n /**\n * @notice Per-account mapping of \"assets you are in\", capped by
                                                                maxAssets\n */\n mapping(address =\u003e SToken[]) public accountAssets;\n\n}\n\ncontract ComptrollerV2Storage is ComptrollerV1Storage {\n
                                                                 struct Market {\n /// @notice Whether or not this market is listed\n bool isListed;\n\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 uint collateralFactorMantissa;\n\n /// @notice
                                                                Per-market mapping of \"accounts in this asset\"\n mapping(address =\u003e bool) accountMembership;\n\n /// @notice Whether or not
                                                                this market receives STRK\n bool isStriked;\n }\n\n /**\n * @notice Official mapping of sTokens -\u003e Market metadata\n *
                                                                @dev Used e.g. to determine if a market is supported\n */\n mapping(address =\u003e Market) public markets;\n\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 =\u003e bool) public mintGuardianPaused;\n mapping(address =\u003e bool) public borrowGuardianPaused;\n}\n\ncontract
                                                                ComptrollerV3Storage is ComptrollerV2Storage {\n struct StrikeMarketState {\n /// @notice The market\u0027s last updated
                                                                strikeBorrowIndex or strikeSupplyIndex\n uint224 index;\n\n /// @notice The block number the index was last updated at\n
                                                                uint32 block;\n }\n\n /// @notice A list of all markets\n SToken[] public allMarkets;\n\n /// @notice The rate at which the flywheel
                                                                distributes STRK, per block\n uint public strikeRate;\n\n /// @notice The portion of strikeRate that each market currently receives\n
                                                                mapping(address =\u003e uint) public strikeSpeeds;\n\n /// @notice The STRK market supply state for each market\n mapping(address =\u003e
                                                                StrikeMarketState) public strikeSupplyState;\n\n /// @notice The STRK market borrow state for each market\n mapping(address =\u003e
                                                                StrikeMarketState) public strikeBorrowState;\n\n /// @notice The STRK borrow index for each market for each supplier as of the last time they
                                                                accrued STRK\n mapping(address =\u003e mapping(address =\u003e uint)) public strikeSupplierIndex;\n\n /// @notice The STRK borrow index for
                                                                each market for each borrower as of the last time they accrued STRK\n mapping(address =\u003e mapping(address =\u003e uint)) public
                                                                strikeBorrowerIndex;\n\n /// @notice The STRK accrued but not yet transferred to each user\n mapping(address =\u003e uint) public
                                                                strikeAccrued;\n}\n\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\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 sToken address. Defaults to zero which corresponds to unlimited borrowing.\n mapping(address
                                                                =\u003e uint) public borrowCaps;\n}\n"},"EIP20Interface.sol":{"content":"pragma 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
                                                                 function symbol() external view returns (string memory);\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(address src, address dst, uint256 amount) 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"},"EIP20NonStandardInterface.sol":{"content":"pragma 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 /**\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(address src, address dst, uint256 amount) 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"},"ErrorReporter.sol":{"content":"pragma 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(uint error, uint info, uint 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 (uint) {\n emit Failure(uint(err),
                                                                uint(info), 0);\n\n return uint(err);\n }\n\n /**\n * @dev use this when reporting an opaque error from an upgradeable
                                                                collaborator contract\n */\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\n emit
                                                                Failure(uint(err), uint(info), opaqueError);\n\n return uint(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_ACCUMULATED_INTEREST_CALCULATION_FAILED,\n
                                                                ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\n
                                                                ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\n
                                                                ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\n
                                                                BORROW_ACCRUE_INTEREST_FAILED,\n BORROW_CASH_NOT_AVAILABLE,\n BORROW_FRESHNESS_CHECK,\n
                                                                BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\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_BALANCE_INCREMENT_FAILED,\n
                                                                LIQUIDATE_SEIZE_BALANCE_DECREMENT_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_EXCHANGE_CALCULATION_FAILED,\n
                                                                 MINT_EXCHANGE_RATE_READ_FAILED,\n MINT_FRESHNESS_CHECK,\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\n
                                                                MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\n MINT_TRANSFER_IN_FAILED,\n MINT_TRANSFER_IN_NOT_POSSIBLE,\n
                                                                REDEEM_ACCRUE_INTEREST_FAILED,\n REDEEM_COMPTROLLER_REJECTION,\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\n
                                                                REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\n REDEEM_EXCHANGE_RATE_READ_FAILED,\n REDEEM_FRESHNESS_CHECK,\n
                                                                REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\n
                                                                 REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\n REDUCE_RESERVES_ADMIN_CHECK,\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\n
                                                                REDUCE_RESERVES_FRESH_CHECK,\n REDUCE_RESERVES_VALIDATION,\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\n
                                                                REPAY_BORROW_ACCRUE_INTEREST_FAILED,\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\n REPAY_BORROW_COMPTROLLER_REJECTION,\n
                                                                 REPAY_BORROW_FRESHNESS_CHECK,\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\n
                                                                REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\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 TRANSFER_NOT_ENOUGH,\n TRANSFER_TOO_MUCH,\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(uint error, uint info, uint 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 (uint) {\n emit Failure(uint(err), uint(info), 0);\n\n return uint(err);\n }\n\n /**\n
                                                                * @dev use this when reporting an opaque error from an upgradeable collaborator contract\n */\n function failOpaque(Error err, FailureInfo
                                                                info, uint opaqueError) internal returns (uint) {\n emit Failure(uint(err), uint(info), opaqueError);\n\n return uint(err);\n
                                                                }\n}"},"Exponential.sol":{"content":"pragma solidity ^0.5.16;\n\nimport \"./CarefulMath.sol\";\n\n/**\n * @title Exponential module for storing
                                                                fixed-precision decimals\n * @author Strike\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 uint constant expScale = 1e18;\n uint constant doubleScale = 1e36;\n uint constant halfExpScale = expScale
                                                                /2;\n uint constant mantissaOne = expScale;\n\n struct Exp {\n uint mantissa;\n }\n\n struct Double {\n uint mantissa;\n
                                                                 }\n\n /**\n * @dev Creates an exponential from numerator and denominator values.\n * Note: Returns an error if (`num` * 10e18)
                                                                \u003e MAX_INT,\n * or if `denom` is zero.\n */\n function getExp(uint num, uint denom) internal pure returns (MathError, Exp
                                                                memory) {\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\n if (err0 != MathError.NO_ERROR) {\n return
                                                                (err0, Exp({mantissa: 0}));\n }\n\n (MathError err1, uint 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, uint 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, uint 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, uint scalar) internal pure returns (MathError, Exp memory) {\n (MathError err0, uint 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, uint scalar) internal pure returns (MathError, uint) {\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(Exp memory a, uint scalar, uint addend) internal
                                                                pure returns (MathError, uint) {\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 Divide an Exp by a
                                                                scalar, returning a new Exp.\n */\n function divScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\n
                                                                (MathError err0, uint 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(uint 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, uint 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(uint scalar, Exp memory divisor) internal pure returns
                                                                (MathError, uint) {\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 Multiplies two
                                                                exponentials, returning a new exponential.\n */\n function mulExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory)
                                                                {\n\n (MathError err0, uint 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, uint doubleScaledProductWithHalfScale) = addUInt
                                                                (halfExpScale, doubleScaledProduct);\n if (err1 != MathError.NO_ERROR) {\n return (err1, Exp({mantissa: 0}));\n }\n\n
                                                                 (MathError err2, uint 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(uint a, uint 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(Exp memory a, Exp
                                                                memory b, Exp memory c) 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 (uint) {\n //
                                                                Note: We are not using careful math here as we\u0027re 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 \u003c right.mantissa;\n }\n\n /**\n * @dev Checks if left Exp \u003c= right Exp.\n
                                                                */\n function lessThanOrEqualExp(Exp memory left, Exp memory right) internal pure returns (bool) {\n return left.mantissa \u003c= right
                                                                .mantissa;\n }\n\n /**\n * @dev Checks if left Exp \u003e right Exp.\n */\n function greaterThanExp(Exp memory left, Exp memory
                                                                right) internal pure returns (bool) {\n return left.mantissa \u003e 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(uint n, string memory errorMessage) internal pure returns (uint224) {\n require(n \u003c 2**224, errorMessage);\n
                                                                return uint224(n);\n }\n\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\n require(n \u003c 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_(uint a, uint b) internal pure
                                                                returns (uint) {\n return add_(a, b, \"addition overflow\");\n }\n\n function add_(uint a, uint b, string memory errorMessage)
                                                                internal pure returns (uint) {\n uint c = a + b;\n require(c \u003e= 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_(uint a, uint b) internal pure returns (uint) {\n return sub_(a, b, \"subtraction underflow\");\n
                                                                 }\n\n function sub_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\n require(b \u003c= 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, uint b) internal pure returns (Exp memory) {\n return
                                                                Exp({mantissa: mul_(a.mantissa, b)});\n }\n\n function mul_(uint a, Exp memory b) internal pure returns (uint) {\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, uint b) internal pure returns (Double memory
                                                                ) {\n return Double({mantissa: mul_(a.mantissa, b)});\n }\n\n function mul_(uint a, Double memory b) internal pure returns (uint) {\n
                                                                 return mul_(a, b.mantissa) / doubleScale;\n }\n\n function mul_(uint a, uint b) internal pure returns (uint) {\n return mul_(a,
                                                                b, \"multiplication overflow\");\n }\n\n function mul_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\n if
                                                                (a == 0 || b == 0) {\n return 0;\n }\n uint 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, uint b) internal pure returns (Exp memory) {\n return Exp({mantissa:
                                                                div_(a.mantissa, b)});\n }\n\n function div_(uint a, Exp memory b) internal pure returns (uint) {\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, uint b) internal pure returns (Double memory) {\n
                                                                 return Double({mantissa: div_(a.mantissa, b)});\n }\n\n function div_(uint a, Double memory b) internal pure returns (uint) {\n
                                                                return div_(mul_(a, doubleScale), b.mantissa);\n }\n\n function div_(uint a, uint b) internal pure returns (uint) {\n return div_(a, b
                                                                , \"divide by zero\");\n }\n\n function div_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\n require(b
                                                                \u003e 0, errorMessage);\n return a / b;\n }\n\n function fraction(uint a, uint b) internal pure returns (Double memory) {\n
                                                                return Double({mantissa: div_(mul_(a, doubleScale), b)});\n }\n}\n"},"InterestRateModel.sol":{"content":"pragma solidity ^0.5.16;\n\n/**\n *
                                                                @title Strike\u0027s InterestRateModel Interface\n * @author Strike\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 amount of reserves the market has\n * @return The borrow rate per block
                                                                (as a percentage, and scaled by 1e18)\n */\n function getBorrowRate(uint cash, uint borrows, uint reserves) external view returns (uint
                                                                );\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 amount 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(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) external view returns
                                                                (uint);\n\n}\n"},"PriceOracle.sol":{"content":"pragma solidity ^0.5.16;\n\nimport \"./SToken.sol\";\n\ncontract PriceOracle {\n /// @notice
                                                                Indicator that this is a PriceOracle contract (for inspection)\n bool public constant isPriceOracle = true;\n\n /**\n * @notice Get the
                                                                underlying price of a sToken asset\n * @param sToken The sToken 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(SToken sToken) external view
                                                                returns (uint);\n}\n"},"SToken.sol":{"content":"pragma solidity ^0.5.16;\n\nimport \"./ComptrollerInterface.sol\";\nimport \"./STokenInterfaces
                                                                .sol\";\nimport \"./ErrorReporter.sol\";\nimport \"./Exponential.sol\";\nimport \"./EIP20Interface.sol\";\nimport \"./EIP20NonStandardInterface
                                                                .sol\";\nimport \"./InterestRateModel.sol\";\n\n/**\n * @title Strike\u0027s SToken Contract\n * @notice Abstract base for STokens\n * @author
                                                                Strike\n */\ncontract SToken is STokenInterface, 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(ComptrollerInterface
                                                                comptroller_,\n InterestRateModel interestRateModel_,\n uint initialExchangeRateMantissa_,\n
                                                                 string memory name_,\n string memory symbol_,\n uint8 decimals_) public {\n
                                                                require(msg.sender == admin, \"only admin may initialize the market\");\n require(accrualBlockNumber == 0 \u0026\u0026 borrowIndex == 0,
                                                                \"market may only be initialized once\");\n\n // Set initial exchange rate\n initialExchangeRateMantissa =
                                                                initialExchangeRateMantissa_;\n require(initialExchangeRateMantissa \u003e 0, \"initial exchange rate must be greater than zero.\");\n\n
                                                                 // Set the comptroller\n uint err = _setComptroller(comptroller_);\n require(err == uint(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 == uint(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(address
                                                                spender, address src, address dst, uint tokens) internal returns (uint) {\n /* Fail if transfer not allowed */\n uint 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 uint startingAllowance = 0;\n if (spender == src) {\n startingAllowance = uint(-1);\n }
                                                                else {\n startingAllowance = transferAllowances[src][spender];\n }\n\n /* Do the calculations, checking for {under
                                                                ,over}flow */\n MathError mathErr;\n uint allowanceNew;\n uint srsTokensNew;\n uint dstTokensNew;\n\n (mathErr,
                                                                allowanceNew) = subUInt(startingAllowance, tokens);\n if (mathErr != MathError.NO_ERROR) {\n return fail(Error.MATH_ERROR,
                                                                FailureInfo.TRANSFER_NOT_ALLOWED);\n }\n\n (mathErr, srsTokensNew) = subUInt(accountTokens[src], tokens);\n if (mathErr !=
                                                                MathError.NO_ERROR) {\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ENOUGH);\n }\n\n (mathErr, dstTokensNew) =
                                                                addUInt(accountTokens[dst], tokens);\n if (mathErr != MathError.NO_ERROR) {\n return fail(Error.MATH_ERROR, FailureInfo
                                                                .TRANSFER_TOO_MUCH);\n }\n\n /////////////////////////\n // EFFECTS \u0026 INTERACTIONS\n // (No safe failures beyond
                                                                this point)\n\n accountTokens[src] = srsTokensNew;\n accountTokens[dst] = dstTokensNew;\n\n /* Eat some of the allowance (if
                                                                necessary) */\n if (startingAllowance != uint(-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 uint(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) == uint(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(address src, address dst, uint256 amount)
                                                                external nonReentrant returns (bool) {\n return transferTokens(msg.sender, src, dst, amount) == uint(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 (uint) {\n Exp memory exchangeRate = Exp({mantissa: exchangeRateCurrent()});\n
                                                                 (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\n require(mErr == MathError.NO_ERROR,
                                                                \"balance could not be calculated\");\n return balance;\n }\n\n /**\n * @notice Get a snapshot of the account\u0027s 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) external view returns (uint, uint, uint, uint) {\n uint sTokenBalance = accountTokens[account];\n
                                                                 uint borrowBalance;\n uint exchangeRateMantissa;\n\n MathError mErr;\n\n (mErr, borrowBalance) = borrowBalanceStoredInternal
                                                                (account);\n if (mErr != MathError.NO_ERROR) {\n return (uint(Error.MATH_ERROR), 0, 0, 0);\n }\n\n (mErr,
                                                                exchangeRateMantissa) = exchangeRateStoredInternal();\n if (mErr != MathError.NO_ERROR) {\n return (uint(Error.MATH_ERROR), 0, 0,
                                                                0);\n }\n\n return (uint(Error.NO_ERROR), sTokenBalance, 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 (uint) {\n return block.number;\n }\n\n /**\n * @notice Returns the current per-block
                                                                borrow interest rate for this sToken\n * @return The borrow interest rate per block, scaled by 1e18\n */\n function borrowRatePerBlock()
                                                                external view returns (uint) {\n return interestRateModel.getBorrowRate(getCashPrior(), totalBorrows, totalReserves);\n }\n\n /**\n
                                                                 * @notice Returns the current per-block supply interest rate for this sToken\n * @return The supply interest rate per block, scaled by 1e18\n
                                                                 */\n function supplyRatePerBlock() external view returns (uint) {\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 (uint) {\n require
                                                                (accrueInterest() == uint(Error.NO_ERROR), \"accrue interest failed\");\n return totalBorrows;\n }\n\n /**\n * @notice Accrue
                                                                interest to updated borrowIndex and then calculate account\u0027s 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 (uint) {\n require(accrueInterest() == uint(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 (uint) {\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\n require(err
                                                                == MathError.NO_ERROR, \"borrowBalanceStored: borrowBalanceStoredInternal failed\");\n return result;\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
                                                                (error code, the calculated balance or 0 if error code is non-zero)\n */\n function borrowBalanceStoredInternal(address account) internal
                                                                view returns (MathError, uint) {\n /* Note: we do not assert that the market is up to date */\n MathError mathErr;\n uint
                                                                principalTimesIndex;\n uint result;\n\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 (MathError
                                                                .NO_ERROR, 0);\n }\n\n /* Calculate new borrow balance using the interest index:\n * recentBorrowBalance = borrower
                                                                .borrowBalance * market.borrowIndex / borrower.borrowIndex\n */\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal,
                                                                borrowIndex);\n if (mathErr != MathError.NO_ERROR) {\n return (mathErr, 0);\n }\n\n (mathErr, result) = divUInt
                                                                (principalTimesIndex, borrowSnapshot.interestIndex);\n if (mathErr != MathError.NO_ERROR) {\n return (mathErr, 0);\n }\n\n
                                                                 return (MathError.NO_ERROR, 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 (uint) {\n require
                                                                (accrueInterest() == uint(Error.NO_ERROR), \"accrue interest failed\");\n return exchangeRateStored();\n }\n\n /**\n * @notice
                                                                Calculates the exchange rate from the underlying to the SToken\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 (uint) {\n
                                                                (MathError err, uint result) = exchangeRateStoredInternal();\n require(err == MathError.NO_ERROR, \"exchangeRateStored:
                                                                exchangeRateStoredInternal failed\");\n return result;\n }\n\n /**\n * @notice Calculates the exchange rate from the underlying to
                                                                the SToken\n * @dev This function does not accrue interest before calculating the exchange rate\n * @return (error code, calculated
                                                                exchange rate scaled by 1e18)\n */\n function exchangeRateStoredInternal() internal view returns (MathError, uint) {\n uint
                                                                _totalSupply = totalSupply;\n if (_totalSupply == 0) {\n /*\n * If there are no tokens minted:\n *
                                                                exchangeRate = initialExchangeRate\n */\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\n } else {\n
                                                                 /*\n * Otherwise:\n * exchangeRate = (totalCash + totalBorrows - totalReserves) / totalSupply\n */\n
                                                                 uint totalCash = getCashPrior();\n uint cashPlusBorrowsMinusReserves;\n Exp memory exchangeRate;\n
                                                                MathError mathErr;\n\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\n if
                                                                (mathErr != MathError.NO_ERROR) {\n return (mathErr, 0);\n }\n\n (mathErr, exchangeRate) = getExp
                                                                (cashPlusBorrowsMinusReserves, _totalSupply);\n if (mathErr != MathError.NO_ERROR) {\n return (mathErr, 0);\n
                                                                }\n\n return (MathError.NO_ERROR, exchangeRate.mantissa);\n }\n }\n\n /**\n * @notice Get cash balance of this sToken
                                                                in the underlying asset\n * @return The quantity of underlying asset owned by this contract\n */\n function getCash() external view
                                                                returns (uint) {\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 (uint) {\n /* Remember the initial block number */\n uint currentBlockNumber =
                                                                getBlockNumber();\n uint accrualBlockNumberPrior = accrualBlockNumber;\n\n /* Short-circuit accumulating 0 interest */\n if
                                                                (accrualBlockNumberPrior == currentBlockNumber) {\n return uint(Error.NO_ERROR);\n }\n\n /* Read the previous values out
                                                                of storage */\n uint cashPrior = getCashPrior();\n uint borrowsPrior = totalBorrows;\n uint reservesPrior = totalReserves;\n
                                                                 uint borrowIndexPrior = borrowIndex;\n\n /* Calculate the current borrow interest rate */\n uint borrowRateMantissa =
                                                                interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\n require(borrowRateMantissa \u003c= borrowRateMaxMantissa,
                                                                \"borrow rate is absurdly high\");\n\n /* Calculate the number of blocks elapsed since the last accrual */\n (MathError mathErr, uint
                                                                blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\n require(mathErr == MathError.NO_ERROR, \"could not calculate block
                                                                delta\");\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;\n uint
                                                                interestAccumulated;\n uint totalBorrowsNew;\n uint totalReservesNew;\n uint borrowIndexNew;\n\n (mathErr,
                                                                simpleInterestFactor) = mulScalar(Exp({mantissa: borrowRateMantissa}), blockDelta);\n if (mathErr != MathError.NO_ERROR) {\n
                                                                return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED, uint(mathErr));\n }\n\n
                                                                (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\n if (mathErr != MathError.NO_ERROR) {\n
                                                                return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED, uint(mathErr));\n }\n\n
                                                                (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\n if (mathErr != MathError.NO_ERROR) {\n return
                                                                failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED, uint(mathErr));\n }\n\n (mathErr,
                                                                totalReservesNew) = mulScalarTruncateAddUInt(Exp({mantissa: reserveFactorMantissa}), interestAccumulated, reservesPrior);\n if (mathErr !=
                                                                MathError.NO_ERROR) {\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED, uint
                                                                (mathErr));\n }\n\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\n
                                                                 if (mathErr != MathError.NO_ERROR) {\n return failOpaque(Error.MATH_ERROR, FailureInfo
                                                                .ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED, uint(mathErr));\n }\n\n /////////////////////////\n // EFFECTS \u0026
                                                                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 uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Sender supplies assets into the market and receives
                                                                sTokens 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(uint mintAmount) internal nonReentrant returns (uint, uint) {\n uint error = accrueInterest
                                                                ();\n if (error != uint(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\u0027t need to\n return mintFresh(msg.sender, mintAmount);\n
                                                                }\n\n struct MintLocalVars {\n Error err;\n MathError mathErr;\n uint exchangeRateMantissa;\n uint mintTokens;\n
                                                                 uint totalSupplyNew;\n uint accountTokensNew;\n uint actualMintAmount;\n }\n\n /**\n * @notice User supplies assets
                                                                into the market and receives sTokens 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, uint mintAmount) internal returns (uint, uint) {\n /* Fail if mint not allowed */\n uint 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\u0027s 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.mathErr, vars.exchangeRateMantissa) =
                                                                exchangeRateStoredInternal();\n if (vars.mathErr != MathError.NO_ERROR) {\n return (failOpaque(Error.MATH_ERROR, FailureInfo
                                                                .MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\n }\n\n /////////////////////////\n // EFFECTS \u0026 INTERACTIONS\n
                                                                 // (No safe failures beyond this point)\n\n /*\n * We call `doTransferIn` for the minter and the mintAmount.\n *
                                                                Note: The sToken must handle variations between ERC-20 and ETH underlying.\n * `doTransferIn` reverts if anything goes wrong, since we
                                                                can\u0027t be sure if\n * side-effects occurred. The function returns the amount actually transferred,\n * in case of a fee. On
                                                                success, the sToken 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 sTokens to be minted:\n * mintTokens =
                                                                actualMintAmount / exchangeRate\n */\n\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(vars.actualMintAmount, Exp
                                                                ({mantissa: vars.exchangeRateMantissa}));\n require(vars.mathErr == MathError.NO_ERROR, \"MINT_EXCHANGE_CALCULATION_FAILED\");\n\n
                                                                /*\n * We calculate the new total supply of sTokens and minter token balance, checking for overflow:\n * totalSupplyNew =
                                                                totalSupply + mintTokens\n * accountTokensNew = accountTokens[minter] + mintTokens\n */\n (vars.mathErr, vars
                                                                .totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\n require(vars.mathErr == MathError.NO_ERROR,
                                                                \"MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED\");\n\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens
                                                                );\n require(vars.mathErr == MathError.NO_ERROR, \"MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\");\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 (uint(Error.NO_ERROR), vars.actualMintAmount);\n }\n\n /**\n * @notice Sender
                                                                redeems sTokens in exchange for the underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n *
                                                                @param redeemTokens The number of sTokens to redeem into underlying\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for
                                                                details)\n */\n function redeemInternal(uint redeemTokens) internal nonReentrant returns (uint) {\n uint error = accrueInterest();\n
                                                                 if (error != uint(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\u0027t need to\n return redeemFresh(msg.sender, redeemTokens, 0);\n }\n\n /**\n *
                                                                @notice Sender redeems sTokens 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 sTokens\n * @return uint 0=success,
                                                                otherwise a failure (see ErrorReporter.sol for details)\n */\n function redeemUnderlyingInternal(uint redeemAmount) internal nonReentrant
                                                                returns (uint) {\n uint error = accrueInterest();\n if (error != uint(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\u0027t need to\n return
                                                                redeemFresh(msg.sender, 0, redeemAmount);\n }\n\n struct RedeemLocalVars {\n Error err;\n MathError mathErr;\n uint
                                                                exchangeRateMantissa;\n uint redeemTokens;\n uint redeemAmount;\n uint totalSupplyNew;\n uint accountTokensNew;\n
                                                                }\n\n /**\n * @notice User redeems sTokens 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
                                                                sTokens 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 sTokens (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(address payable redeemer, uint redeemTokensIn, uint
                                                                redeemAmountIn) internal returns (uint) {\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.mathErr, vars
                                                                .exchangeRateMantissa) = exchangeRateStoredInternal();\n if (vars.mathErr != MathError.NO_ERROR) {\n return failOpaque(Error
                                                                .MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr));\n }\n\n /* If redeemTokensIn \u003e 0: */\n if
                                                                (redeemTokensIn \u003e 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\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(Exp({mantissa: vars.exchangeRateMantissa}),
                                                                redeemTokensIn);\n if (vars.mathErr != MathError.NO_ERROR) {\n return failOpaque(Error.MATH_ERROR, FailureInfo
                                                                .REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED, uint(vars.mathErr));\n }\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\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(redeemAmountIn, Exp
                                                                ({mantissa: vars.exchangeRateMantissa}));\n if (vars.mathErr != MathError.NO_ERROR) {\n return failOpaque(Error
                                                                .MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED, uint(vars.mathErr));\n }\n\n vars.redeemAmount =
                                                                redeemAmountIn;\n }\n\n /* Fail if redeem not allowed */\n uint 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\u0027s 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.mathErr, vars.totalSupplyNew) =
                                                                subUInt(totalSupply, vars.redeemTokens);\n if (vars.mathErr != MathError.NO_ERROR) {\n return failOpaque(Error.MATH_ERROR,
                                                                FailureInfo.REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED, uint(vars.mathErr));\n }\n\n (vars.mathErr, vars.accountTokensNew) = subUInt
                                                                (accountTokens[redeemer], vars.redeemTokens);\n if (vars.mathErr != MathError.NO_ERROR) {\n return failOpaque(Error.MATH_ERROR,
                                                                FailureInfo.REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED, uint(vars.mathErr));\n }\n\n /* Fail gracefully if protocol has
                                                                insufficient cash */\n if (getCashPrior() \u003c vars.redeemAmount) {\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo
                                                                .REDEEM_TRANSFER_OUT_NOT_POSSIBLE);\n }\n\n /////////////////////////\n // EFFECTS \u0026 INTERACTIONS\n // (No safe
                                                                failures beyond this point)\n\n /*\n * We invoke doTransferOut for the redeemer and the redeemAmount.\n * Note: The sToken
                                                                must handle variations between ERC-20 and ETH underlying.\n * On success, the sToken has redeemAmount less of cash.\n *
                                                                doTransferOut reverts if anything goes wrong, since we can\u0027t 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 uint(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(uint borrowAmount) internal nonReentrant returns (uint) {\n uint error = accrueInterest();\n if (error != uint(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\u0027t need to\n return borrowFresh(msg.sender, borrowAmount);\n }\n\n struct BorrowLocalVars {\n MathError mathErr;\n
                                                                 uint accountBorrows;\n uint accountBorrowsNew;\n uint 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, uint borrowAmount) internal
                                                                returns (uint) {\n /* Fail if borrow not allowed */\n uint 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\u0027s 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() \u003c 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.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\n if (vars
                                                                .mathErr != MathError.NO_ERROR) {\n return failOpaque(Error.MATH_ERROR, FailureInfo.BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED, uint
                                                                (vars.mathErr));\n }\n\n (vars.mathErr, vars.accountBorrowsNew) = addUInt(vars.accountBorrows, borrowAmount);\n if (vars
                                                                .mathErr != MathError.NO_ERROR) {\n return failOpaque(Error.MATH_ERROR, FailureInfo.BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED
                                                                , uint(vars.mathErr));\n }\n\n (vars.mathErr, vars.totalBorrowsNew) = addUInt(totalBorrows, borrowAmount);\n if (vars.mathErr
                                                                != MathError.NO_ERROR) {\n return failOpaque(Error.MATH_ERROR, FailureInfo.BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED, uint(vars
                                                                .mathErr));\n }\n\n /////////////////////////\n // EFFECTS \u0026 INTERACTIONS\n // (No safe failures beyond this point
                                                                )\n\n /*\n * We invoke doTransferOut for the borrower and the borrowAmount.\n * Note: The sToken must handle variations
                                                                between ERC-20 and ETH underlying.\n * On success, the sToken borrowAmount less of cash.\n * doTransferOut reverts if anything
                                                                goes wrong, since we can\u0027t 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 uint(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(uint repayAmount) internal nonReentrant returns
                                                                (uint, uint) {\n uint error = accrueInterest();\n if (error != uint(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\u0027t
                                                                need to\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\n }\n\n /**\n * @notice Sender repays a borrow belonging
                                                                to borrower\n * @param borrower the account with the debt being payed off\n * @param repayAmount The amount to repay\n * @return (uint,
                                                                uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\n */\n function
                                                                repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\n uint error = accrueInterest
                                                                ();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an
                                                                attempted borrow failed\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\n }\n //
                                                                repayBorrowFresh emits repay-borrow-specific logs on errors, so we don\u0027t need to\n return repayBorrowFresh(msg.sender, borrower,
                                                                repayAmount);\n }\n\n struct RepayBorrowLocalVars {\n Error err;\n MathError mathErr;\n uint repayAmount;\n uint
                                                                borrowerIndex;\n uint accountBorrows;\n uint accountBorrowsNew;\n uint totalBorrowsNew;\n uint 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(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\n /* Fail if repayBorrow not allowed
                                                                */\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\n if (allowed != 0) {\n
                                                                return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed), 0);\n }\n\n /* Verify
                                                                market\u0027s 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.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal
                                                                (borrower);\n if (vars.mathErr != MathError.NO_ERROR) {\n return (failOpaque(Error.MATH_ERROR, FailureInfo
                                                                .REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED, uint(vars.mathErr)), 0);\n }\n\n /* If repayAmount == -1, repayAmount =
                                                                accountBorrows */\n if (repayAmount == uint(-1)) {\n vars.repayAmount = vars.accountBorrows;\n } else {\n vars
                                                                .repayAmount = repayAmount;\n }\n\n /////////////////////////\n // EFFECTS \u0026 INTERACTIONS\n // (No safe failures
                                                                beyond this point)\n\n /*\n * We call doTransferIn for the payer and the repayAmount\n * Note: The sToken must handle
                                                                variations between ERC-20 and ETH underlying.\n * On success, the sToken holds an additional repayAmount of cash.\n *
                                                                doTransferIn reverts if anything goes wrong, since we can\u0027t 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.mathErr, vars.accountBorrowsNew) = subUInt(vars
                                                                .accountBorrows, vars.actualRepayAmount);\n require(vars.mathErr == MathError.NO_ERROR,
                                                                \"REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED\");\n\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars
                                                                .actualRepayAmount);\n require(vars.mathErr == MathError.NO_ERROR, \"REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED\");\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 (uint
                                                                (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 sToken to be liquidated\n * @param
                                                                sTokenCollateral 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(address borrower, uint repayAmount, STokenInterface sTokenCollateral) internal nonReentrant returns (uint
                                                                , uint) {\n uint error = accrueInterest();\n if (error != uint(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 = sTokenCollateral.accrueInterest();\n if (error != uint(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\u0027t need to\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, sTokenCollateral
                                                                );\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 sToken to be liquidated\n * @param liquidator The address repaying the borrow and
                                                                seizing collateral\n * @param sTokenCollateral 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(address liquidator, address borrower, uint repayAmount, STokenInterface
                                                                sTokenCollateral) internal returns (uint, uint) {\n /* Fail if liquidate not allowed */\n uint allowed = comptroller
                                                                .liquidateBorrowAllowed(address(this), address(sTokenCollateral), liquidator, borrower, repayAmount);\n if (allowed != 0) {\n
                                                                return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\n }\n\n /* Verify
                                                                market\u0027s 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 sTokenCollateral market\u0027s block number equals
                                                                current block number */\n if (sTokenCollateral.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 == uint(-1)) {\n
                                                                return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\n }\n\n\n /* Fail if
                                                                repayBorrow fails */\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\n if
                                                                (repayBorrowError != uint(Error.NO_ERROR)) {\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0
                                                                );\n }\n\n /////////////////////////\n // EFFECTS \u0026 INTERACTIONS\n // (No safe failures beyond this point)\n\n
                                                                 /* We calculate the number of collateral tokens that will be seized */\n (uint amountSeizeError, uint seizeTokens) = comptroller
                                                                .liquidateCalculateSeizeTokens(address(this), address(sTokenCollateral), actualRepayAmount);\n require(amountSeizeError == uint(Error
                                                                .NO_ERROR), \"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\");\n\n /* Revert if borrower collateral token balance \u003c seizeTokens
                                                                */\n require(sTokenCollateral.balanceOf(borrower) \u003e= 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 uint seizeError;\n if (address(sTokenCollateral
                                                                ) == address(this)) {\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\n } else {\n
                                                                seizeError = sTokenCollateral.seize(liquidator, borrower, seizeTokens);\n }\n\n /* Revert if seize tokens fails (since we cannot be
                                                                sure of side effects) */\n require(seizeError == uint(Error.NO_ERROR), \"token seizure failed\");\n\n /* We emit a LiquidateBorrow
                                                                event */\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(sTokenCollateral), seizeTokens);\n\n /* We call the
                                                                defense hook */\n comptroller.liquidateBorrowVerify(address(this), address(sTokenCollateral), liquidator, borrower, actualRepayAmount,
                                                                seizeTokens);\n\n return (uint(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 sToken during the process of liquidation.\n * Its absolutely
                                                                critical to use msg.sender as the borrowed sToken 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 sTokens to seize\n * @return uint 0=success,
                                                                otherwise a failure (see ErrorReporter.sol for details)\n */\n function seize(address liquidator, address borrower, uint seizeTokens)
                                                                external nonReentrant returns (uint) {\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 SToken.\n * Its absolutely critical to use msg.sender as the seizer sToken and not a parameter.\n *
                                                                @param seizerToken The contract seizing the collateral (i.e. borrowed sToken)\n * @param liquidator The account receiving seized collateral\n
                                                                 * @param borrower The account having collateral seized\n * @param seizeTokens The number of sTokens to seize\n * @return uint 0=success,
                                                                otherwise a failure (see ErrorReporter.sol for details)\n */\n function seizeInternal(address seizerToken, address liquidator, address
                                                                borrower, uint seizeTokens) internal returns (uint) {\n /* Fail if seize not allowed */\n uint 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 MathError mathErr;\n uint borrowerTokensNew;\n uint liquidatorTokensNew;\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 (mathErr, borrowerTokensNew) = subUInt
                                                                (accountTokens[borrower], seizeTokens);\n if (mathErr != MathError.NO_ERROR) {\n return failOpaque(Error.MATH_ERROR, FailureInfo
                                                                .LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(mathErr));\n }\n\n (mathErr, liquidatorTokensNew) = addUInt(accountTokens[liquidator]
                                                                , seizeTokens);\n if (mathErr != MathError.NO_ERROR) {\n return failOpaque(Error.MATH_ERROR, FailureInfo
                                                                .LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(mathErr));\n }\n\n /////////////////////////\n // EFFECTS \u0026
                                                                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 uint(Error.NO_ERROR);\n }\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 (uint) {\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
                                                                uint(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 (uint) {\n // Check caller is pendingAdmin and pendingAdmin ≠ 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 uint(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 (uint) {\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\u0027s comptroller to newComptroller\n comptroller = newComptroller;\n\n // Emit
                                                                NewComptroller(oldComptroller, newComptroller)\n emit NewComptroller(oldComptroller, newComptroller);\n\n return uint(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(uint newReserveFactorMantissa) external nonReentrant returns (uint) {\n uint error =
                                                                accrueInterest();\n if (error != uint(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\u0027t 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(uint newReserveFactorMantissa) internal
                                                                returns (uint) {\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\u0027s 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 ≤ maxReserveFactor\n if (newReserveFactorMantissa \u003e reserveFactorMaxMantissa) {\n
                                                                return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\n }\n\n uint oldReserveFactorMantissa =
                                                                reserveFactorMantissa;\n reserveFactorMantissa = newReserveFactorMantissa;\n\n emit NewReserveFactor(oldReserveFactorMantissa,
                                                                newReserveFactorMantissa);\n\n return uint(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(uint addAmount) internal nonReentrant returns (uint) {\n uint
                                                                error = accrueInterest();\n if (error != uint(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\u0027t
                                                                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(uint addAmount) internal returns (uint, uint) {\n // totalReserves + actualAddAmount\n uint totalReservesNew;\n
                                                                 uint actualAddAmount;\n\n // We fail gracefully unless market\u0027s 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 \u0026 INTERACTIONS\n // (No safe failures beyond this point)\n\n
                                                                 /*\n * We call doTransferIn for the caller and the addAmount\n * Note: The sToken must handle variations between ERC-20 and
                                                                ETH underlying.\n * On success, the sToken holds an additional addAmount of cash.\n * doTransferIn reverts if anything goes wrong
                                                                , since we can\u0027t 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 = totalReserves + actualAddAmount;\n\n /* Revert
                                                                on overflow */\n require(totalReservesNew \u003e= totalReserves, \"add reserves unexpected overflow\");\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 (uint
                                                                (Error.NO_ERROR), actualAddAmount);\n }\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(uint reduceAmount) external nonReentrant returns (uint) {\n uint error = accrueInterest();\n if
                                                                (error != uint(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\u0027t 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(uint reduceAmount) internal returns (uint) {\n // totalReserves - reduceAmount\n uint 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\u0027s 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() \u003c reduceAmount) {\n return
                                                                fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\n }\n\n // Check reduceAmount ≤ reserves[n]
                                                                (totalReserves)\n if (reduceAmount \u003e totalReserves) {\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION
                                                                );\n }\n\n /////////////////////////\n // EFFECTS \u0026 INTERACTIONS\n // (No safe failures beyond this point)\n\n
                                                                 totalReservesNew = totalReserves - reduceAmount;\n // We checked reduceAmount \u003c= totalReserves above, so this should never revert
                                                                .\n require(totalReservesNew \u003c= totalReserves, \"reduce reserves unexpected underflow\");\n\n // Store reserves[n+1] =
                                                                reserves[n] - reduceAmount\n totalReserves = totalReservesNew;\n\n // doTransferOut reverts if anything goes wrong, since we
                                                                can\u0027t be sure if side effects occurred.\n doTransferOut(admin, reduceAmount);\n\n emit ReservesReduced(admin, reduceAmount,
                                                                totalReservesNew);\n\n return uint(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 (uint) {\n uint error = accrueInterest();\n
                                                                 if (error != uint(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\u0027t 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 (uint) {\n\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\u0027s
                                                                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\u0027s 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 uint(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 (uint
                                                                );\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, uint amount)
                                                                internal returns (uint);\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\u0027s balance, may revert due to insufficient cash held in the contract.\n * If
                                                                caller has checked protocol\u0027s balance, and verified it is \u003e= amount, this should not revert in normal conditions.\n */\n function
                                                                doTransferOut(address payable to, uint amount) internal;\n\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"},"STokenInterfaces.sol":{"content":"pragma
                                                                solidity ^0.5.16;\n\nimport \"./ComptrollerInterface.sol\";\nimport \"./InterestRateModel.sol\";\n\ncontract STokenStorage {\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 uint internal constant borrowRateMaxMantissa = 0.0005e16;\n\n /**\n * @notice Maximum fraction of
                                                                interest that can be set aside for reserves\n */\n uint 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-sToken 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 STokens (used when
                                                                totalSupply = 0)\n */\n uint internal initialExchangeRateMantissa;\n\n /**\n * @notice Fraction of interest currently set aside for
                                                                reserves\n */\n uint public reserveFactorMantissa;\n\n /**\n * @notice Block number that interest was last accrued at\n */\n
                                                                uint public accrualBlockNumber;\n\n /**\n * @notice Accumulator of the total earned interest rate since the opening of the market\n */\n
                                                                 uint public borrowIndex;\n\n /**\n * @notice Total amount of outstanding borrows of the underlying in this market\n */\n uint
                                                                public totalBorrows;\n\n /**\n * @notice Total amount of reserves of the underlying held in this market\n */\n uint public
                                                                totalReserves;\n\n /**\n * @notice Total number of tokens in circulation\n */\n uint public totalSupply;\n\n /**\n * @notice
                                                                Official record of token balances for each account\n */\n mapping (address =\u003e uint) internal accountTokens;\n\n /**\n * @notice
                                                                Approved token transfer amounts on behalf of others\n */\n mapping (address =\u003e mapping (address =\u003e uint)) 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 uint principal;\n uint interestIndex;\n }\n\n /**\n * @notice
                                                                Mapping of account addresses to outstanding borrow balances\n */\n mapping(address =\u003e BorrowSnapshot) internal accountBorrows
                                                                ;\n}\n\ncontract STokenInterface is STokenStorage {\n /**\n * @notice Indicator that this is a SToken contract (for inspection)\n */\n
                                                                 bool public constant isSToken = true;\n\n\n /*** Market Events ***/\n\n /**\n * @notice Event emitted when interest is accrued\n
                                                                */\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\n\n /**\n * @notice Event
                                                                emitted when tokens are minted\n */\n event Mint(address minter, uint mintAmount, uint mintTokens);\n\n /**\n * @notice Event emitted
                                                                when tokens are redeemed\n */\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens);\n\n /**\n * @notice Event
                                                                emitted when underlying is borrowed\n */\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\n\n
                                                                 /**\n * @notice Event emitted when a borrow is repaid\n */\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint
                                                                accountBorrows, uint totalBorrows);\n\n /**\n * @notice Event emitted when a borrow is liquidated\n */\n event LiquidateBorrow
                                                                (address liquidator, address borrower, uint repayAmount, address sTokenCollateral, uint 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(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\n\n
                                                                 /**\n * @notice Event emitted when the reserves are added\n */\n event ReservesAdded(address benefactor, uint addAmount, uint
                                                                newTotalReserves);\n\n /**\n * @notice Event emitted when the reserves are reduced\n */\n event ReservesReduced(address admin, uint
                                                                reduceAmount, uint newTotalReserves);\n\n /**\n * @notice EIP20 Transfer event\n */\n event Transfer(address indexed from, address
                                                                indexed to, uint amount);\n\n /**\n * @notice EIP20 Approval event\n */\n event Approval(address indexed owner, address indexed
                                                                spender, uint amount);\n\n /**\n * @notice Failure event\n */\n event Failure(uint error, uint info, uint detail);\n\n\n /*** User
                                                                Interface ***/\n\n function transfer(address dst, uint amount) external returns (bool);\n function transferFrom(address src, address dst,
                                                                uint amount) external returns (bool);\n function approve(address spender, uint amount) external returns (bool);\n function allowance(address
                                                                owner, address spender) external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n function
                                                                balanceOfUnderlying(address owner) external returns (uint);\n function getAccountSnapshot(address account) external view returns (uint, uint,
                                                                uint, uint);\n function borrowRatePerBlock() external view returns (uint);\n function supplyRatePerBlock() external view returns (uint);\n
                                                                 function totalBorrowsCurrent() external returns (uint);\n function borrowBalanceCurrent(address account) external returns (uint);\n function
                                                                borrowBalanceStored(address account) public view returns (uint);\n function exchangeRateCurrent() public returns (uint);\n function
                                                                exchangeRateStored() public view returns (uint);\n function getCash() external view returns (uint);\n function accrueInterest() public
                                                                returns (uint);\n function seize(address liquidator, address borrower, uint seizeTokens) external returns (uint);\n\n\n /*** Admin Functions
                                                                ***/\n\n function _setPendingAdmin(address payable newPendingAdmin) external returns (uint);\n function _acceptAdmin() external returns (uint
                                                                );\n function _setComptroller(ComptrollerInterface newComptroller) public returns (uint);\n function _setReserveFactor(uint
                                                                newReserveFactorMantissa) external returns (uint);\n function _reduceReserves(uint reduceAmount) external returns (uint);\n function
                                                                _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint);\n}\n\ncontract SErc20Storage {\n /**\n * @notice
                                                                Underlying asset for this SToken\n */\n address public underlying;\n}\n\ncontract SErc20Interface is SErc20Storage {\n\n /*** User
                                                                Interface ***/\n\n function mint(uint mintAmount) external returns (uint);\n function redeem(uint redeemTokens) external returns (uint);\n
                                                                 function redeemUnderlying(uint redeemAmount) external returns (uint);\n function borrow(uint borrowAmount) external returns (uint);\n
                                                                function repayBorrow(uint repayAmount) external returns (uint);\n function repayBorrowBehalf(address borrower, uint repayAmount) external
                                                                returns (uint);\n function liquidateBorrow(address borrower, uint repayAmount, STokenInterface sTokenCollateral) external returns (uint);\n\n\n
                                                                 /*** Admin Functions ***/\n\n function _addReserves(uint addAmount) external returns (uint);\n}\n\ncontract SDelegationStorage {\n /**\n
                                                                 * @notice Implementation address for this contract\n */\n address public implementation;\n}\n\ncontract SDelegatorInterface is
                                                                SDelegationStorage {\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(address implementation_, bool allowResign, bytes memory becomeImplementationData)
                                                                public;\n}\n\ncontract SDelegateInterface is SDelegationStorage {\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"},"Unitroller.sol":{"content":"pragma solidity
                                                                ^0.5.16;\n\nimport \"./ErrorReporter.sol\";\nimport \"./ComptrollerStorage.sol\";\n/**\n * @title ComptrollerCore\n * @dev Storage for the
                                                                comptroller is at this address, while execution is delegated to the `comptrollerImplementation`.\n * STokens should reference this contract as
                                                                their comptroller.\n */\ncontract Unitroller is UnitrollerAdminStorage, ComptrollerErrorReporter {\n\n /**\n * @notice Emitted when
                                                                pendingComptrollerImplementation is changed\n */\n event NewPendingImplementation(address oldPendingImplementation, address
                                                                newPendingImplementation);\n\n /**\n * @notice Emitted when pendingComptrollerImplementation is accepted, which means comptroller
                                                                implementation is updated\n */\n event NewImplementation(address oldImplementation, address newImplementation);\n\n /**\n * @notice
                                                                Emitted when pendingAdmin is changed\n */\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\n\n /**\n *
                                                                @notice Emitted when pendingAdmin is accepted, which means admin is updated\n */\n event NewAdmin(address oldAdmin, address newAdmin);\n\n
                                                                 constructor() public {\n // Set admin to caller\n admin = msg.sender;\n }\n\n /*** Admin Functions ***/\n function
                                                                _setPendingImplementation(address newPendingImplementation) public returns (uint) {\n\n if (msg.sender != admin) {\n return fail
                                                                (Error.UNAUTHORIZED, FailureInfo.SET_PENDING_IMPLEMENTATION_OWNER_CHECK);\n }\n\n address oldPendingImplementation =
                                                                pendingComptrollerImplementation;\n\n pendingComptrollerImplementation = newPendingImplementation;\n\n emit NewPendingImplementation
                                                                (oldPendingImplementation, pendingComptrollerImplementation);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Accepts new
                                                                implementation of comptroller. msg.sender must be pendingImplementation\n * @dev Admin function for new implementation to accept it\u0027s role
                                                                as implementation\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function
                                                                _acceptImplementation() public returns (uint) {\n // Check caller is pendingImplementation and pendingImplementation ≠ address(0)\n
                                                                if (msg.sender != pendingComptrollerImplementation || pendingComptrollerImplementation == address(0)) {\n return fail(Error.UNAUTHORIZED
                                                                , FailureInfo.ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK);\n }\n\n // Save current values for inclusion in log\n address
                                                                oldImplementation = comptrollerImplementation;\n address oldPendingImplementation = pendingComptrollerImplementation;\n\n
                                                                comptrollerImplementation = pendingComptrollerImplementation;\n\n pendingComptrollerImplementation = address(0);\n\n emit
                                                                NewImplementation(oldImplementation, comptrollerImplementation);\n emit NewPendingImplementation(oldPendingImplementation,
                                                                pendingComptrollerImplementation);\n\n return uint(Error.NO_ERROR);\n }\n\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 newPendingAdmin) public returns (uint) {\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 uint(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() public
                                                                returns (uint) {\n // Check caller is pendingAdmin and pendingAdmin ≠ 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 uint(Error.NO_ERROR);\n }\n\n
                                                                /**\n * @dev Delegates execution to an implementation contract.\n * It returns to the external caller whatever the implementation returns\n
                                                                 * or forwards reverts.\n */\n function () external payable {\n // delegate all other functions to current implementation\n
                                                                 (bool success, ) = comptrollerImplementation.delegatecall(msg.data);\n\n assembly {\n let free_mem_ptr := mload(0x40)\n
                                                                 returndatacopy(free_mem_ptr, 0, returndatasize)\n\n switch success\n case 0 { revert(free_mem_ptr, returndatasize)
                                                                }\n default { return(free_mem_ptr, returndatasize) }\n }\n }\n}\n"}}
                                                            XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

                                                            File 3 of 14: FiatTokenProxy
                                                            1
                                                            2
                                                            3
                                                            4
                                                            5
                                                            6
                                                            7
                                                            8
                                                            9
                                                            10
                                                            11
                                                            12
                                                            13
                                                            14
                                                            15
                                                            16
                                                            pragma solidity ^0.4.24;
                                                            // File: zos-lib/contracts/upgradeability/Proxy.sol
                                                            /**
                                                            * @title Proxy
                                                            * @dev Implements delegation of calls to other contracts, with proper
                                                            * forwarding of return values and bubbling of failures.
                                                            * It defines a fallback function that delegates all calls to the address
                                                            * returned by the abstract _implementation() internal function.
                                                            */
                                                            contract Proxy {
                                                            /**
                                                            * @dev Fallback function.
                                                            * Implemented entirely in `_fallback`.
                                                            */
                                                            XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

                                                            File 4 of 14: SErc20Delegate
                                                            1
                                                            2
                                                            3
                                                            4
                                                            5
                                                            6
                                                            7
                                                            8
                                                            9
                                                            10
                                                            11
                                                            12
                                                            13
                                                            14
                                                            15
                                                            16
                                                            // File: contracts/ComptrollerInterface.sol
                                                            pragma solidity ^0.5.16;
                                                            contract ComptrollerInterface {
                                                            /// @notice Indicator that this is a Comptroller contract (for inspection)
                                                            bool public constant isComptroller = true;
                                                            /*** Assets You Are In ***/
                                                            function enterMarkets(address[] calldata sTokens) external returns (uint[] memory);
                                                            function exitMarket(address sToken) external returns (uint);
                                                            /*** Policy Hooks ***/
                                                            function mintAllowed(address sToken, address minter, uint mintAmount) external returns (uint);
                                                            XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

                                                            File 5 of 14: FiatTokenV2_2
                                                            1
                                                            2
                                                            3
                                                            4
                                                            5
                                                            6
                                                            7
                                                            8
                                                            9
                                                            10
                                                            11
                                                            12
                                                            13
                                                            14
                                                            15
                                                            16
                                                            /**
                                                            * SPDX-License-Identifier: Apache-2.0
                                                            *
                                                            * Copyright (c) 2023, Circle Internet Financial, LLC.
                                                            *
                                                            * Licensed under the Apache License, Version 2.0 (the "License");
                                                            * you may not use this file except in compliance with the License.
                                                            * You may obtain a copy of the License at
                                                            *
                                                            * http://www.apache.org/licenses/LICENSE-2.0
                                                            *
                                                            * Unless required by applicable law or agreed to in writing, software
                                                            * distributed under the License is distributed on an "AS IS" BASIS,
                                                            * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
                                                            * See the License for the specific language governing permissions and
                                                            * limitations under the License.
                                                            XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

                                                            File 6 of 14: JumpRateModelV2
                                                            1
                                                            2
                                                            3
                                                            4
                                                            5
                                                            6
                                                            7
                                                            8
                                                            9
                                                            10
                                                            11
                                                            12
                                                            13
                                                            14
                                                            15
                                                            16
                                                            pragma solidity ^0.5.16;
                                                            /**
                                                            * @title Strike's InterestRateModel Interface
                                                            * @author Strike
                                                            */
                                                            contract InterestRateModel {
                                                            /// @notice Indicator that this is an InterestRateModel contract (for inspection)
                                                            bool public constant isInterestRateModel = true;
                                                            /**
                                                            * @notice Calculates the current borrow interest rate per block
                                                            * @param cash The total amount of cash the market has
                                                            * @param borrows The total amount of borrows the market has outstanding
                                                            * @param reserves The total amount of reserves the market has
                                                            * @return The borrow rate per block (as a percentage, and scaled by 1e18)
                                                            XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

                                                            File 7 of 14: Comptroller
                                                            1
                                                            {"CarefulMath.sol":{"content":"pragma solidity ^0.5.16;\n\n/**\n * @title Careful Math\n * @author Strike\n * @notice Derived from
                                                                OpenZeppelin\u0027s SafeMath library\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\n
                                                                */\ncontract CarefulMath {\n\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(uint a, uint b) internal pure returns (MathError, uint) {\n if (a == 0) {\n return
                                                                (MathError.NO_ERROR, 0);\n }\n\n uint 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(uint a, uint b) internal pure returns (MathError, uint) {\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(uint a, uint b) internal pure returns
                                                                (MathError, uint) {\n if (b \u003c= 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(uint
                                                                a, uint b) internal pure returns (MathError, uint) {\n uint c = a + b;\n\n if (c \u003e= 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(uint a, uint b, uint c) internal pure returns (MathError, uint) {\n (MathError err0, uint sum) =
                                                                addUInt(a, b);\n\n if (err0 != MathError.NO_ERROR) {\n return (err0, 0);\n }\n\n return subUInt(sum, c);\n
                                                                }\n}"},"Comptroller.sol":{"content":"pragma solidity ^0.5.16;\n\nimport \"./SToken.sol\";\nimport \"./ErrorReporter.sol\";\nimport \"./Exponential
                                                                .sol\";\nimport \"./PriceOracle.sol\";\nimport \"./ComptrollerInterface.sol\";\nimport \"./ComptrollerStorage.sol\";\nimport \"./Unitroller.sol\"
                                                                ;\nimport \"./STRK.sol\";\nimport \"./IStrikeStaking.sol\";\n\n/**\n * @title Strike\u0027s Comptroller Contract\n * @author Strike\n */\ncontract
                                                                Comptroller is ComptrollerV7Storage, ComptrollerInterface, ComptrollerErrorReporter, Exponential {\n /// @notice Emitted when an admin supports
                                                                a market\n event MarketListed(SToken sToken);\n\n /// @notice Emitted when an account enters a market\n event MarketEntered(SToken sToken,
                                                                address account);\n\n /// @notice Emitted when an account exits a market\n event MarketExited(SToken sToken, address account);\n\n ///
                                                                @notice Emitted when close factor is changed by admin\n event NewCloseFactor(uint oldCloseFactorMantissa, uint newCloseFactorMantissa);\n\n
                                                                /// @notice Emitted when a collateral factor is changed by admin\n event NewCollateralFactor(SToken sToken, uint oldCollateralFactorMantissa,
                                                                uint newCollateralFactorMantissa);\n\n /// @notice Emitted when liquidation incentive is changed by admin\n event NewLiquidationIncentive
                                                                (uint oldLiquidationIncentiveMantissa, uint newLiquidationIncentiveMantissa);\n\n /// @notice Emitted when price oracle is changed\n event
                                                                NewPriceOracle(PriceOracle oldPriceOracle, PriceOracle newPriceOracle);\n\n /// @notice Emitted when pause guardian is changed\n event
                                                                NewPauseGuardian(address oldPauseGuardian, address newPauseGuardian);\n\n /// @notice Emitted when an action is paused globally\n event
                                                                ActionPaused(string action, bool pauseState);\n\n /// @notice Emitted when an action is paused on a market\n event ActionPaused(SToken sToken
                                                                , string action, bool pauseState);\n\n /// @notice Emitted when protocol pause state is changed by admin\n event ActionProtocolPaused(bool
                                                                state);\n\n /// @notice Emitted when market striked status is changed\n event MarketStriked(SToken sToken, bool isStriked);\n\n ///
                                                                @notice Emitted when STRK rate is changed\n event NewStrikeRate(uint oldStrikeRate, uint newStrikeRate);\n\n /// @notice Emitted when a new
                                                                STRK speed is calculated for a market\n event StrikeSpeedUpdated(SToken indexed sToken, uint newSpeed);\n\n /// @notice Emitted when STRK is
                                                                distributed to a supplier\n event DistributedSupplierStrike(SToken indexed sToken, address indexed supplier, uint strikeDelta, uint
                                                                strikeSupplyIndex);\n\n /// @notice Emitted when STRK is distributed to a borrower\n event DistributedBorrowerStrike(SToken indexed sToken,
                                                                address indexed borrower, uint strikeDelta, uint strikeBorrowIndex);\n\n /// @notice Emitted when new Strike speed is set\n event
                                                                ContributorStrikeSpeedUpdated(address indexed contributor, uint newStrikeSpeed);\n\n /// @notice Emitted when Strike is granted\n event
                                                                StrikeGranted(address recipient, uint amount);\n\n /// @notice Emitted when a new borrow-side Strike speed is calculated for a market\n
                                                                event StrikeBorrowSpeedUpdated(SToken indexed sToken, uint newSpeed);\n\n /// @notice Emitted when a new supply-side Strike speed is calculated
                                                                for a market\n event StrikeSupplySpeedUpdated(SToken indexed sToken, uint newSpeed);\n\n /// @notice Emitted when reserve guardian is
                                                                changed\n event NewReserveGuardian(address oldReserveGuardian, address newReserveGuardian, address oldReserveAddress, address newReserveAddress
                                                                );\n\n /// @notice Emitted when strk staking info is changed\n event NewStrkStakingInfo(address oldStrkStaking, address newStrkStaking);\n\n
                                                                 /// @notice Emitted when market cap for a sToken is changed\n event NewMarketCap(SToken indexed sToken, uint newSupplyCap, uint newBorrowCap
                                                                );\n\n /// @notice Emitted when market cap guardian is changed\n event NewMarketCapGuardian(address oldMarketCapGuardian, address
                                                                newMarketCapGuardian);\n\n /// @notice The initial STRK index for a market\n uint224 public constant strikeInitialIndex = 1e36;\n\n // No
                                                                collateralFactorMantissa may exceed this value\n uint internal constant collateralFactorMaxMantissa = 0.9e18; // 0.9\n\n constructor() public
                                                                {\n admin = msg.sender;\n }\n\n modifier onlyProtocolAllowed {\n require(!protocolPaused, \"protocol is paused\");\n _
                                                                ;\n }\n\n modifier validPauseState(bool state) {\n require(msg.sender == pauseGuardian || msg.sender == admin, \"only pause guardian
                                                                and admin can\");\n _;\n }\n\n /*** Assets You Are In ***/\n\n /**\n * @notice Returns the assets an account has entered\n
                                                                * @param account The address of the account to pull assets for\n * @return A dynamic list with the assets the account has entered\n */\n
                                                                 function getAssetsIn(address account) external view returns (SToken[] memory) {\n SToken[] memory assetsIn = accountAssets[account];\n\n
                                                                 return assetsIn;\n }\n\n /**\n * @notice Returns whether the given account is entered in the given asset\n * @param account The
                                                                address of the account to check\n * @param sToken The sToken to check\n * @return True if the account is in the asset, otherwise false.\n
                                                                 */\n function checkMembership(address account, SToken sToken) external view returns (bool) {\n return markets[address(sToken)]
                                                                .accountMembership[account];\n }\n\n /**\n * @notice Add assets to be included in account liquidity calculation\n * @param sTokens
                                                                The list of addresses of the sToken markets to be enabled\n * @return Success indicator for whether each corresponding market was entered\n
                                                                 */\n function enterMarkets(address[] memory sTokens) public returns (uint[] memory) {\n uint len = sTokens.length;\n\n uint[]
                                                                memory results = new uint[](len);\n for (uint i = 0; i \u003c len; i++) {\n SToken sToken = SToken(sTokens[i]);\n\n
                                                                results[i] = uint(addToMarketInternal(sToken, msg.sender));\n }\n\n return results;\n }\n\n /**\n * @notice Add the market
                                                                to the borrower\u0027s \"assets in\" for liquidity calculations\n * @param sToken The market to enter\n * @param borrower The address of
                                                                the account to modify\n * @return Success indicator for whether the market was entered\n */\n function addToMarketInternal(SToken sToken
                                                                , address borrower) internal returns (Error) {\n Market storage marketToJoin = markets[address(sToken)];\n\n if (!marketToJoin
                                                                .isListed) {\n // market is not listed, cannot join\n return Error.MARKET_NOT_LISTED;\n }\n\n if (marketToJoin
                                                                .accountMembership[borrower] == true) {\n // already joined\n return Error.NO_ERROR;\n }\n\n // survived the
                                                                gauntlet, add to list\n // NOTE: we store these somewhat redundantly as a significant optimization\n // this avoids having to
                                                                iterate through the list for the most common use cases\n // that is, only when we need to perform liquidity checks\n // and not
                                                                whenever we want to check if an account is in a particular market\n marketToJoin.accountMembership[borrower] = true;\n
                                                                accountAssets[borrower].push(sToken);\n\n emit MarketEntered(sToken, borrower);\n\n return Error.NO_ERROR;\n }\n\n /**\n *
                                                                @notice Removes asset from sender\u0027s account liquidity calculation\n * @dev Sender must not have an outstanding borrow balance in the asset
                                                                ,\n * or be providing necessary collateral for an outstanding borrow.\n * @param sTokenAddress The address of the asset to be removed\n
                                                                 * @return Whether or not the account successfully exited the market\n */\n function exitMarket(address sTokenAddress) external returns
                                                                (uint) {\n SToken sToken = SToken(sTokenAddress);\n /* Get sender tokensHeld and amountOwed underlying from the sToken */\n
                                                                (uint oErr, uint tokensHeld, uint amountOwed, ) = sToken.getAccountSnapshot(msg.sender);\n require(oErr == 0, \"exitMarket:
                                                                getAccountSnapshot failed\"); // semi-opaque error code\n\n /* Fail if the sender has a borrow balance */\n if (amountOwed != 0) {\n
                                                                 return fail(Error.NONZERO_BORROW_BALANCE, FailureInfo.EXIT_MARKET_BALANCE_OWED);\n }\n\n /* Fail if the sender is not
                                                                permitted to redeem all of their tokens */\n uint allowed = redeemAllowedInternal(sTokenAddress, msg.sender, tokensHeld);\n if
                                                                (allowed != 0) {\n return failOpaque(Error.REJECTION, FailureInfo.EXIT_MARKET_REJECTION, allowed);\n }\n\n Market storage
                                                                marketToExit = markets[address(sToken)];\n\n /* Return true if the sender is not already ‘in’ the market */\n if (!marketToExit
                                                                .accountMembership[msg.sender]) {\n return uint(Error.NO_ERROR);\n }\n\n /* Set sToken account membership to false */\n
                                                                 delete marketToExit.accountMembership[msg.sender];\n\n /* Delete sToken from the account’s list of assets */\n // load into
                                                                memory for faster iteration\n SToken[] memory userAssetList = accountAssets[msg.sender];\n uint len = userAssetList.length;\n
                                                                uint assetIndex = len;\n for (uint i = 0; i \u003c len; i++) {\n if (userAssetList[i] == sToken) {\n assetIndex =
                                                                i;\n break;\n }\n }\n\n // We *must* have found the asset in the list or our redundant data structure is
                                                                broken\n assert(assetIndex \u003c len);\n\n // copy last item in list to location of item to be removed, reduce length by 1\n
                                                                SToken[] storage storedList = accountAssets[msg.sender];\n storedList[assetIndex] = storedList[storedList.length - 1];\n storedList
                                                                .length--;\n\n emit MarketExited(sToken, msg.sender);\n\n return uint(Error.NO_ERROR);\n }\n\n /*** Policy Hooks ***/\n\n
                                                                /**\n * @notice Checks if the account should be allowed to mint tokens in the given market\n * @param sToken The market to verify the mint
                                                                against\n * @param minter The account which would get the minted tokens\n * @param mintAmount The amount of underlying being supplied to
                                                                the market in exchange for tokens\n * @return 0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\n */\n
                                                                 function mintAllowed(address sToken, address minter, uint mintAmount) external onlyProtocolAllowed returns (uint) {\n // Pausing is a very
                                                                serious situation - we revert to sound the alarms\n\n // Shh - currently unused\n minter;\n mintAmount;\n\n if
                                                                (!markets[sToken].isListed) {\n return uint(Error.MARKET_NOT_LISTED);\n }\n\n uint supplyCap = supplyCaps[sToken];\n
                                                                 // Supply cap of 0 corresponds to unlimited supplying\n if (supplyCap != 0) {\n uint totalCash = SToken(sToken).getCash();\n
                                                                 uint totalBorrows = SToken(sToken).totalBorrows();\n uint totalReserves = SToken(sToken).totalReserves();\n //
                                                                totalSupplies = totalCash + totalBorrows - totalReserves\n (MathError mathErr, uint totalSupplies) = addThenSubUInt(totalCash,
                                                                totalBorrows, totalReserves);\n require(mathErr == MathError.NO_ERROR, \"totalSupplies failed\");\n\n uint nextTotalSupplies
                                                                = add_(totalSupplies, mintAmount);\n require(nextTotalSupplies \u003c supplyCap, \"market supply cap reached\");\n }\n\n
                                                                // Keep the flywheel moving\n updateStrikeSupplyIndex(sToken);\n distributeSupplierStrike(sToken, minter);\n\n return uint
                                                                (Error.NO_ERROR);\n }\n\n /**\n * @notice Validates mint and reverts on rejection. May emit logs.\n * @param sToken Asset being
                                                                minted\n * @param minter The address minting the tokens\n * @param actualMintAmount The amount of the underlying asset being minted\n *
                                                                @param mintTokens The number of tokens being minted\n */\n function mintVerify(address sToken, address minter, uint actualMintAmount, uint
                                                                mintTokens) external {\n // Shh - currently unused\n sToken;\n minter;\n actualMintAmount;\n mintTokens;\n
                                                                }\n\n /**\n * @notice Checks if the account should be allowed to redeem tokens in the given market\n * @param sToken The market to
                                                                verify the redeem against\n * @param redeemer The account which would redeem the tokens\n * @param redeemTokens The number of sTokens to
                                                                exchange for the underlying asset in the market\n * @return 0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter
                                                                .sol)\n */\n function redeemAllowed(address sToken, address redeemer, uint redeemTokens) external onlyProtocolAllowed returns (uint) {\n
                                                                 uint allowed = redeemAllowedInternal(sToken, redeemer, redeemTokens);\n if (allowed != uint(Error.NO_ERROR)) {\n return
                                                                allowed;\n }\n\n // Keep the flywheel moving\n updateStrikeSupplyIndex(sToken);\n distributeSupplierStrike(sToken,
                                                                redeemer);\n\n return uint(Error.NO_ERROR);\n }\n\n function redeemAllowedInternal(address sToken, address redeemer, uint redeemTokens
                                                                ) internal view returns (uint) {\n if (!markets[sToken].isListed) {\n return uint(Error.MARKET_NOT_LISTED);\n }\n\n
                                                                 /* If the redeemer is not \u0027in\u0027 the market, then we can bypass the liquidity check */\n if (!markets[sToken]
                                                                .accountMembership[redeemer]) {\n return uint(Error.NO_ERROR);\n }\n\n /* Otherwise, perform a hypothetical liquidity
                                                                check to guard against shortfall */\n (Error err, , uint shortfall) = getHypotheticalAccountLiquidityInternal(redeemer, SToken(sToken),
                                                                redeemTokens, 0);\n if (err != Error.NO_ERROR) {\n return uint(err);\n }\n if (shortfall \u003e 0) {\n
                                                                return uint(Error.INSUFFICIENT_LIQUIDITY);\n }\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Validates redeem
                                                                and reverts on rejection. May emit logs.\n * @param sToken Asset being redeemed\n * @param redeemer The address redeeming the tokens\n
                                                                * @param redeemAmount The amount of the underlying asset being redeemed\n * @param redeemTokens The number of tokens being redeemed\n */\n
                                                                 function redeemVerify(address sToken, address redeemer, uint redeemAmount, uint redeemTokens) external {\n // Shh - currently unused\n
                                                                 sToken;\n redeemer;\n\n // Require tokens is zero or amount is also zero\n if (redeemTokens == 0 \u0026\u0026
                                                                redeemAmount \u003e 0) {\n revert(\"redeemTokens zero\");\n }\n }\n\n /**\n * @notice Checks if the account should be
                                                                allowed to borrow the underlying asset of the given market\n * @param sToken The market to verify the borrow against\n * @param borrower
                                                                The account which would borrow the asset\n * @param borrowAmount The amount of underlying the account would borrow\n * @return 0 if the
                                                                borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\n */\n function borrowAllowed(address sToken, address borrower
                                                                , uint borrowAmount) external onlyProtocolAllowed returns (uint) {\n // Pausing is a very serious situation - we revert to sound the
                                                                alarms\n require(!borrowGuardianPaused[sToken], \"borrow is paused\");\n\n if (!markets[sToken].isListed) {\n return uint
                                                                (Error.MARKET_NOT_LISTED);\n }\n\n if (!markets[sToken].accountMembership[borrower]) {\n // only sTokens may call
                                                                borrowAllowed if borrower not in market\n require(msg.sender == sToken, \"sender must be sToken\");\n\n // attempt to add
                                                                borrower to the market\n Error err = addToMarketInternal(SToken(msg.sender), borrower);\n if (err != Error.NO_ERROR) {\n
                                                                 return uint(err);\n }\n\n // it should be impossible to break the important invariant\n assert
                                                                (markets[sToken].accountMembership[borrower]);\n }\n\n if (oracle.getUnderlyingPrice(SToken(sToken)) == 0) {\n return uint
                                                                (Error.PRICE_ERROR);\n }\n\n uint borrowCap = borrowCaps[sToken];\n // Borrow cap of 0 corresponds to unlimited borrowing\n
                                                                 if (borrowCap != 0) {\n uint totalBorrows = SToken(sToken).totalBorrows();\n (MathError mathErr, uint nextTotalBorrows)
                                                                = addUInt(totalBorrows, borrowAmount);\n require(mathErr == MathError.NO_ERROR, \"total borrows overflow\");\n require
                                                                (nextTotalBorrows \u003c borrowCap, \"market borrow cap reached\");\n }\n\n (Error err, , uint shortfall) =
                                                                getHypotheticalAccountLiquidityInternal(borrower, SToken(sToken), 0, borrowAmount);\n if (err != Error.NO_ERROR) {\n return uint
                                                                (err);\n }\n if (shortfall \u003e 0) {\n return uint(Error.INSUFFICIENT_LIQUIDITY);\n }\n\n // Keep the
                                                                flywheel moving\n Exp memory borrowIndex = Exp({mantissa: SToken(sToken).borrowIndex()});\n updateStrikeBorrowIndex(sToken,
                                                                borrowIndex);\n distributeBorrowerStrike(sToken, borrower, borrowIndex);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n *
                                                                @notice Validates borrow and reverts on rejection. May emit logs.\n * @param sToken Asset whose underlying is being borrowed\n * @param
                                                                borrower The address borrowing the underlying\n * @param borrowAmount The amount of the underlying asset requested to borrow\n */\n
                                                                function borrowVerify(address sToken, address borrower, uint borrowAmount) external {\n // Shh - currently unused\n sToken;\n
                                                                borrower;\n borrowAmount;\n }\n\n /**\n * @notice Checks if the account should be allowed to repay a borrow in the given market\n
                                                                 * @param sToken The market to verify the repay against\n * @param payer The account which would repay the asset\n * @param borrower The
                                                                account which would borrowed the asset\n * @param repayAmount The amount of the underlying asset the account would repay\n * @return 0 if
                                                                the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\n */\n function repayBorrowAllowed(\n address sToken
                                                                ,\n address payer,\n address borrower,\n uint repayAmount) external onlyProtocolAllowed returns (uint) {\n // Shh -
                                                                currently unused\n payer;\n borrower;\n repayAmount;\n\n if (!markets[sToken].isListed) {\n return uint
                                                                (Error.MARKET_NOT_LISTED);\n }\n\n // Keep the flywheel moving\n Exp memory borrowIndex = Exp({mantissa: SToken(sToken
                                                                ).borrowIndex()});\n updateStrikeBorrowIndex(sToken, borrowIndex);\n distributeBorrowerStrike(sToken, borrower, borrowIndex);\n\n
                                                                 return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Validates repayBorrow and reverts on rejection. May emit logs.\n * @param
                                                                sToken Asset being repaid\n * @param payer The address repaying the borrow\n * @param borrower The address of the borrower\n * @param
                                                                actualRepayAmount The amount of underlying being repaid\n */\n function repayBorrowVerify(\n address sToken,\n address payer
                                                                ,\n address borrower,\n uint actualRepayAmount,\n uint borrowerIndex) external {\n // Shh - currently unused\n
                                                                sToken;\n payer;\n borrower;\n actualRepayAmount;\n borrowerIndex;\n }\n\n /**\n * @notice Checks if the
                                                                liquidation should be allowed to occur\n * @param sTokenBorrowed Asset which was borrowed by the borrower\n * @param sTokenCollateral Asset
                                                                which was used as collateral and will be seized\n * @param liquidator The address repaying the borrow and seizing the collateral\n * @param
                                                                borrower The address of the borrower\n * @param repayAmount The amount of underlying being repaid\n */\n function liquidateBorrowAllowed
                                                                (\n address sTokenBorrowed,\n address sTokenCollateral,\n address liquidator,\n address borrower,\n uint
                                                                repayAmount) external onlyProtocolAllowed returns (uint) {\n // Shh - currently unused\n liquidator;\n\n if
                                                                (!markets[sTokenBorrowed].isListed || !markets[sTokenCollateral].isListed) {\n return uint(Error.MARKET_NOT_LISTED);\n }\n\n
                                                                 /* The borrower must have shortfall in order to be liquidatable */\n (Error err, , uint shortfall) = getAccountLiquidityInternal(borrower
                                                                );\n if (err != Error.NO_ERROR) {\n return uint(err);\n }\n if (shortfall == 0) {\n return uint(Error
                                                                .INSUFFICIENT_SHORTFALL);\n }\n\n /* The liquidator may not repay more than what is allowed by the closeFactor */\n uint
                                                                borrowBalance = SToken(sTokenBorrowed).borrowBalanceStored(borrower);\n (MathError mathErr, uint maxClose) = mulScalarTruncate(Exp({mantissa
                                                                : closeFactorMantissa}), borrowBalance);\n if (mathErr != MathError.NO_ERROR) {\n return uint(Error.MATH_ERROR);\n }\n
                                                                 if (repayAmount \u003e maxClose) {\n return uint(Error.TOO_MUCH_REPAY);\n }\n\n return uint(Error.NO_ERROR);\n
                                                                }\n\n /**\n * @notice Validates liquidateBorrow and reverts on rejection. May emit logs.\n * @param sTokenBorrowed Asset which was
                                                                borrowed by the borrower\n * @param sTokenCollateral Asset which was used as collateral and will be seized\n * @param liquidator The
                                                                address repaying the borrow and seizing the collateral\n * @param borrower The address of the borrower\n * @param actualRepayAmount The
                                                                amount of underlying being repaid\n */\n function liquidateBorrowVerify(\n address sTokenBorrowed,\n address sTokenCollateral
                                                                ,\n address liquidator,\n address borrower,\n uint actualRepayAmount,\n uint seizeTokens) external {\n // Shh -
                                                                currently unused\n sTokenBorrowed;\n sTokenCollateral;\n liquidator;\n borrower;\n actualRepayAmount;\n
                                                                seizeTokens;\n }\n\n /**\n * @notice Checks if the seizing of assets should be allowed to occur\n * @param sTokenCollateral Asset
                                                                which was used as collateral and will be seized\n * @param sTokenBorrowed Asset which was borrowed by the borrower\n * @param liquidator
                                                                The address repaying the borrow and seizing the collateral\n * @param borrower The address of the borrower\n * @param seizeTokens The
                                                                number of collateral tokens to seize\n */\n function seizeAllowed(\n address sTokenCollateral,\n address sTokenBorrowed,\n
                                                                 address liquidator,\n address borrower,\n uint seizeTokens) external onlyProtocolAllowed returns (uint) {\n // Pausing is
                                                                a very serious situation - we revert to sound the alarms\n\n // Shh - currently unused\n seizeTokens;\n\n if
                                                                (!markets[sTokenCollateral].isListed || !markets[sTokenBorrowed].isListed) {\n return uint(Error.MARKET_NOT_LISTED);\n }\n\n
                                                                 if (SToken(sTokenCollateral).comptroller() != SToken(sTokenBorrowed).comptroller()) {\n return uint(Error.COMPTROLLER_MISMATCH);\n
                                                                 }\n\n // Keep the flywheel moving\n updateStrikeSupplyIndex(sTokenCollateral);\n distributeSupplierStrike
                                                                (sTokenCollateral, borrower);\n distributeSupplierStrike(sTokenCollateral, liquidator);\n\n return uint(Error.NO_ERROR);\n }\n\n
                                                                 /**\n * @notice Validates seize and reverts on rejection. May emit logs.\n * @param sTokenCollateral Asset which was used as collateral
                                                                and will be seized\n * @param sTokenBorrowed Asset which was borrowed by the borrower\n * @param liquidator The address repaying the borrow
                                                                and seizing the collateral\n * @param borrower The address of the borrower\n * @param seizeTokens The number of collateral tokens to
                                                                seize\n */\n function seizeVerify(\n address sTokenCollateral,\n address sTokenBorrowed,\n address liquidator,\n
                                                                 address borrower,\n uint seizeTokens) external {\n // Shh - currently unused\n sTokenCollateral;\n sTokenBorrowed;\n
                                                                 liquidator;\n borrower;\n seizeTokens;\n }\n\n /**\n * @notice Checks if the account should be allowed to transfer
                                                                tokens in the given market\n * @param sToken The market to verify the transfer against\n * @param src The account which sources the
                                                                tokens\n * @param dst The account which receives the tokens\n * @param transferTokens The number of sTokens to transfer\n * @return 0
                                                                if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\n */\n function transferAllowed(address sToken,
                                                                address src, address dst, uint transferTokens) external onlyProtocolAllowed returns (uint) {\n // Pausing is a very serious situation - we
                                                                revert to sound the alarms\n\n // Currently the only consideration is whether or not\n // the src is allowed to redeem this many
                                                                tokens\n uint allowed = redeemAllowedInternal(sToken, src, transferTokens);\n if (allowed != uint(Error.NO_ERROR)) {\n
                                                                return allowed;\n }\n\n // Keep the flywheel moving\n updateStrikeSupplyIndex(sToken);\n distributeSupplierStrike
                                                                (sToken, src);\n distributeSupplierStrike(sToken, dst);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Validates
                                                                transfer and reverts on rejection. May emit logs.\n * @param sToken Asset being transferred\n * @param src The account which sources the
                                                                tokens\n * @param dst The account which receives the tokens\n * @param transferTokens The number of sTokens to transfer\n */\n
                                                                function transferVerify(address sToken, address src, address dst, uint transferTokens) external {\n // Shh - currently unused\n
                                                                sToken;\n src;\n dst;\n transferTokens;\n }\n\n /*** Liquidity/Liquidation Calculations ***/\n\n /**\n * @dev
                                                                Local vars for avoiding stack-depth limits in calculating account liquidity.\n * Note that `sTokenBalance` is the number of sTokens the
                                                                account owns in the market,\n * whereas `borrowBalance` is the amount of underlying that the account has borrowed.\n */\n struct
                                                                AccountLiquidityLocalVars {\n uint sumCollateral;\n uint sumBorrowPlusEffects;\n uint sTokenBalance;\n uint
                                                                borrowBalance;\n uint exchangeRateMantissa;\n uint oraclePriceMantissa;\n Exp collateralFactor;\n Exp exchangeRate;\n
                                                                 Exp oraclePrice;\n Exp tokensToDenom;\n }\n\n /**\n * @notice Determine the current account liquidity wrt collateral
                                                                requirements\n * @return (possible error code (semi-opaque),\n account liquidity in excess of collateral requirements,\n *
                                                                 account shortfall below collateral requirements)\n */\n function getAccountLiquidity(address account) public view returns (uint,
                                                                uint, uint) {\n (Error err, uint liquidity, uint shortfall) = getHypotheticalAccountLiquidityInternal(account, SToken(0), 0, 0);\n\n
                                                                return (uint(err), liquidity, shortfall);\n }\n\n /**\n * @notice Determine the current account liquidity wrt collateral requirements\n
                                                                 * @return (possible error code,\n account liquidity in excess of collateral requirements,\n * account shortfall
                                                                below collateral requirements)\n */\n function getAccountLiquidityInternal(address account) internal view returns (Error, uint, uint) {\n
                                                                 return getHypotheticalAccountLiquidityInternal(account, SToken(0), 0, 0);\n }\n\n /**\n * @notice Determine what the account
                                                                liquidity would be if the given amounts were redeemed/borrowed\n * @param sTokenModify The market to hypothetically redeem/borrow in\n *
                                                                @param account The account to determine liquidity for\n * @param redeemTokens The number of tokens to hypothetically redeem\n * @param
                                                                borrowAmount The amount of underlying to hypothetically borrow\n * @return (possible error code (semi-opaque),\n hypothetical
                                                                account liquidity in excess of collateral requirements,\n * hypothetical account shortfall below collateral requirements)\n */\n
                                                                 function getHypotheticalAccountLiquidity(\n address account,\n address sTokenModify,\n uint redeemTokens,\n uint
                                                                borrowAmount) public view returns (uint, uint, uint) {\n (Error err, uint liquidity, uint shortfall) =
                                                                getHypotheticalAccountLiquidityInternal(account, SToken(sTokenModify), redeemTokens, borrowAmount);\n return (uint(err), liquidity,
                                                                shortfall);\n }\n\n /**\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\n *
                                                                @param sTokenModify The market to hypothetically redeem/borrow in\n * @param account The account to determine liquidity for\n * @param
                                                                redeemTokens The number of tokens to hypothetically redeem\n * @param borrowAmount The amount of underlying to hypothetically borrow\n *
                                                                @dev Note that we calculate the exchangeRateStored for each collateral sToken using stored data,\n * without calculating accumulated interest
                                                                .\n * @return (possible error code,\n hypothetical account liquidity in excess of collateral requirements,\n *
                                                                hypothetical account shortfall below collateral requirements)\n */\n function getHypotheticalAccountLiquidityInternal(\n address
                                                                account,\n SToken sTokenModify,\n uint redeemTokens,\n uint borrowAmount) internal view returns (Error, uint, uint) {\n\n
                                                                 AccountLiquidityLocalVars memory vars; // Holds all our calculation results\n uint oErr;\n MathError mErr;\n\n // For each
                                                                asset the account is in\n SToken[] memory assets = accountAssets[account];\n for (uint i = 0; i \u003c assets.length; i++) {\n
                                                                 SToken asset = assets[i];\n\n // Read the balances and exchange rate from the sToken\n (oErr, vars.sTokenBalance, vars
                                                                .borrowBalance, vars.exchangeRateMantissa) = asset.getAccountSnapshot(account);\n if (oErr != 0) { // semi-opaque error code, we assume
                                                                NO_ERROR == 0 is invariant between upgrades\n return (Error.SNAPSHOT_ERROR, 0, 0);\n }\n vars.collateralFactor
                                                                = Exp({mantissa: markets[address(asset)].collateralFactorMantissa});\n vars.exchangeRate = Exp({mantissa: vars.exchangeRateMantissa}
                                                                );\n\n // Get the normalized price of the asset\n vars.oraclePriceMantissa = oracle.getUnderlyingPrice(asset);\n
                                                                if (vars.oraclePriceMantissa == 0) {\n return (Error.PRICE_ERROR, 0, 0);\n }\n vars.oraclePrice = Exp
                                                                ({mantissa: vars.oraclePriceMantissa});\n\n // Pre-compute a conversion factor from tokens -\u003e ether (normalized price value)\n
                                                                 (mErr, vars.tokensToDenom) = mulExp3(vars.collateralFactor, vars.exchangeRate, vars.oraclePrice);\n if (mErr != MathError
                                                                .NO_ERROR) {\n return (Error.MATH_ERROR, 0, 0);\n }\n\n // sumCollateral += tokensToDenom * sTokenBalance\n
                                                                 (mErr, vars.sumCollateral) = mulScalarTruncateAddUInt(vars.tokensToDenom, vars.sTokenBalance, vars.sumCollateral);\n if (mErr !
                                                                = MathError.NO_ERROR) {\n return (Error.MATH_ERROR, 0, 0);\n }\n\n // sumBorrowPlusEffects += oraclePrice *
                                                                borrowBalance\n (mErr, vars.sumBorrowPlusEffects) = mulScalarTruncateAddUInt(vars.oraclePrice, vars.borrowBalance, vars
                                                                .sumBorrowPlusEffects);\n if (mErr != MathError.NO_ERROR) {\n return (Error.MATH_ERROR, 0, 0);\n }\n\n
                                                                 // Calculate effects of interacting with sTokenModify\n if (asset == sTokenModify) {\n // redeem effect\n
                                                                 // sumBorrowPlusEffects += tokensToDenom * redeemTokens\n (mErr, vars.sumBorrowPlusEffects) = mulScalarTruncateAddUInt(vars
                                                                .tokensToDenom, redeemTokens, vars.sumBorrowPlusEffects);\n if (mErr != MathError.NO_ERROR) {\n return (Error
                                                                .MATH_ERROR, 0, 0);\n }\n\n // borrow effect\n // sumBorrowPlusEffects += oraclePrice * borrowAmount\n
                                                                 (mErr, vars.sumBorrowPlusEffects) = mulScalarTruncateAddUInt(vars.oraclePrice, borrowAmount, vars.sumBorrowPlusEffects);\n
                                                                 if (mErr != MathError.NO_ERROR) {\n return (Error.MATH_ERROR, 0, 0);\n }\n }\n }\n\n
                                                                 // These are safe, as the underflow condition is checked first\n if (vars.sumCollateral \u003e vars.sumBorrowPlusEffects) {\n
                                                                return (Error.NO_ERROR, vars.sumCollateral - vars.sumBorrowPlusEffects, 0);\n } else {\n return (Error.NO_ERROR, 0, vars
                                                                .sumBorrowPlusEffects - vars.sumCollateral);\n }\n }\n\n /**\n * @notice Calculate number of tokens of collateral asset to seize
                                                                given an underlying amount\n * @dev Used in liquidation (called in sToken.liquidateBorrowFresh)\n * @param sTokenBorrowed The address of
                                                                the borrowed sToken\n * @param sTokenCollateral The address of the collateral sToken\n * @param actualRepayAmount The amount of
                                                                sTokenBorrowed underlying to convert into sTokenCollateral tokens\n * @return (errorCode, number of sTokenCollateral tokens to be seized in a
                                                                liquidation)\n */\n function liquidateCalculateSeizeTokens(address sTokenBorrowed, address sTokenCollateral, uint actualRepayAmount)
                                                                external view returns (uint, uint) {\n /* Read oracle prices for borrowed and collateral markets */\n uint priceBorrowedMantissa =
                                                                oracle.getUnderlyingPrice(SToken(sTokenBorrowed));\n uint priceCollateralMantissa = oracle.getUnderlyingPrice(SToken(sTokenCollateral));\n
                                                                 if (priceBorrowedMantissa == 0 || priceCollateralMantissa == 0) {\n return (uint(Error.PRICE_ERROR), 0);\n }\n\n
                                                                /*\n * Get the exchange rate and calculate the number of collateral tokens to seize:\n * seizeAmount = actualRepayAmount *
                                                                liquidationIncentive * priceBorrowed / priceCollateral\n * seizeTokens = seizeAmount / exchangeRate\n * = actualRepayAmount *
                                                                (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate)\n */\n uint exchangeRateMantissa = SToken(sTokenCollateral
                                                                ).exchangeRateStored(); // Note: reverts on error\n uint seizeTokens;\n Exp memory numerator;\n Exp memory denominator;\n
                                                                 Exp memory ratio;\n MathError mathErr;\n\n (mathErr, numerator) = mulExp(liquidationIncentiveMantissa, priceBorrowedMantissa);\n
                                                                 if (mathErr != MathError.NO_ERROR) {\n return (uint(Error.MATH_ERROR), 0);\n }\n\n (mathErr, denominator) = mulExp
                                                                (priceCollateralMantissa, exchangeRateMantissa);\n if (mathErr != MathError.NO_ERROR) {\n return (uint(Error.MATH_ERROR), 0);\n
                                                                 }\n\n (mathErr, ratio) = divExp(numerator, denominator);\n if (mathErr != MathError.NO_ERROR) {\n return (uint(Error
                                                                .MATH_ERROR), 0);\n }\n\n (mathErr, seizeTokens) = mulScalarTruncate(ratio, actualRepayAmount);\n if (mathErr != MathError
                                                                .NO_ERROR) {\n return (uint(Error.MATH_ERROR), 0);\n }\n\n return (uint(Error.NO_ERROR), seizeTokens);\n }\n\n /***
                                                                Admin Functions ***/\n\n /**\n * @notice Sets a new price oracle for the comptroller\n * @dev Admin function to set a new price
                                                                oracle\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setPriceOracle(PriceOracle
                                                                newOracle) public returns (uint) {\n // Check caller is admin\n if (msg.sender != admin) {\n return fail(Error
                                                                .UNAUTHORIZED, FailureInfo.SET_PRICE_ORACLE_OWNER_CHECK);\n }\n\n // Track the old oracle for the comptroller\n PriceOracle
                                                                oldOracle = oracle;\n\n // Set comptroller\u0027s oracle to newOracle\n oracle = newOracle;\n\n // Emit NewPriceOracle
                                                                (oldOracle, newOracle)\n emit NewPriceOracle(oldOracle, newOracle);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n *
                                                                @notice Sets the closeFactor used when liquidating borrows\n * @dev Admin function to set closeFactor\n * @param newCloseFactorMantissa
                                                                New close factor, scaled by 1e18\n * @return uint 0=success, otherwise a failure\n */\n function _setCloseFactor(uint
                                                                newCloseFactorMantissa) external returns (uint) {\n // Check caller is admin\n \trequire(msg.sender == admin, \"only admin can set close
                                                                factor\");\n\n uint oldCloseFactorMantissa = closeFactorMantissa;\n closeFactorMantissa = newCloseFactorMantissa;\n emit
                                                                NewCloseFactor(oldCloseFactorMantissa, closeFactorMantissa);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Sets the
                                                                collateralFactor for a market\n * @dev Admin function to set per-market collateralFactor\n * @param sToken The market to set the factor
                                                                on\n * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18\n * @return uint 0=success, otherwise a failure. (See
                                                                ErrorReporter for details)\n */\n function _setCollateralFactor(SToken sToken, uint newCollateralFactorMantissa) external returns (uint)
                                                                {\n // Check caller is admin\n if (msg.sender != admin) {\n return fail(Error.UNAUTHORIZED, FailureInfo
                                                                .SET_COLLATERAL_FACTOR_OWNER_CHECK);\n }\n\n // Verify market is listed\n Market storage market = markets[address(sToken)];\n
                                                                 if (!market.isListed) {\n return fail(Error.MARKET_NOT_LISTED, FailureInfo.SET_COLLATERAL_FACTOR_NO_EXISTS);\n }\n\n
                                                                 Exp memory newCollateralFactorExp = Exp({mantissa: newCollateralFactorMantissa});\n\n // Check collateral factor \u003c= 0.9\n Exp
                                                                memory highLimit = Exp({mantissa: collateralFactorMaxMantissa});\n if (lessThanExp(highLimit, newCollateralFactorExp)) {\n return
                                                                fail(Error.INVALID_COLLATERAL_FACTOR, FailureInfo.SET_COLLATERAL_FACTOR_VALIDATION);\n }\n\n // If collateral factor != 0, fail if
                                                                price == 0\n if (newCollateralFactorMantissa != 0 \u0026\u0026 oracle.getUnderlyingPrice(sToken) == 0) {\n return fail(Error
                                                                .PRICE_ERROR, FailureInfo.SET_COLLATERAL_FACTOR_WITHOUT_PRICE);\n }\n\n // Set market\u0027s collateral factor to new collateral
                                                                factor, remember old value\n uint oldCollateralFactorMantissa = market.collateralFactorMantissa;\n market.collateralFactorMantissa =
                                                                newCollateralFactorMantissa;\n\n // Emit event with asset, old collateral factor, and new collateral factor\n emit
                                                                NewCollateralFactor(sToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n
                                                                 * @notice Sets liquidationIncentive\n * @dev Admin function to set liquidationIncentive\n * @param newLiquidationIncentiveMantissa
                                                                New liquidationIncentive scaled by 1e18\n * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\n */\n
                                                                function _setLiquidationIncentive(uint newLiquidationIncentiveMantissa) external returns (uint) {\n // Check caller is admin\n if
                                                                (msg.sender != admin) {\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_LIQUIDATION_INCENTIVE_OWNER_CHECK);\n }\n\n //
                                                                Save current value for use in log\n uint oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa;\n\n // Set liquidation
                                                                incentive to new incentive\n liquidationIncentiveMantissa = newLiquidationIncentiveMantissa;\n\n // Emit event with old incentive,
                                                                new incentive\n emit NewLiquidationIncentive(oldLiquidationIncentiveMantissa, newLiquidationIncentiveMantissa);\n\n return uint(Error
                                                                .NO_ERROR);\n }\n\n /**\n * @notice Add the market to the markets mapping and set it as listed\n * @dev Admin function to set
                                                                isListed and add support for the market\n * @param sToken The address of the market (token) to list\n * @return uint 0=success, otherwise
                                                                a failure. (See enum Error for details)\n */\n function _supportMarket(SToken sToken) external returns (uint) {\n if (msg.sender !=
                                                                admin) {\n return fail(Error.UNAUTHORIZED, FailureInfo.SUPPORT_MARKET_OWNER_CHECK);\n }\n\n if (markets[address(sToken)]
                                                                .isListed) {\n return fail(Error.MARKET_ALREADY_LISTED, FailureInfo.SUPPORT_MARKET_EXISTS);\n }\n\n sToken.isSToken(); //
                                                                Sanity check to make sure its really a SToken\n\n markets[address(sToken)] = Market({isListed: true, isStriked: false,
                                                                collateralFactorMantissa: 0});\n\n _addMarketInternal(address(sToken));\n _initializeMarket(address(sToken));\n\n emit
                                                                MarketListed(sToken);\n\n return uint(Error.NO_ERROR);\n }\n\n function _initializeMarket(address sToken) internal {\n uint32
                                                                blockNumber = safe32(getBlockNumber(), \"block number exceeds 32 bits\");\n\n StrikeMarketState storage supplyState =
                                                                strikeSupplyState[sToken];\n StrikeMarketState storage borrowState = strikeBorrowState[sToken];\n\n /*\n * Update market
                                                                state indices\n */\n if (supplyState.index == 0) {\n // Initialize supply state index with default value\n
                                                                supplyState.index = strikeInitialIndex;\n }\n\n if (borrowState.index == 0) {\n // Initialize borrow state index with
                                                                default value\n borrowState.index = strikeInitialIndex;\n }\n\n supplyState.block = borrowState.block = blockNumber;\n
                                                                }\n\n function _addMarketInternal(address sToken) internal {\n for (uint i = 0; i \u003c allMarkets.length; i ++) {\n require
                                                                (allMarkets[i] != SToken(sToken), \"market already added\");\n }\n allMarkets.push(SToken(sToken));\n }\n\n /**\n * @notice
                                                                Admin function to change the Pause Guardian\n * @param newPauseGuardian The address of the new Pause Guardian\n * @return uint 0=success,
                                                                otherwise a failure. (See enum Error for details)\n */\n function _setPauseGuardian(address newPauseGuardian) public returns (uint) {\n
                                                                 if (msg.sender != admin) {\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PAUSE_GUARDIAN_OWNER_CHECK);\n }\n\n //
                                                                Save current value for inclusion in log\n address oldPauseGuardian = pauseGuardian;\n\n // Store pauseGuardian with value
                                                                newPauseGuardian\n pauseGuardian = newPauseGuardian;\n\n // Emit NewPauseGuardian(OldPauseGuardian, NewPauseGuardian)\n emit
                                                                NewPauseGuardian(oldPauseGuardian, pauseGuardian);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Set whole protocol
                                                                pause/unpause state\n */\n function _setProtocolPaused(bool state) public validPauseState(state) returns(bool) {\n protocolPaused =
                                                                state;\n emit ActionProtocolPaused(state);\n return state;\n }\n\n function _setBorrowPaused(SToken sToken, bool state) public
                                                                returns (bool) {\n require(markets[address(sToken)].isListed, \"cannot pause a market that is not listed\");\n require(msg.sender ==
                                                                pauseGuardian || msg.sender == admin, \"only pause guardian and admin can pause\");\n require(msg.sender == admin || state == true, \"only
                                                                admin can unpause\");\n\n borrowGuardianPaused[address(sToken)] = state;\n emit ActionPaused(sToken, \"Borrow\", state);\n
                                                                return state;\n }\n\n function _setReserveInfo(address payable newReserveGuardian, address payable newReserveAddress) external returns (uint)
                                                                {\n // Check caller is admin or reserveGuardian\n if (!(msg.sender == admin || msg.sender == reserveGuardian)) {\n return
                                                                fail(Error.UNAUTHORIZED, FailureInfo.SET_RESERVE_GUARDIAN_OWNER_CHECK);\n }\n\n address payable oldReserveGuardian = reserveGuardian
                                                                ;\n address payable oldReserveAddress = reserveAddress;\n\n reserveGuardian = newReserveGuardian;\n reserveAddress =
                                                                newReserveAddress;\n\n // Emit NewReserveGuardian(OldReserveGuardian, NewReserveGuardian, OldReserveAddress, NewReserveAddress)\n
                                                                emit NewReserveGuardian(oldReserveGuardian, newReserveGuardian, oldReserveAddress, newReserveAddress);\n\n return uint(Error.NO_ERROR);\n
                                                                 }\n\n function _setStrkStakingInfo(address newStrkStaking) external returns (uint) {\n require(msg.sender == admin, \"only admin can set
                                                                strk staking info\");\n\n address oldStrkStaking = strkStaking;\n\n strkStaking = newStrkStaking;\n\n // Emit
                                                                NewStrkStakingInfo(OldStrkStaking, NewStrkStaking)\n emit NewStrkStakingInfo(oldStrkStaking, newStrkStaking);\n\n return uint(Error
                                                                .NO_ERROR);\n }\n\n /**\n * @notice Admin function to change the Market Cap Guardian\n * @param newMarketCapGuardian The address of
                                                                the new Market Cap Guardian\n */\n function _setMarketCapGuardian(address newMarketCapGuardian) external {\n require(msg.sender ==
                                                                admin, \"only admin can set market cap guardian\");\n\n // Save current value for inclusion in log\n address oldMarketCapGuardian =
                                                                marketCapGuardian;\n\n // Store marketCapGuardian with value newMarketCapGuardian\n marketCapGuardian = newMarketCapGuardian;\n\n
                                                                 // Emit NewMarketCapGuardian(OldMarketCapGuardian, NewMarketCapGuardian)\n emit NewMarketCapGuardian(oldMarketCapGuardian,
                                                                newMarketCapGuardian);\n }\n\n /**\n * @notice Set the given market caps for the given sToken markets.\n * @dev Admin or
                                                                marketCapGuardian function to set the market caps.\n * @param sTokens The addresses of the markets (tokens) to change the market caps for\n
                                                                 * @param newSupplyCaps The new supply cap values in underlying to be set. A value of 0 corresponds to unlimited supplying.\n * @param
                                                                newBorrowCaps The new borrow cap values in underlying to be set. A value of 0 corresponds to unlimited borrowing.\n */\n function
                                                                _setMarketCaps(SToken[] calldata sTokens, uint[] calldata newSupplyCaps, uint[] calldata newBorrowCaps) external {\n require(msg.sender ==
                                                                admin || msg.sender == marketCapGuardian, \"only admin or market cap guardian can set supply caps\");\n\n uint numMarkets = sTokens.length
                                                                ;\n uint numSupplyCaps = newSupplyCaps.length;\n uint numBorrowCaps = newBorrowCaps.length;\n\n require(numMarkets != 0
                                                                \u0026\u0026 numMarkets == numSupplyCaps \u0026\u0026 numMarkets == numBorrowCaps, \"invalid input\");\n\n for (uint i = 0; i \u003c
                                                                numMarkets; i++) {\n supplyCaps[address(sTokens[i])] = newSupplyCaps[i];\n borrowCaps[address(sTokens[i])] = newBorrowCaps[i]
                                                                ;\n emit NewMarketCap(sTokens[i], newSupplyCaps[i], newBorrowCaps[i]);\n }\n }\n\n function _become(Unitroller unitroller)
                                                                public {\n require(msg.sender == unitroller.admin(), \"only unitroller admin can change brains\");\n require(unitroller
                                                                ._acceptImplementation() == 0, \"change not authorized\");\n }\n\n /**\n * @notice Checks caller is admin, or this contract is becoming
                                                                the new implementation\n */\n function adminOrInitializing() internal view returns (bool) {\n return msg.sender == admin || msg
                                                                .sender == comptrollerImplementation;\n }\n\n /*** STRK Distribution ***/\n\n /**\n * @notice Set STRK speed for a single market\n
                                                                 * @param sToken The market whose STRK speed to update\n * @param supplySpeeds New supply-side STRK speed for market\n * @param
                                                                borrowSpeeds New borrow-side STRK speed for market\n */\n function _setStrikeSpeeds(SToken[] memory sToken, uint[] memory supplySpeeds,
                                                                uint[] memory borrowSpeeds) public {\n require(adminOrInitializing(), \"only admin can set strike speed\");\n\n uint numTokens =
                                                                sToken.length;\n require(numTokens == supplySpeeds.length \u0026\u0026 numTokens == borrowSpeeds.length, \"Comptroller::_setCompSpeeds
                                                                invalid input\");\n\n for (uint i = 0; i \u003c numTokens; ++i) {\n setStrikeSpeedInternal(sToken[i], supplySpeeds[i],
                                                                borrowSpeeds[i]);\n }\n }\n\n function setStrikeSpeedInternal(SToken sToken, uint supplySpeed, uint borrowSpeed) internal {\n
                                                                Market storage market = markets[address(sToken)];\n require(market.isListed, \"strike market is not listed\");\n\n if
                                                                (strikeSupplySpeeds[address(sToken)] != supplySpeed) {\n updateStrikeSupplyIndex(address(sToken));\n
                                                                strikeSupplySpeeds[address(sToken)] = supplySpeed;\n emit StrikeSupplySpeedUpdated(sToken, supplySpeed);\n }\n\n if
                                                                (strikeBorrowSpeeds[address(sToken)] != borrowSpeed) {\n Exp memory borrowIndex = Exp({mantissa: sToken.borrowIndex()});\n
                                                                updateStrikeBorrowIndex(address(sToken), borrowIndex);\n\n // Update speed and emit event\n strikeBorrowSpeeds[address(sToken
                                                                )] = borrowSpeed;\n emit StrikeBorrowSpeedUpdated(sToken, borrowSpeed);\n }\n }\n\n /**\n * @notice Accrue STRK to the
                                                                market by updating the supply index\n * @param sToken The market whose supply index to update\n */\n function updateStrikeSupplyIndex
                                                                (address sToken) internal {\n StrikeMarketState storage supplyState = strikeSupplyState[sToken];\n uint supplySpeed =
                                                                strikeSupplySpeeds[sToken];\n uint32 blockNumber = safe32(getBlockNumber(), \"block number exceeds 32 bits\");\n uint deltaBlocks =
                                                                sub_(uint(blockNumber), uint(supplyState.block));\n if (deltaBlocks \u003e 0 \u0026\u0026 supplySpeed \u003e 0) {\n uint
                                                                supplyTokens = SToken(sToken).totalSupply();\n uint strikeAccrued = mul_(deltaBlocks, supplySpeed);\n Double memory ratio =
                                                                supplyTokens \u003e 0 ? fraction(strikeAccrued, supplyTokens) : Double({mantissa: 0});\n supplyState.index = safe224(add_(Double
                                                                ({mantissa: supplyState.index}), ratio).mantissa, \"new index exceeds 224 bits\");\n supplyState.block = blockNumber;\n } else if
                                                                (deltaBlocks \u003e 0) {\n supplyState.block = blockNumber;\n }\n }\n\n /**\n * @notice Accrue STRK to the market by
                                                                updating the borrow index\n * @param sToken The market whose borrow index to update\n */\n function updateStrikeBorrowIndex(address
                                                                sToken, Exp memory marketBorrowIndex) internal {\n StrikeMarketState storage borrowState = strikeBorrowState[sToken];\n uint
                                                                borrowSpeed = strikeBorrowSpeeds[sToken];\n uint32 blockNumber = safe32(getBlockNumber(), \"block number exceeds 32 bits\");\n uint
                                                                deltaBlocks = sub_(uint(blockNumber), uint(borrowState.block));\n if (deltaBlocks \u003e 0 \u0026\u0026 borrowSpeed \u003e 0) {\n
                                                                 uint borrowAmount = div_(SToken(sToken).totalBorrows(), marketBorrowIndex);\n uint strikeAccrued = mul_(deltaBlocks, borrowSpeed);\n
                                                                 Double memory ratio = borrowAmount \u003e 0 ? fraction(strikeAccrued, borrowAmount) : Double({mantissa: 0});\n borrowState
                                                                .index = safe224(add_(Double({mantissa: borrowState.index}), ratio).mantissa, \"new index exceeds 224 bits\");\n borrowState.block =
                                                                blockNumber;\n } else if (deltaBlocks \u003e 0) {\n borrowState.block = blockNumber;\n }\n }\n\n /**\n * @notice
                                                                Calculate STRK accrued by a supplier and possibly transfer it to them\n * @param sToken The market in which the supplier is interacting\n *
                                                                @param supplier The address of the supplier to distribute STRK to\n */\n function distributeSupplierStrike(address sToken, address supplier)
                                                                internal {\n StrikeMarketState storage supplyState = strikeSupplyState[sToken];\n\n uint supplyIndex = supplyState.index;\n
                                                                uint supplierIndex = strikeSupplierIndex[sToken][supplier];\n\n strikeSupplierIndex[sToken][supplier] = supplyIndex;\n\n if
                                                                (supplierIndex == 0 \u0026\u0026 supplyIndex \u003e= strikeInitialIndex) {\n supplierIndex = strikeInitialIndex;\n }\n\n
                                                                Double memory deltaIndex = Double({mantissa: sub_(supplyIndex, supplierIndex)});\n uint supplierTokens = SToken(sToken).balanceOf(supplier
                                                                );\n uint supplierDelta = mul_(supplierTokens, deltaIndex);\n uint supplierAccrued = add_(strikeAccrued[supplier], supplierDelta);\n
                                                                 strikeAccrued[supplier] = supplierAccrued;\n emit DistributedSupplierStrike(SToken(sToken), supplier, supplierDelta, supplyIndex);\n
                                                                 }\n\n /**\n * @notice Calculate STRK accrued by a borrower and possibly transfer it to them\n * @dev Borrowers will not begin to
                                                                accrue until after the first interaction with the protocol.\n * @param sToken The market in which the borrower is interacting\n * @param
                                                                borrower The address of the borrower to distribute STRK to\n */\n function distributeBorrowerStrike(address sToken, address borrower, Exp
                                                                memory marketBorrowIndex) internal {\n StrikeMarketState storage borrowState = strikeBorrowState[sToken];\n\n uint borrowIndex =
                                                                borrowState.index;\n uint borrowerIndex = strikeBorrowerIndex[sToken][borrower];\n\n strikeBorrowerIndex[sToken][borrower] =
                                                                borrowIndex;\n\n if (borrowerIndex == 0 \u0026\u0026 borrowIndex \u003e= strikeInitialIndex) {\n borrowerIndex =
                                                                strikeInitialIndex;\n }\n\n Double memory deltaIndex = Double({mantissa: sub_(borrowIndex, borrowerIndex)});\n uint
                                                                borrowerAmount = div_(SToken(sToken).borrowBalanceStored(borrower), marketBorrowIndex);\n\n // Calculate strike accrued: sTokenAmount *
                                                                accruedPerBorrowedUnit\n uint borrowerDelta = mul_(borrowerAmount, deltaIndex);\n uint borrowerAccrued = add_(strikeAccrued[borrower]
                                                                , borrowerDelta);\n strikeAccrued[borrower] = borrowerAccrued;\n emit DistributedBorrowerStrike(SToken(sToken), borrower,
                                                                borrowerDelta, borrowIndex);\n }\n\n /**\n * @notice Claim all the strike accrued by holder in all markets\n * @param holder The
                                                                address to claim STRK for\n */\n function claimStrike(address holder) public {\n return claimStrike(holder, allMarkets);\n }\n\n
                                                                 /**\n * @notice Claim all the strike accrued by holder in the specified markets\n * @param holder The address to claim STRK for\n *
                                                                @param sTokens The list of markets to claim STRK in\n */\n function claimStrike(address holder, SToken[] memory sTokens) public {\n
                                                                address[] memory holders = new address[](1);\n holders[0] = holder;\n claimStrike(holders, sTokens, true, true);\n }\n\n /**\n
                                                                 * @notice Claim all strike accrued by the holders\n * @param holders The addresses to claim STRK for\n * @param sTokens The list of
                                                                markets to claim STRK in\n * @param borrowers Whether or not to claim STRK earned by borrowing\n * @param suppliers Whether or not to claim
                                                                STRK earned by supplying\n */\n function claimStrike(address[] memory holders, SToken[] memory sTokens, bool borrowers, bool suppliers)
                                                                public {\n for (uint i = 0; i \u003c sTokens.length; i++) {\n SToken sToken = sTokens[i];\n require(markets[address
                                                                (sToken)].isListed, \"market must be listed\");\n if (borrowers) {\n Exp memory borrowIndex = Exp({mantissa: sToken
                                                                .borrowIndex()});\n updateStrikeBorrowIndex(address(sToken), borrowIndex);\n for (uint j = 0; j \u003c holders.length
                                                                ; j++) {\n distributeBorrowerStrike(address(sToken), holders[j], borrowIndex);\n }\n }\n if
                                                                (suppliers) {\n updateStrikeSupplyIndex(address(sToken));\n for (uint j = 0; j \u003c holders.length; j++) {\n
                                                                 distributeSupplierStrike(address(sToken), holders[j]);\n }\n }\n }\n\n for (uint j = 0; j
                                                                \u003c holders.length; j++) {\n strikeAccrued[holders[j]] = stakeSTRKInternal(holders[j], strikeAccrued[holders[j]]);\n }\n
                                                                }\n\n /**\n * @notice Transfer STRK to the strk staking\n * @dev Note: If there is not enough STRK, we do not perform the transfer and
                                                                staking all.\n * @param user The address of the user who stake STRK\n * @param amount The amount of STRK to (possibly) transfer and stake\n
                                                                 * @return The amount of STRK which was NOT staked and transferred to the staking\n */\n function stakeSTRKInternal(address user, uint
                                                                amount) internal returns (uint) {\n if (strkStaking != address(0)) {\n STRK strk = STRK(getSTRKAddress());\n uint
                                                                strkRemaining = strk.balanceOf(address(this));\n if (amount \u003e 0 \u0026\u0026 amount \u003c= strkRemaining) {\n strk
                                                                .transfer(strkStaking, amount);\n IStrikeStaking(strkStaking).mint(user, amount);\n return 0;\n }\n
                                                                 } else {\n return grantSTRKInternal(user, amount);\n }\n return amount;\n }\n\n /**\n * @notice Transfer STRK
                                                                to the user\n * @dev Note: If there is not enough STRK, we do not perform the transfer all.\n * @param user The address of the user to
                                                                transfer STRK to\n * @param amount The amount of STRK to (possibly) transfer\n * @return The amount of STRK which was NOT transferred to
                                                                the user\n */\n function grantSTRKInternal(address user, uint amount) internal returns (uint) {\n STRK strk = STRK(getSTRKAddress
                                                                ());\n uint strikeRemaining = strk.balanceOf(address(this));\n if (amount \u003e 0 \u0026\u0026 amount \u003c= strikeRemaining) {\n
                                                                 strk.transfer(user, amount);\n return 0;\n }\n return amount;\n }\n\n /*** STRK Distribution Admin
                                                                ***/\n\n /**\n * @notice Update additional accrued Strike for a contributor\n * @param contributor The address to calculate contributor
                                                                rewards\n */\n function updateContributorRewards(address contributor) public {\n uint strikeSpeed =
                                                                strikeContributorSpeeds[contributor];\n uint blockNumber = getBlockNumber();\n uint deltaBlocks = sub_(blockNumber,
                                                                lastContributorBlock[contributor]);\n\n if (deltaBlocks \u003e 0 \u0026\u0026 strikeSpeed \u003e 0) {\n uint newAccrued = mul_
                                                                (deltaBlocks, strikeSpeed);\n uint contributorAccrued = add_(strikeAccrued[contributor], newAccrued);\n\n
                                                                strikeAccrued[contributor] = contributorAccrued;\n lastContributorBlock[contributor] = blockNumber;\n }\n }\n\n /**\n *
                                                                @notice Set Strike speed for a single contributor\n * @param contributor The contributor whose Strike speed to set\n * @param strikeSpeed
                                                                New Strike speed for contributor\n */\n function _setContributorStrikeSpeed(address contributor, uint strikeSpeed) public {\n require
                                                                (adminOrInitializing(), \"Only Admin can set STRK speed\");\n\n // Update contributor STRK reward before update speed\n
                                                                updateContributorRewards(contributor);\n\n if (strikeSpeed == 0) {\n // release storage\n delete
                                                                lastContributorBlock[contributor];\n }\n\n // Update last block\n lastContributorBlock[contributor] = getBlockNumber();\n
                                                                 // Update STRK speed\n strikeContributorSpeeds[contributor] = strikeSpeed;\n\n emit ContributorStrikeSpeedUpdated(contributor,
                                                                strikeSpeed);\n }\n\n /**\n * @notice Transfer STRK to the recipient\n * @param recipient The address of the receipient to transfer
                                                                STRK to\n * @param amount The amount of STRK to (possibly) transfer\n */\n function _grantSTRK(address recipient, uint amount) public
                                                                {\n require(adminOrInitializing(), \"Only Admin can grant STRK\");\n\n uint amountLeft = grantSTRKInternal(recipient, amount);\n
                                                                 require(amountLeft == 0, \"Insufficient STRK for grant\");\n\n emit StrikeGranted(recipient, amount);\n }\n\n /**\n * @notice
                                                                Return all of the markets\n * @dev The automatic getter may be used to access an individual market.\n * @return The list of market
                                                                addresses\n */\n function getAllMarkets() public view returns (SToken[] memory) {\n return allMarkets;\n }\n\n function
                                                                getBlockNumber() public view returns (uint) {\n return block.number;\n }\n\n /**\n * @notice Return the address of the STRK
                                                                token\n * @return The address of STRK\n */\n function getSTRKAddress() public view returns (address) {\n return
                                                                0x74232704659ef37c08995e386A2E26cc27a8d7B1;\n }\n\n}\n"},"ComptrollerInterface.sol":{"content":"pragma solidity ^0.5.16;\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 sTokens) external returns (uint[] memory);\n function
                                                                exitMarket(address sToken) external returns (uint);\n\n /*** Policy Hooks ***/\n\n function mintAllowed(address sToken, address minter, uint
                                                                mintAmount) external returns (uint);\n function mintVerify(address sToken, address minter, uint mintAmount, uint mintTokens) external;\n\n
                                                                function redeemAllowed(address sToken, address redeemer, uint redeemTokens) external returns (uint);\n function redeemVerify(address sToken,
                                                                address redeemer, uint redeemAmount, uint redeemTokens) external;\n\n function borrowAllowed(address sToken, address borrower, uint borrowAmount
                                                                ) external returns (uint);\n function borrowVerify(address sToken, address borrower, uint borrowAmount) external;\n\n function
                                                                repayBorrowAllowed(\n address sToken,\n address payer,\n address borrower,\n uint repayAmount) external returns (uint
                                                                );\n function repayBorrowVerify(\n address sToken,\n address payer,\n address borrower,\n uint repayAmount,\n
                                                                 uint borrowerIndex) external;\n\n function liquidateBorrowAllowed(\n address sTokenBorrowed,\n address sTokenCollateral,\n
                                                                 address liquidator,\n address borrower,\n uint repayAmount) external returns (uint);\n function liquidateBorrowVerify(\n
                                                                address sTokenBorrowed,\n address sTokenCollateral,\n address liquidator,\n address borrower,\n uint repayAmount,\n
                                                                 uint seizeTokens) external;\n\n function seizeAllowed(\n address sTokenCollateral,\n address sTokenBorrowed,\n address
                                                                liquidator,\n address borrower,\n uint seizeTokens) external returns (uint);\n function seizeVerify(\n address
                                                                sTokenCollateral,\n address sTokenBorrowed,\n address liquidator,\n address borrower,\n uint seizeTokens) external;\n\n
                                                                 function transferAllowed(address sToken, address src, address dst, uint transferTokens) external returns (uint);\n function transferVerify
                                                                (address sToken, address src, address dst, uint transferTokens) external;\n\n /*** Liquidity/Liquidation Calculations ***/\n\n function
                                                                liquidateCalculateSeizeTokens(\n address sTokenBorrowed,\n address sTokenCollateral,\n uint repayAmount) external view returns
                                                                (uint, uint);\n}\n\ninterface IComptroller {\n /*** Reserve Info ***/\n function reserveGuardian() external view returns (address payable);\n
                                                                 function reserveAddress() external view returns (address payable);\n}\n"},"ComptrollerStorage.sol":{"content":"pragma solidity ^0.5.16
                                                                ;\n\nimport \"./SToken.sol\";\nimport \"./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 /**\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 uint public closeFactorMantissa
                                                                ;\n\n /**\n * @notice Multiplier representing the discount on collateral that a liquidator receives\n */\n uint public
                                                                liquidationIncentiveMantissa;\n\n /**\n * @notice Max number of assets a single account can participate in (borrow or use as collateral)\n
                                                                 */\n uint public maxAssets;\n\n /**\n * @notice Per-account mapping of \"assets you are in\", capped by maxAssets\n */\n
                                                                mapping(address =\u003e SToken[]) public accountAssets;\n\n}\n\ncontract ComptrollerV2Storage is ComptrollerV1Storage {\n struct Market {\n
                                                                 /// @notice Whether or not this market is listed\n bool isListed;\n\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 uint collateralFactorMantissa;\n\n /// @notice Per-market mapping of
                                                                \"accounts in this asset\"\n mapping(address =\u003e bool) accountMembership;\n\n /// @notice Whether or not this market receives
                                                                STRK\n bool isStriked;\n }\n\n /**\n * @notice Official mapping of sTokens -\u003e Market metadata\n * @dev Used e.g. to
                                                                determine if a market is supported\n */\n mapping(address =\u003e Market) public markets;\n\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 =\u003e bool) public mintGuardianPaused;\n mapping(address =\u003e bool) public borrowGuardianPaused;\n}\n\ncontract
                                                                ComptrollerV3Storage is ComptrollerV2Storage {\n struct StrikeMarketState {\n /// @notice The market\u0027s last updated
                                                                strikeBorrowIndex or strikeSupplyIndex\n uint224 index;\n\n /// @notice The block number the index was last updated at\n
                                                                uint32 block;\n }\n\n /// @notice A list of all markets\n SToken[] public allMarkets;\n\n /// @notice The rate at which the flywheel
                                                                distributes STRK, per block\n uint public strikeRate;\n\n /// @notice The portion of strikeRate that each market currently receives\n
                                                                mapping(address =\u003e uint) public strikeSpeeds;\n\n /// @notice The STRK market supply state for each market\n mapping(address =\u003e
                                                                StrikeMarketState) public strikeSupplyState;\n\n /// @notice The STRK market borrow state for each market\n mapping(address =\u003e
                                                                StrikeMarketState) public strikeBorrowState;\n\n /// @notice The STRK borrow index for each market for each supplier as of the last time they
                                                                accrued STRK\n mapping(address =\u003e mapping(address =\u003e uint)) public strikeSupplierIndex;\n\n /// @notice The STRK borrow index for
                                                                each market for each borrower as of the last time they accrued STRK\n mapping(address =\u003e mapping(address =\u003e uint)) public
                                                                strikeBorrowerIndex;\n\n /// @notice The STRK accrued but not yet transferred to each user\n mapping(address =\u003e uint) public
                                                                strikeAccrued;\n}\n\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\n /// @notice The portion of STRK that each constributor receives
                                                                per block\n mapping(address =\u003e uint) public strikeContributorSpeeds;\n\n /// @notice Last block at which a contributor\u0027s STRK
                                                                rewards have been allocated\n mapping(address =\u003e uint) public lastContributorBlock;\n}\n\ncontract ComptrollerV5Storage is
                                                                ComptrollerV4Storage {\n /// @notice The rate at which strike is distributed to the corresponding borrow market (per block)\n mapping(address
                                                                =\u003e uint) public strikeBorrowSpeeds;\n\n /// @notice The rate at which strike is distributed to the corresponding supply market (per block
                                                                )\n mapping(address =\u003e uint) public strikeSupplySpeeds;\n}\n\ncontract ComptrollerV6Storage is ComptrollerV5Storage {\n /// @notice
                                                                Reserve Guardian address\n address payable public reserveGuardian;\n\n /// @notice Reserve address\n address payable public reserveAddress
                                                                ;\n\n /// @notice STRK staking\n address public strkStaking;\n}\n\ncontract ComptrollerV7Storage is ComptrollerV6Storage {\n // @notice
                                                                The marketCapGuardian can set marketCaps to any number for any market.\n address public marketCapGuardian;\n\n // @notice Supply caps
                                                                enforced by mintAllowed for each sToken address. Defaults to zero which corresponds to unlimited supplying.\n mapping(address =\u003e uint)
                                                                public supplyCaps;\n\n // @notice Borrow caps enforced by borrowAllowed for each cToken address. Defaults to zero which corresponds to unlimited
                                                                borrowing.\n mapping(address =\u003e uint) public borrowCaps;\n\n /**\n * @notice The Pause Guardian can pause protocol.\n */\n
                                                                bool public protocolPaused;\n}\n"},"EIP20Interface.sol":{"content":"pragma 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 function
                                                                symbol() external view returns (string memory);\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(address src, address dst, uint256 amount) 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"}
                                                                ,"EIP20NonStandardInterface.sol":{"content":"pragma 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 /**\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(address src, address dst, uint256 amount) 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"},"ErrorReporter.sol":{"content":"pragma 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 SET_RESERVE_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(uint error, uint info, uint 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 (uint) {\n emit Failure(uint(err), uint(info), 0);\n\n return uint(err);\n }\n\n /**\n * @dev use this when
                                                                reporting an opaque error from an upgradeable collaborator contract\n */\n function failOpaque(Error err, FailureInfo info, uint
                                                                opaqueError) internal returns (uint) {\n emit Failure(uint(err), uint(info), opaqueError);\n\n return uint(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_ACCUMULATED_INTEREST_CALCULATION_FAILED,\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\n
                                                                ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\n
                                                                ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\n
                                                                BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\n BORROW_ACCRUE_INTEREST_FAILED,\n BORROW_CASH_NOT_AVAILABLE,\n
                                                                BORROW_FRESHNESS_CHECK,\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\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_BALANCE_INCREMENT_FAILED,\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_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_EXCHANGE_CALCULATION_FAILED,\n MINT_EXCHANGE_RATE_READ_FAILED,\n MINT_FRESHNESS_CHECK,\n
                                                                 MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\n MINT_TRANSFER_IN_FAILED,\n
                                                                MINT_TRANSFER_IN_NOT_POSSIBLE,\n REDEEM_ACCRUE_INTEREST_FAILED,\n REDEEM_COMPTROLLER_REJECTION,\n
                                                                REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\n REDEEM_EXCHANGE_RATE_READ_FAILED,\n
                                                                REDEEM_FRESHNESS_CHECK,\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\n
                                                                REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\n REDUCE_RESERVES_ADMIN_CHECK,\n
                                                                REDUCE_RESERVES_CASH_NOT_AVAILABLE,\n REDUCE_RESERVES_FRESH_CHECK,\n REDUCE_RESERVES_VALIDATION,\n
                                                                REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\n
                                                                 REPAY_BORROW_COMPTROLLER_REJECTION,\n REPAY_BORROW_FRESHNESS_CHECK,\n
                                                                REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\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
                                                                 TRANSFER_NOT_ENOUGH,\n TRANSFER_TOO_MUCH,\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\n ADD_RESERVES_FRESH_CHECK,\n
                                                                ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE,\n TRANSFER_RESERVES_ACCRUE_INTEREST_FAILED,\n TRANSFER_RESERVES_ADMIN_CHECK,\n
                                                                TRANSFER_RESERVES_CASH_NOT_AVAILABLE,\n TRANSFER_RESERVES_FRESH_CHECK,\n TRANSFER_RESERVES_VALIDATION\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(uint error, uint info, uint 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 (uint) {\n emit Failure(uint(err), uint(info), 0);\n\n return uint(err);\n }\n\n /**\n
                                                                * @dev use this when reporting an opaque error from an upgradeable collaborator contract\n */\n function failOpaque(Error err, FailureInfo
                                                                info, uint opaqueError) internal returns (uint) {\n emit Failure(uint(err), uint(info), opaqueError);\n\n return uint(err);\n
                                                                }\n}"},"Exponential.sol":{"content":"pragma solidity ^0.5.16;\n\nimport \"./CarefulMath.sol\";\n\n/**\n * @title Exponential module for storing
                                                                fixed-precision decimals\n * @author Strike\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 uint constant expScale = 1e18;\n uint constant doubleScale = 1e36;\n uint constant halfExpScale = expScale
                                                                /2;\n uint constant mantissaOne = expScale;\n\n struct Exp {\n uint mantissa;\n }\n\n struct Double {\n uint mantissa;\n
                                                                 }\n\n /**\n * @dev Creates an exponential from numerator and denominator values.\n * Note: Returns an error if (`num` * 10e18)
                                                                \u003e MAX_INT,\n * or if `denom` is zero.\n */\n function getExp(uint num, uint denom) internal pure returns (MathError, Exp
                                                                memory) {\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\n if (err0 != MathError.NO_ERROR) {\n return
                                                                (err0, Exp({mantissa: 0}));\n }\n\n (MathError err1, uint 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, uint 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, uint 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, uint scalar) internal pure returns (MathError, Exp memory) {\n (MathError err0, uint 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, uint scalar) internal pure returns (MathError, uint) {\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(Exp memory a, uint scalar, uint addend) internal
                                                                pure returns (MathError, uint) {\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 Divide an Exp by a
                                                                scalar, returning a new Exp.\n */\n function divScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\n
                                                                (MathError err0, uint 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(uint 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, uint 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(uint scalar, Exp memory divisor) internal pure returns
                                                                (MathError, uint) {\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 Multiplies two
                                                                exponentials, returning a new exponential.\n */\n function mulExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory)
                                                                {\n\n (MathError err0, uint 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, uint doubleScaledProductWithHalfScale) = addUInt
                                                                (halfExpScale, doubleScaledProduct);\n if (err1 != MathError.NO_ERROR) {\n return (err1, Exp({mantissa: 0}));\n }\n\n
                                                                 (MathError err2, uint 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(uint a, uint 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(Exp memory a, Exp
                                                                memory b, Exp memory c) 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 (uint) {\n //
                                                                Note: We are not using careful math here as we\u0027re 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 \u003c right.mantissa;\n }\n\n /**\n * @dev Checks if left Exp \u003c= right Exp.\n
                                                                */\n function lessThanOrEqualExp(Exp memory left, Exp memory right) internal pure returns (bool) {\n return left.mantissa \u003c= right
                                                                .mantissa;\n }\n\n /**\n * @dev Checks if left Exp \u003e right Exp.\n */\n function greaterThanExp(Exp memory left, Exp memory
                                                                right) internal pure returns (bool) {\n return left.mantissa \u003e 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(uint n, string memory errorMessage) internal pure returns (uint224) {\n require(n \u003c 2**224, errorMessage);\n
                                                                return uint224(n);\n }\n\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\n require(n \u003c 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_(uint a, uint b) internal pure
                                                                returns (uint) {\n return add_(a, b, \"addition overflow\");\n }\n\n function add_(uint a, uint b, string memory errorMessage)
                                                                internal pure returns (uint) {\n uint c = a + b;\n require(c \u003e= 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_(uint a, uint b) internal pure returns (uint) {\n return sub_(a, b, \"subtraction underflow\");\n
                                                                 }\n\n function sub_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\n require(b \u003c= 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, uint b) internal pure returns (Exp memory) {\n return
                                                                Exp({mantissa: mul_(a.mantissa, b)});\n }\n\n function mul_(uint a, Exp memory b) internal pure returns (uint) {\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, uint b) internal pure returns (Double memory
                                                                ) {\n return Double({mantissa: mul_(a.mantissa, b)});\n }\n\n function mul_(uint a, Double memory b) internal pure returns (uint) {\n
                                                                 return mul_(a, b.mantissa) / doubleScale;\n }\n\n function mul_(uint a, uint b) internal pure returns (uint) {\n return mul_(a,
                                                                b, \"multiplication overflow\");\n }\n\n function mul_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\n if
                                                                (a == 0 || b == 0) {\n return 0;\n }\n uint 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, uint b) internal pure returns (Exp memory) {\n return Exp({mantissa:
                                                                div_(a.mantissa, b)});\n }\n\n function div_(uint a, Exp memory b) internal pure returns (uint) {\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, uint b) internal pure returns (Double memory) {\n
                                                                 return Double({mantissa: div_(a.mantissa, b)});\n }\n\n function div_(uint a, Double memory b) internal pure returns (uint) {\n
                                                                return div_(mul_(a, doubleScale), b.mantissa);\n }\n\n function div_(uint a, uint b) internal pure returns (uint) {\n return div_(a, b
                                                                , \"divide by zero\");\n }\n\n function div_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\n require(b
                                                                \u003e 0, errorMessage);\n return a / b;\n }\n\n function fraction(uint a, uint b) internal pure returns (Double memory) {\n
                                                                return Double({mantissa: div_(mul_(a, doubleScale), b)});\n }\n}\n"},"InterestRateModel.sol":{"content":"pragma solidity ^0.5.16;\n\n/**\n *
                                                                @title Strike\u0027s InterestRateModel Interface\n * @author Strike\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 amount of reserves the market has\n * @return The borrow rate per block
                                                                (as a percentage, and scaled by 1e18)\n */\n function getBorrowRate(uint cash, uint borrows, uint reserves) external view returns (uint
                                                                );\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 amount 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(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) external view returns
                                                                (uint);\n\n}\n"},"IStrikeStaking.sol":{"content":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.5.16;\n\ninterface IStrikeStaking {\n\n
                                                                function mint(address user, uint256 amount) external;\n}\n"},"PriceOracle.sol":{"content":"pragma solidity ^0.5.16;\n\nimport \"./SToken.sol\"
                                                                ;\n\ncontract PriceOracle {\n /// @notice Indicator that this is a PriceOracle contract (for inspection)\n bool public constant isPriceOracle
                                                                = true;\n\n /**\n * @notice Get the underlying price of a sToken asset\n * @param sToken The sToken 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(SToken sToken) external view returns (uint);\n}\n"},"SafeMath.sol":{"content":"pragma solidity ^0.5.16;\n\n// From https
                                                                ://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/math/Math.sol\n// Subject to the MIT license.\n\n/**\n * @dev Wrappers over
                                                                Solidity\u0027s arithmetic operations with added overflow\n * checks.\n *\n * Arithmetic operations in Solidity wrap on overflow. This can easily
                                                                result\n * in bugs, because programmers usually assume that an overflow raises an\n * error, which is the standard behavior in high level
                                                                programming languages.\n * `SafeMath` restores this intuition by reverting the transaction when an\n * operation overflows.\n *\n * Using this
                                                                library instead of the unchecked operations eliminates an entire\n * class of bugs, so it\u0027s recommended to use it always.\n */\nlibrary
                                                                SafeMath {\n /**\n * @dev Returns the addition of two unsigned integers, reverting on overflow.\n *\n * Counterpart to
                                                                Solidity\u0027s `+` operator.\n *\n * Requirements:\n * - Addition cannot overflow.\n */\n function add(uint256 a, uint256 b)
                                                                internal pure returns (uint256) {\n uint256 c = a + b;\n require(c \u003e= a, \"SafeMath: addition overflow\");\n\n return c
                                                                ;\n }\n\n /**\n * @dev Returns the addition of two unsigned integers, reverting with custom message on overflow.\n *\n *
                                                                Counterpart to Solidity\u0027s `+` operator.\n *\n * Requirements:\n * - Addition cannot overflow.\n */\n function add(uint256 a
                                                                , uint256 b, string memory errorMessage) internal pure returns (uint256) {\n uint256 c = a + b;\n require(c \u003e= a, errorMessage
                                                                );\n\n return c;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting on underflow (when the result is
                                                                negative).\n *\n * Counterpart to Solidity\u0027s `-` operator.\n *\n * Requirements:\n * - Subtraction cannot underflow.\n
                                                                 */\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n return sub(a, b, \"SafeMath: subtraction underflow\");\n
                                                                }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on underflow (when the result is negative
                                                                ).\n *\n * Counterpart to Solidity\u0027s `-` operator.\n *\n * Requirements:\n * - Subtraction cannot underflow.\n */\n
                                                                 function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b \u003c= a, errorMessage);\n
                                                                 uint256 c = a - b;\n\n return c;\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, reverting on
                                                                overflow.\n *\n * Counterpart to Solidity\u0027s `*` operator.\n *\n * Requirements:\n * - Multiplication cannot overflow.\n
                                                                 */\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n // Gas optimization: this is cheaper than requiring
                                                                \u0027a\u0027 not being zero, but the\n // benefit is lost if \u0027b\u0027 is also tested.\n // See: https://github.com/OpenZeppelin
                                                                /openzeppelin-contracts/pull/522\n if (a == 0) {\n return 0;\n }\n\n uint256 c = a * b;\n require(c / a == b
                                                                , \"SafeMath: multiplication overflow\");\n\n return c;\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers,
                                                                reverting on overflow.\n *\n * Counterpart to Solidity\u0027s `*` operator.\n *\n * Requirements:\n * - Multiplication cannot
                                                                overflow.\n */\n function mul(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n // Gas
                                                                optimization: this is cheaper than requiring \u0027a\u0027 not being zero, but the\n // benefit is lost if \u0027b\u0027 is also tested.\n
                                                                 // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n if (a == 0) {\n return 0;\n }\n\n
                                                                uint256 c = a * b;\n require(c / a == b, errorMessage);\n\n return c;\n }\n\n /**\n * @dev Returns the integer division of
                                                                two unsigned integers.\n * Reverts on division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity\u0027s `/`
                                                                operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode
                                                                to revert (consuming all remaining gas).\n *\n * Requirements:\n * - The divisor cannot be zero.\n */\n function div(uint256 a,
                                                                uint256 b) internal pure returns (uint256) {\n return div(a, b, \"SafeMath: division by zero\");\n }\n\n /**\n * @dev Returns the
                                                                integer division of two unsigned integers.\n * Reverts with custom message on division by zero. The result is rounded towards zero.\n *\n
                                                                 * Counterpart to Solidity\u0027s `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while
                                                                Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n * - The divisor cannot be zero
                                                                .\n */\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n // Solidity only
                                                                automatically asserts when dividing by 0\n require(b \u003e 0, errorMessage);\n uint256 c = a / b;\n // assert(a == b * c + a
                                                                % b); // There is no case in which this doesn\u0027t hold\n\n return c;\n }\n\n /**\n * @dev Returns the remainder of dividing two
                                                                unsigned integers. (unsigned integer modulo),\n * Reverts when dividing by zero.\n *\n * Counterpart to Solidity\u0027s `%` operator.
                                                                This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert
                                                                (consuming all remaining gas).\n *\n * Requirements:\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b)
                                                                internal pure returns (uint256) {\n return mod(a, b, \"SafeMath: modulo by zero\");\n }\n\n /**\n * @dev Returns the remainder of
                                                                dividing two unsigned integers. (unsigned integer modulo),\n * Reverts with custom message when dividing by zero.\n *\n * Counterpart
                                                                to Solidity\u0027s `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n *
                                                                invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n * - The divisor cannot be zero.\n */\n function
                                                                mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b != 0, errorMessage);\n return a %
                                                                b;\n }\n}\n"},"SErc20.sol":{"content":"pragma solidity ^0.5.16;\n\nimport \"./SToken.sol\";\n\n/**\n * @title Strike\u0027s SErc20 Contract\n *
                                                                @notice STokens which wrap an EIP-20 underlying\n * @author Strike\n */\ncontract SErc20 is SToken, SErc20Interface {\n /**\n * @notice
                                                                Initialize the new money market\n * @param underlying_ The address of the underlying asset\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 */\n function initialize(address underlying_,\n
                                                                ComptrollerInterface comptroller_,\n InterestRateModel interestRateModel_,\n uint
                                                                initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n
                                                                 uint8 decimals_) public {\n // SToken initialize does the bulk of the work\n super.initialize(comptroller_, interestRateModel_,
                                                                initialExchangeRateMantissa_, name_, symbol_, decimals_);\n\n // Set underlying and sanity check it\n underlying = underlying_;\n
                                                                 EIP20Interface(underlying).totalSupply();\n }\n\n /*** User Interface ***/\n\n /**\n * @notice Sender supplies assets into the
                                                                market and receives sTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param
                                                                mintAmount The amount of the underlying asset to supply\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n
                                                                 */\n function mint(uint mintAmount) external returns (uint) {\n (uint err,) = mintInternal(mintAmount);\n return err;\n
                                                                }\n\n /**\n * @notice Sender redeems sTokens in exchange for the underlying asset\n * @dev Accrues interest whether or not the operation
                                                                succeeds, unless reverted\n * @param redeemTokens The number of sTokens to redeem into underlying\n * @return uint 0=success, otherwise a
                                                                failure (see ErrorReporter.sol for details)\n */\n function redeem(uint redeemTokens) external returns (uint) {\n return
                                                                redeemInternal(redeemTokens);\n }\n\n /**\n * @notice Sender redeems sTokens 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(uint redeemAmount)
                                                                external returns (uint) {\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(uint borrowAmount) external returns (uint) {\n return
                                                                borrowInternal(borrowAmount);\n }\n\n /**\n * @notice Sender repays their own borrow\n * @param repayAmount The amount to repay\n
                                                                 * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function repayBorrow(uint repayAmount) external
                                                                returns (uint) {\n (uint err,) = repayBorrowInternal(repayAmount);\n return err;\n }\n\n /**\n * @notice Sender repays a
                                                                borrow belonging to borrower\n * @param borrower the account with the debt being payed off\n * @param repayAmount The amount to repay\n
                                                                 * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function repayBorrowBehalf(address borrower, uint
                                                                repayAmount) external returns (uint) {\n (uint err,) = repayBorrowBehalfInternal(borrower, repayAmount);\n return err;\n }\n\n
                                                                /**\n * @notice The sender liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param
                                                                borrower The borrower of this sToken to be liquidated\n * @param repayAmount The amount of the underlying borrowed asset to repay\n *
                                                                @param sTokenCollateral The market in which to seize collateral from the borrower\n * @return uint 0=success, otherwise a failure (see
                                                                ErrorReporter.sol for details)\n */\n function liquidateBorrow(address borrower, uint repayAmount, STokenInterface sTokenCollateral)
                                                                external returns (uint) {\n (uint err,) = liquidateBorrowInternal(borrower, repayAmount, sTokenCollateral);\n return err;\n }\n\n
                                                                 /**\n * @notice The sender adds to reserves.\n * @param addAmount The amount fo underlying token to add as reserves\n * @return uint
                                                                0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _addReserves(uint addAmount) external returns (uint) {\n
                                                                 return _addReservesInternal(addAmount);\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 tokens owned by
                                                                this contract\n */\n function getCashPrior() internal view returns (uint) {\n EIP20Interface token = EIP20Interface(underlying);\n
                                                                 return token.balanceOf(address(this));\n }\n\n /**\n * @dev Similar to EIP20 transfer, except it handles a False result from
                                                                `transferFrom` and reverts in that case.\n * This will revert due to insufficient balance or insufficient allowance.\n * This
                                                                function returns the actual amount received,\n * which may be less than `amount` if there is a fee attached to the transfer.\n *\n
                                                                 * Note: This wrapper safely handles non-standard ERC-20 tokens that do not return a value.\n * See here: https://medium.com
                                                                /coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\n */\n function doTransferIn(address from, uint amount)
                                                                internal returns (uint) {\n EIP20NonStandardInterface token = EIP20NonStandardInterface(underlying);\n uint balanceBefore =
                                                                EIP20Interface(underlying).balanceOf(address(this));\n token.transferFrom(from, address(this), amount);\n\n bool success;\n
                                                                assembly {\n switch returndatasize()\n case 0 { // This is a non-standard ERC-20\n
                                                                 success := not(0) // set success to true\n }\n case 32 { // This is a compliant ERC
                                                                -20\n returndatacopy(0, 0, 32)\n success := mload(0) // Set `success = returndata` of external call\n
                                                                 }\n default { // This is an excessively non-compliant ERC-20, revert.\n
                                                                revert(0, 0)\n }\n }\n require(success, \"TOKEN_TRANSFER_IN_FAILED\");\n\n // Calculate the amount that was
                                                                *actually* transferred\n uint balanceAfter = EIP20Interface(underlying).balanceOf(address(this));\n require(balanceAfter \u003e=
                                                                balanceBefore, \"TOKEN_TRANSFER_IN_OVERFLOW\");\n return balanceAfter - balanceBefore; // underflow already checked above, just subtract\n
                                                                 }\n\n /**\n * @dev Similar to EIP20 transfer, except it handles a False success from `transfer` and returns an explanatory\n *
                                                                error code rather than reverting. If caller has not called checked protocol\u0027s balance, this may revert due to\n * insufficient cash
                                                                held in this contract. If caller has checked protocol\u0027s balance prior to this call, and verified\n * it is \u003e= amount, this
                                                                should not revert in normal conditions.\n *\n * Note: This wrapper safely handles non-standard ERC-20 tokens that do not return a
                                                                value.\n * See here: https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\n */\n
                                                                function doTransferOut(address payable to, uint amount) internal {\n EIP20NonStandardInterface token = EIP20NonStandardInterface(underlying
                                                                );\n token.transfer(to, amount);\n\n bool success;\n assembly {\n switch returndatasize()\n case 0 {
                                                                 // This is a non-standard ERC-20\n success := not(0) // set success to true\n }\n
                                                                 case 32 { // This is a complaint ERC-20\n returndatacopy(0, 0, 32)\n
                                                                success := mload(0) // Set `success = returndata` of external call\n }\n default { // This
                                                                is an excessively non-compliant ERC-20, revert.\n revert(0, 0)\n }\n }\n require(success,
                                                                \"TOKEN_TRANSFER_OUT_FAILED\");\n }\n}\n"},"SErc20Delegate.sol":{"content":"pragma solidity ^0.5.16;\n\nimport \"./SErc20.sol\";\n\n/**\n *
                                                                @title Strike\u0027s SErc20Delegate Contract\n * @notice STokens which wrap an EIP-20 underlying and are delegated to\n * @author Strike\n
                                                                */\ncontract SErc20Delegate is SErc20, SDelegateInterface {\n /**\n * @notice Construct an empty delegate\n */\n constructor() public
                                                                {}\n\n /**\n * @notice Called by the delegator on a delegate to initialize it for duty\n * @param data The encoded bytes data for any
                                                                initialization\n */\n function _becomeImplementation(bytes memory data) public {\n // Shh -- currently unused\n data;\n\n
                                                                 // Shh -- we don\u0027t ever want this hook to be marked pure\n if (false) {\n implementation = address(0);\n }\n\n
                                                                 require(msg.sender == admin, \"only the admin may call _becomeImplementation\");\n }\n\n /**\n * @notice Called by the delegator on a
                                                                delegate to forfeit its responsibility\n */\n function _resignImplementation() public {\n // Shh -- we don\u0027t ever want this hook
                                                                to be marked pure\n if (false) {\n implementation = address(0);\n }\n\n require(msg.sender == admin, \"only the
                                                                admin may call _resignImplementation\");\n }\n}\n"},"SErc20Delegator.sol":{"content":"pragma solidity ^0.5.16;\n\nimport \"./STokenInterfaces
                                                                .sol\";\n\n/**\n * @title Strike\u0027s SErc20Delegator Contract\n * @notice STokens which wrap an EIP-20 underlying and delegate to an
                                                                implementation\n * @author Strike\n */\ncontract SErc20Delegator is STokenInterface, SErc20Interface, SDelegatorInterface {\n /**\n *
                                                                @notice Construct a new money market\n * @param underlying_ The address of the underlying asset\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 * @param implementation_
                                                                The address of the implementation the contract delegates to\n * @param becomeImplementationData The encoded args for becomeImplementation\n
                                                                 */\n constructor(address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModel interestRateModel_
                                                                ,\n uint initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n
                                                                 uint8 decimals_,\n address payable admin_,\n address implementation_,\n bytes memory
                                                                becomeImplementationData) public {\n // Creator of the contract is admin during initialization\n admin = msg.sender;\n\n //
                                                                First delegate gets to initialize the delegator (i.e. storage contract)\n delegateTo(implementation_, abi.encodeWithSignature(\"initialize
                                                                (address,address,address,uint256,string,string,uint8)\",\n underlying_,\n
                                                                 comptroller_,\n interestRateModel_,\n
                                                                 initialExchangeRateMantissa_,\n
                                                                name_,\n symbol_,\n decimals_
                                                                ));\n\n // New implementations always get set via the settor (post-initialize)\n _setImplementation(implementation_, false,
                                                                becomeImplementationData);\n\n // Set the proper admin now that initialization is done\n admin = admin_;\n }\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(address
                                                                implementation_, bool allowResign, bytes memory becomeImplementationData) public {\n require(msg.sender == admin, \"SErc20Delegator
                                                                ::_setImplementation: Caller must be admin\");\n\n if (allowResign) {\n delegateToImplementation(abi.encodeWithSignature
                                                                (\"_resignImplementation()\"));\n }\n\n address oldImplementation = implementation;\n implementation = implementation_;\n\n
                                                                 delegateToImplementation(abi.encodeWithSignature(\"_becomeImplementation(bytes)\", becomeImplementationData));\n\n emit
                                                                NewImplementation(oldImplementation, implementation);\n }\n\n /**\n * @notice Sender supplies assets into the market and receives sTokens
                                                                in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param mintAmount The amount of the
                                                                underlying asset to supply\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function mint(uint
                                                                mintAmount) external returns (uint) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"mint(uint256)\", mintAmount
                                                                ));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Sender redeems sTokens in exchange for the underlying asset\n *
                                                                @dev Accrues interest whether or not the operation succeeds, unless reverted`\n * @param redeemTokens The number of sTokens to redeem into
                                                                underlying\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function redeem(uint redeemTokens)
                                                                external returns (uint) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"redeem(uint256)\", redeemTokens));\n
                                                                 return abi.decode(data, (uint));\n }\n\n /**\n * @notice Sender redeems sTokens 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(uint
                                                                redeemAmount) external returns (uint) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"redeemUnderlying(uint256)\"
                                                                , redeemAmount));\n return abi.decode(data, (uint));\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(uint borrowAmount) external returns (uint) {\n bytes memory data =
                                                                delegateToImplementation(abi.encodeWithSignature(\"borrow(uint256)\", borrowAmount));\n return abi.decode(data, (uint));\n }\n\n /**\n
                                                                 * @notice Sender repays their own borrow\n * @param repayAmount The amount to repay\n * @return uint 0=success, otherwise a failure
                                                                (see ErrorReporter.sol for details)\n */\n function repayBorrow(uint repayAmount) external returns (uint) {\n bytes memory data =
                                                                delegateToImplementation(abi.encodeWithSignature(\"repayBorrow(uint256)\", repayAmount));\n return abi.decode(data, (uint));\n }\n\n
                                                                /**\n * @notice Sender repays a borrow belonging to borrower\n * @param borrower the account with the debt being payed off\n * @param
                                                                repayAmount The amount to repay\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function
                                                                repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint) {\n bytes memory data = delegateToImplementation(abi
                                                                .encodeWithSignature(\"repayBorrowBehalf(address,uint256)\", borrower, repayAmount));\n return abi.decode(data, (uint));\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 sToken to be liquidated\n * @param sTokenCollateral 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 0=success, otherwise a failure (see ErrorReporter
                                                                .sol for details)\n */\n function liquidateBorrow(address borrower, uint repayAmount, STokenInterface sTokenCollateral) external returns
                                                                (uint) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"liquidateBorrow(address,uint256,address)\", borrower,
                                                                repayAmount, sTokenCollateral));\n return abi.decode(data, (uint));\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, uint amount) external returns (bool) {\n bytes memory
                                                                data = delegateToImplementation(abi.encodeWithSignature(\"transfer(address,uint256)\", dst, amount));\n return abi.decode(data, (bool));\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(address src, address dst, uint256 amount) external returns (bool) {\n bytes memory data =
                                                                delegateToImplementation(abi.encodeWithSignature(\"transferFrom(address,address,uint256)\", src, dst, amount));\n return abi.decode(data,
                                                                (bool));\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 bytes
                                                                memory data = delegateToImplementation(abi.encodeWithSignature(\"approve(address,uint256)\", spender, amount));\n return abi.decode(data,
                                                                (bool));\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 (uint) {\n
                                                                bytes memory data = delegateToViewImplementation(abi.encodeWithSignature(\"allowance(address,address)\", owner, spender));\n return abi
                                                                .decode(data, (uint));\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 (uint) {\n
                                                                 bytes memory data = delegateToViewImplementation(abi.encodeWithSignature(\"balanceOf(address)\", owner));\n return abi.decode(data, (uint
                                                                ));\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 (uint) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature
                                                                (\"balanceOfUnderlying(address)\", owner));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Get a snapshot of the
                                                                account\u0027s 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) external view returns (uint, uint, uint, uint) {\n bytes memory data =
                                                                delegateToViewImplementation(abi.encodeWithSignature(\"getAccountSnapshot(address)\", account));\n return abi.decode(data, (uint, uint, uint
                                                                , uint));\n }\n\n /**\n * @notice Returns the current per-block borrow interest rate for this sToken\n * @return The borrow interest
                                                                rate per block, scaled by 1e18\n */\n function borrowRatePerBlock() external view returns (uint) {\n bytes memory data =
                                                                delegateToViewImplementation(abi.encodeWithSignature(\"borrowRatePerBlock()\"));\n return abi.decode(data, (uint));\n }\n\n /**\n
                                                                * @notice Returns the current per-block supply interest rate for this sToken\n * @return The supply interest rate per block, scaled by 1e18\n
                                                                 */\n function supplyRatePerBlock() external view returns (uint) {\n bytes memory data = delegateToViewImplementation(abi
                                                                .encodeWithSignature(\"supplyRatePerBlock()\"));\n return abi.decode(data, (uint));\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 returns
                                                                (uint) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"totalBorrowsCurrent()\"));\n return abi.decode(data
                                                                , (uint));\n }\n\n /**\n * @notice Accrue interest to updated borrowIndex and then calculate account\u0027s 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 returns (uint) {\n bytes memory data =
                                                                delegateToImplementation(abi.encodeWithSignature(\"borrowBalanceCurrent(address)\", account));\n return abi.decode(data, (uint));\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 (uint) {\n
                                                                 bytes memory data = delegateToViewImplementation(abi.encodeWithSignature(\"borrowBalanceStored(address)\", account));\n return abi.decode
                                                                (data, (uint));\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 returns (uint) {\n bytes memory data = delegateToImplementation(abi
                                                                .encodeWithSignature(\"exchangeRateCurrent()\"));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Calculates the
                                                                exchange rate from the underlying to the SToken\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 (uint) {\n bytes memory data
                                                                = delegateToViewImplementation(abi.encodeWithSignature(\"exchangeRateStored()\"));\n return abi.decode(data, (uint));\n }\n\n /**\n
                                                                 * @notice Get cash balance of this sToken in the underlying asset\n * @return The quantity of underlying asset owned by this contract\n
                                                                */\n function getCash() external view returns (uint) {\n bytes memory data = delegateToViewImplementation(abi.encodeWithSignature
                                                                (\"getCash()\"));\n return abi.decode(data, (uint));\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 (uint) {\n bytes memory data = delegateToImplementation(abi
                                                                .encodeWithSignature(\"accrueInterest()\"));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Transfers collateral
                                                                tokens (this market) to the liquidator.\n * @dev Will fail unless called by another sToken during the process of liquidation.\n * Its
                                                                absolutely critical to use msg.sender as the borrowed sToken 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 sTokens to seize\n * @return
                                                                uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function seize(address liquidator, address borrower, uint
                                                                seizeTokens) external returns (uint) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"seize(address,address
                                                                ,uint256)\", liquidator, borrower, seizeTokens));\n return abi.decode(data, (uint));\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 (uint) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"_setPendingAdmin(address
                                                                )\", newPendingAdmin));\n return abi.decode(data, (uint));\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 (uint) {\n bytes memory data = delegateToImplementation(abi
                                                                .encodeWithSignature(\"_setComptroller(address)\", newComptroller));\n return abi.decode(data, (uint));\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(uint newReserveFactorMantissa) external returns (uint) {\n bytes memory data = delegateToImplementation(abi
                                                                .encodeWithSignature(\"_setReserveFactor(uint256)\", newReserveFactorMantissa));\n return abi.decode(data, (uint));\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 (uint) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"_acceptAdmin()\"));\n return abi
                                                                .decode(data, (uint));\n }\n\n /**\n * @notice Accrues interest and adds reserves by transferring from admin\n * @param addAmount
                                                                Amount of reserves to add\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function
                                                                _addReserves(uint addAmount) external returns (uint) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"_addReserves
                                                                (uint256)\", addAmount));\n return abi.decode(data, (uint));\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(uint reduceAmount) external returns (uint) {\n bytes memory data =
                                                                delegateToImplementation(abi.encodeWithSignature(\"_reduceReserves(uint256)\", reduceAmount));\n return abi.decode(data, (uint));\n }\n\n
                                                                 /**\n * @notice Accrues interest and reduces reserves by transferring to reserve address\n * @param reduceAmount Amount of reduction to
                                                                reserves\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _transferReserves(uint
                                                                reduceAmount) external returns (uint) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"_transferReserves(uint256
                                                                )\", reduceAmount));\n return abi.decode(data, (uint));\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 (uint) {\n bytes memory data =
                                                                delegateToImplementation(abi.encodeWithSignature(\"_setInterestRateModel(address)\", newInterestRateModel));\n return abi.decode(data, (uint
                                                                ));\n }\n\n /**\n * @notice Internal method to delegate execution to another contract\n * @dev It returns to the external caller
                                                                whatever the implementation returns or forwards reverts\n * @param callee The contract to delegatecall\n * @param data The raw data to
                                                                delegatecall\n * @return The returned bytes from the delegatecall\n */\n function delegateTo(address callee, bytes memory data) internal
                                                                returns (bytes memory) {\n (bool success, bytes memory returnData) = callee.delegatecall(data);\n assembly {\n if eq
                                                                (success, 0) {\n revert(add(returnData, 0x20), returndatasize)\n }\n }\n return returnData;\n }\n\n
                                                                /**\n * @notice Delegates execution to the implementation contract\n * @dev It returns to the external caller whatever the implementation
                                                                returns or forwards reverts\n * @param data The raw data to delegatecall\n * @return The returned bytes from the delegatecall\n */\n
                                                                 function delegateToImplementation(bytes memory data) public returns (bytes memory) {\n return delegateTo(implementation, data);\n }\n\n
                                                                 /**\n * @notice Delegates execution to an implementation contract\n * @dev It returns to the external caller whatever the implementation
                                                                returns or forwards reverts\n * There are an additional 2 prefix uints from the wrapper returndata, which we ignore since we make an extra hop
                                                                .\n * @param data The raw data to delegatecall\n * @return The returned bytes from the delegatecall\n */\n function
                                                                delegateToViewImplementation(bytes memory data) public view returns (bytes memory) {\n (bool success, bytes memory returnData) = address
                                                                (this).staticcall(abi.encodeWithSignature(\"delegateToImplementation(bytes)\", data));\n assembly {\n if eq(success, 0) {\n
                                                                 revert(add(returnData, 0x20), returndatasize)\n }\n }\n return abi.decode(returnData, (bytes));\n }\n\n
                                                                /**\n * @notice Delegates execution to an implementation contract\n * @dev It returns to the external caller whatever the implementation
                                                                returns or forwards reverts\n */\n function () external payable {\n require(msg.value == 0,\"SErc20Delegator:fallback: cannot send
                                                                value to fallback\");\n\n // delegate all other functions to current implementation\n (bool success, ) = implementation.delegatecall
                                                                (msg.data);\n\n assembly {\n let free_mem_ptr := mload(0x40)\n returndatacopy(free_mem_ptr, 0, returndatasize)\n\n
                                                                 switch success\n case 0 { revert(free_mem_ptr, returndatasize) }\n default { return(free_mem_ptr, returndatasize) }\n
                                                                 }\n }\n}\n"},"SToken.sol":{"content":"pragma solidity ^0.5.16;\n\nimport \"./ComptrollerInterface.sol\";\nimport \"./STokenInterfaces
                                                                .sol\";\nimport \"./ErrorReporter.sol\";\nimport \"./Exponential.sol\";\nimport \"./EIP20Interface.sol\";\nimport \"./EIP20NonStandardInterface
                                                                .sol\";\nimport \"./InterestRateModel.sol\";\n\n/**\n * @title Strike\u0027s SToken Contract\n * @notice Abstract base for STokens\n * @author
                                                                Strike\n */\ncontract SToken is STokenInterface, 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(ComptrollerInterface
                                                                comptroller_,\n InterestRateModel interestRateModel_,\n uint initialExchangeRateMantissa_,\n
                                                                 string memory name_,\n string memory symbol_,\n uint8 decimals_) public {\n
                                                                require(msg.sender == admin, \"only admin may initialize the market\");\n require(accrualBlockNumber == 0 \u0026\u0026 borrowIndex == 0,
                                                                \"market may only be initialized once\");\n\n // Set initial exchange rate\n initialExchangeRateMantissa =
                                                                initialExchangeRateMantissa_;\n require(initialExchangeRateMantissa \u003e 0, \"initial exchange rate must be greater than zero.\");\n\n
                                                                 // Set the comptroller\n uint err = _setComptroller(comptroller_);\n require(err == uint(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 == uint(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(address
                                                                spender, address src, address dst, uint tokens) internal returns (uint) {\n /* Fail if transfer not allowed */\n uint 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 uint startingAllowance = 0;\n if (spender == src) {\n startingAllowance = uint(-1);\n }
                                                                else {\n startingAllowance = transferAllowances[src][spender];\n }\n\n /* Do the calculations, checking for {under
                                                                ,over}flow */\n MathError mathErr;\n uint allowanceNew;\n uint srsTokensNew;\n uint dstTokensNew;\n\n (mathErr,
                                                                allowanceNew) = subUInt(startingAllowance, tokens);\n if (mathErr != MathError.NO_ERROR) {\n return fail(Error.MATH_ERROR,
                                                                FailureInfo.TRANSFER_NOT_ALLOWED);\n }\n\n (mathErr, srsTokensNew) = subUInt(accountTokens[src], tokens);\n if (mathErr !=
                                                                MathError.NO_ERROR) {\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ENOUGH);\n }\n\n (mathErr, dstTokensNew) =
                                                                addUInt(accountTokens[dst], tokens);\n if (mathErr != MathError.NO_ERROR) {\n return fail(Error.MATH_ERROR, FailureInfo
                                                                .TRANSFER_TOO_MUCH);\n }\n\n /////////////////////////\n // EFFECTS \u0026 INTERACTIONS\n // (No safe failures beyond
                                                                this point)\n\n accountTokens[src] = srsTokensNew;\n accountTokens[dst] = dstTokensNew;\n\n /* Eat some of the allowance (if
                                                                necessary) */\n if (startingAllowance != uint(-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 uint(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) == uint(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(address src, address dst, uint256 amount)
                                                                external nonReentrant returns (bool) {\n return transferTokens(msg.sender, src, dst, amount) == uint(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 (uint) {\n Exp memory exchangeRate = Exp({mantissa: exchangeRateCurrent()});\n
                                                                 (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\n require(mErr == MathError.NO_ERROR,
                                                                \"balance could not be calculated\");\n return balance;\n }\n\n /**\n * @notice Get a snapshot of the account\u0027s 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) external view returns (uint, uint, uint, uint) {\n uint sTokenBalance = accountTokens[account];\n
                                                                 uint borrowBalance;\n uint exchangeRateMantissa;\n\n MathError mErr;\n\n (mErr, borrowBalance) = borrowBalanceStoredInternal
                                                                (account);\n if (mErr != MathError.NO_ERROR) {\n return (uint(Error.MATH_ERROR), 0, 0, 0);\n }\n\n (mErr,
                                                                exchangeRateMantissa) = exchangeRateStoredInternal();\n if (mErr != MathError.NO_ERROR) {\n return (uint(Error.MATH_ERROR), 0, 0,
                                                                0);\n }\n\n return (uint(Error.NO_ERROR), sTokenBalance, 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 (uint) {\n return block.number;\n }\n\n /**\n * @notice Returns the current per-block
                                                                borrow interest rate for this sToken\n * @return The borrow interest rate per block, scaled by 1e18\n */\n function borrowRatePerBlock()
                                                                external view returns (uint) {\n return interestRateModel.getBorrowRate(getCashPrior(), totalBorrows, totalReserves);\n }\n\n /**\n
                                                                 * @notice Returns the current per-block supply interest rate for this sToken\n * @return The supply interest rate per block, scaled by 1e18\n
                                                                 */\n function supplyRatePerBlock() external view returns (uint) {\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 (uint) {\n require
                                                                (accrueInterest() == uint(Error.NO_ERROR), \"accrue interest failed\");\n return totalBorrows;\n }\n\n /**\n * @notice Accrue
                                                                interest to updated borrowIndex and then calculate account\u0027s 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 (uint) {\n require(accrueInterest() == uint(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 (uint) {\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\n require(err
                                                                == MathError.NO_ERROR, \"borrowBalanceStored: borrowBalanceStoredInternal failed\");\n return result;\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
                                                                (error code, the calculated balance or 0 if error code is non-zero)\n */\n function borrowBalanceStoredInternal(address account) internal
                                                                view returns (MathError, uint) {\n /* Note: we do not assert that the market is up to date */\n MathError mathErr;\n uint
                                                                principalTimesIndex;\n uint result;\n\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 (MathError
                                                                .NO_ERROR, 0);\n }\n\n /* Calculate new borrow balance using the interest index:\n * recentBorrowBalance = borrower
                                                                .borrowBalance * market.borrowIndex / borrower.borrowIndex\n */\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal,
                                                                borrowIndex);\n if (mathErr != MathError.NO_ERROR) {\n return (mathErr, 0);\n }\n\n (mathErr, result) = divUInt
                                                                (principalTimesIndex, borrowSnapshot.interestIndex);\n if (mathErr != MathError.NO_ERROR) {\n return (mathErr, 0);\n }\n\n
                                                                 return (MathError.NO_ERROR, 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 (uint) {\n require
                                                                (accrueInterest() == uint(Error.NO_ERROR), \"accrue interest failed\");\n return exchangeRateStored();\n }\n\n /**\n * @notice
                                                                Calculates the exchange rate from the underlying to the SToken\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 (uint) {\n
                                                                (MathError err, uint result) = exchangeRateStoredInternal();\n require(err == MathError.NO_ERROR, \"exchangeRateStored:
                                                                exchangeRateStoredInternal failed\");\n return result;\n }\n\n /**\n * @notice Calculates the exchange rate from the underlying to
                                                                the SToken\n * @dev This function does not accrue interest before calculating the exchange rate\n * @return (error code, calculated
                                                                exchange rate scaled by 1e18)\n */\n function exchangeRateStoredInternal() internal view returns (MathError, uint) {\n uint
                                                                _totalSupply = totalSupply;\n if (_totalSupply == 0) {\n /*\n * If there are no tokens minted:\n *
                                                                exchangeRate = initialExchangeRate\n */\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\n } else {\n
                                                                 /*\n * Otherwise:\n * exchangeRate = (totalCash + totalBorrows - totalReserves) / totalSupply\n */\n
                                                                 uint totalCash = getCashPrior();\n uint cashPlusBorrowsMinusReserves;\n Exp memory exchangeRate;\n
                                                                MathError mathErr;\n\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\n if
                                                                (mathErr != MathError.NO_ERROR) {\n return (mathErr, 0);\n }\n\n (mathErr, exchangeRate) = getExp
                                                                (cashPlusBorrowsMinusReserves, _totalSupply);\n if (mathErr != MathError.NO_ERROR) {\n return (mathErr, 0);\n
                                                                }\n\n return (MathError.NO_ERROR, exchangeRate.mantissa);\n }\n }\n\n /**\n * @notice Get cash balance of this sToken
                                                                in the underlying asset\n * @return The quantity of underlying asset owned by this contract\n */\n function getCash() external view
                                                                returns (uint) {\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 (uint) {\n /* Remember the initial block number */\n uint currentBlockNumber =
                                                                getBlockNumber();\n uint accrualBlockNumberPrior = accrualBlockNumber;\n\n /* Short-circuit accumulating 0 interest */\n if
                                                                (accrualBlockNumberPrior == currentBlockNumber) {\n return uint(Error.NO_ERROR);\n }\n\n /* Read the previous values out
                                                                of storage */\n uint cashPrior = getCashPrior();\n uint borrowsPrior = totalBorrows;\n uint reservesPrior = totalReserves;\n
                                                                 uint borrowIndexPrior = borrowIndex;\n\n /* Calculate the current borrow interest rate */\n uint borrowRateMantissa =
                                                                interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\n require(borrowRateMantissa \u003c= borrowRateMaxMantissa,
                                                                \"borrow rate is absurdly high\");\n\n /* Calculate the number of blocks elapsed since the last accrual */\n (MathError mathErr, uint
                                                                blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\n require(mathErr == MathError.NO_ERROR, \"could not calculate block
                                                                delta\");\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;\n uint
                                                                interestAccumulated;\n uint totalBorrowsNew;\n uint totalReservesNew;\n uint borrowIndexNew;\n\n (mathErr,
                                                                simpleInterestFactor) = mulScalar(Exp({mantissa: borrowRateMantissa}), blockDelta);\n if (mathErr != MathError.NO_ERROR) {\n
                                                                return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED, uint(mathErr));\n }\n\n
                                                                (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\n if (mathErr != MathError.NO_ERROR) {\n
                                                                return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED, uint(mathErr));\n }\n\n
                                                                (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\n if (mathErr != MathError.NO_ERROR) {\n return
                                                                failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED, uint(mathErr));\n }\n\n (mathErr,
                                                                totalReservesNew) = mulScalarTruncateAddUInt(Exp({mantissa: reserveFactorMantissa}), interestAccumulated, reservesPrior);\n if (mathErr !=
                                                                MathError.NO_ERROR) {\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED, uint
                                                                (mathErr));\n }\n\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\n
                                                                 if (mathErr != MathError.NO_ERROR) {\n return failOpaque(Error.MATH_ERROR, FailureInfo
                                                                .ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED, uint(mathErr));\n }\n\n /////////////////////////\n // EFFECTS \u0026
                                                                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 uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Sender supplies assets into the market and receives
                                                                sTokens 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(uint mintAmount) internal nonReentrant returns (uint, uint) {\n uint error = accrueInterest
                                                                ();\n if (error != uint(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\u0027t need to\n return mintFresh(msg.sender, mintAmount);\n
                                                                }\n\n struct MintLocalVars {\n Error err;\n MathError mathErr;\n uint exchangeRateMantissa;\n uint mintTokens;\n
                                                                 uint totalSupplyNew;\n uint accountTokensNew;\n uint actualMintAmount;\n }\n\n /**\n * @notice User supplies assets
                                                                into the market and receives sTokens 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, uint mintAmount) internal returns (uint, uint) {\n /* Fail if mint not allowed */\n uint 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\u0027s 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.mathErr, vars.exchangeRateMantissa) =
                                                                exchangeRateStoredInternal();\n if (vars.mathErr != MathError.NO_ERROR) {\n return (failOpaque(Error.MATH_ERROR, FailureInfo
                                                                .MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\n }\n\n /////////////////////////\n // EFFECTS \u0026 INTERACTIONS\n
                                                                 // (No safe failures beyond this point)\n\n /*\n * We call `doTransferIn` for the minter and the mintAmount.\n *
                                                                Note: The sToken must handle variations between ERC-20 and ETH underlying.\n * `doTransferIn` reverts if anything goes wrong, since we
                                                                can\u0027t be sure if\n * side-effects occurred. The function returns the amount actually transferred,\n * in case of a fee. On
                                                                success, the sToken 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 sTokens to be minted:\n * mintTokens =
                                                                actualMintAmount / exchangeRate\n */\n\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(vars.actualMintAmount, Exp
                                                                ({mantissa: vars.exchangeRateMantissa}));\n require(vars.mathErr == MathError.NO_ERROR, \"MINT_EXCHANGE_CALCULATION_FAILED\");\n\n
                                                                /*\n * We calculate the new total supply of sTokens and minter token balance, checking for overflow:\n * totalSupplyNew =
                                                                totalSupply + mintTokens\n * accountTokensNew = accountTokens[minter] + mintTokens\n */\n (vars.mathErr, vars
                                                                .totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\n require(vars.mathErr == MathError.NO_ERROR,
                                                                \"MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED\");\n\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens
                                                                );\n require(vars.mathErr == MathError.NO_ERROR, \"MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\");\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 (uint(Error.NO_ERROR), vars.actualMintAmount);\n }\n\n /**\n * @notice Sender
                                                                redeems sTokens in exchange for the underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n *
                                                                @param redeemTokens The number of sTokens to redeem into underlying\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for
                                                                details)\n */\n function redeemInternal(uint redeemTokens) internal nonReentrant returns (uint) {\n uint error = accrueInterest();\n
                                                                 if (error != uint(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\u0027t need to\n return redeemFresh(msg.sender, redeemTokens, 0);\n }\n\n /**\n *
                                                                @notice Sender redeems sTokens 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 sTokens\n * @return uint 0=success,
                                                                otherwise a failure (see ErrorReporter.sol for details)\n */\n function redeemUnderlyingInternal(uint redeemAmount) internal nonReentrant
                                                                returns (uint) {\n uint error = accrueInterest();\n if (error != uint(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\u0027t need to\n return
                                                                redeemFresh(msg.sender, 0, redeemAmount);\n }\n\n struct RedeemLocalVars {\n Error err;\n MathError mathErr;\n uint
                                                                exchangeRateMantissa;\n uint redeemTokens;\n uint redeemAmount;\n uint totalSupplyNew;\n uint accountTokensNew;\n
                                                                }\n\n /**\n * @notice User redeems sTokens 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
                                                                sTokens 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 sTokens (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(address payable redeemer, uint redeemTokensIn, uint
                                                                redeemAmountIn) internal returns (uint) {\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.mathErr, vars
                                                                .exchangeRateMantissa) = exchangeRateStoredInternal();\n if (vars.mathErr != MathError.NO_ERROR) {\n return failOpaque(Error
                                                                .MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr));\n }\n\n /* If redeemTokensIn \u003e 0: */\n if
                                                                (redeemTokensIn \u003e 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\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(Exp({mantissa: vars.exchangeRateMantissa}),
                                                                redeemTokensIn);\n if (vars.mathErr != MathError.NO_ERROR) {\n return failOpaque(Error.MATH_ERROR, FailureInfo
                                                                .REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED, uint(vars.mathErr));\n }\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\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(redeemAmountIn, Exp
                                                                ({mantissa: vars.exchangeRateMantissa}));\n if (vars.mathErr != MathError.NO_ERROR) {\n return failOpaque(Error
                                                                .MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED, uint(vars.mathErr));\n }\n\n vars.redeemAmount =
                                                                redeemAmountIn;\n }\n\n /* Fail if redeem not allowed */\n uint 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\u0027s 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.mathErr, vars.totalSupplyNew) =
                                                                subUInt(totalSupply, vars.redeemTokens);\n if (vars.mathErr != MathError.NO_ERROR) {\n return failOpaque(Error.MATH_ERROR,
                                                                FailureInfo.REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED, uint(vars.mathErr));\n }\n\n (vars.mathErr, vars.accountTokensNew) = subUInt
                                                                (accountTokens[redeemer], vars.redeemTokens);\n if (vars.mathErr != MathError.NO_ERROR) {\n return failOpaque(Error.MATH_ERROR,
                                                                FailureInfo.REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED, uint(vars.mathErr));\n }\n\n /* Fail gracefully if protocol has
                                                                insufficient cash */\n if (getCashPrior() \u003c vars.redeemAmount) {\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo
                                                                .REDEEM_TRANSFER_OUT_NOT_POSSIBLE);\n }\n\n /////////////////////////\n // EFFECTS \u0026 INTERACTIONS\n // (No safe
                                                                failures beyond this point)\n\n /*\n * We invoke doTransferOut for the redeemer and the redeemAmount.\n * Note: The sToken
                                                                must handle variations between ERC-20 and ETH underlying.\n * On success, the sToken has redeemAmount less of cash.\n *
                                                                doTransferOut reverts if anything goes wrong, since we can\u0027t 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 uint(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(uint borrowAmount) internal nonReentrant returns (uint) {\n uint error = accrueInterest();\n if (error != uint(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\u0027t need to\n return borrowFresh(msg.sender, borrowAmount);\n }\n\n struct BorrowLocalVars {\n MathError mathErr;\n
                                                                 uint accountBorrows;\n uint accountBorrowsNew;\n uint 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, uint borrowAmount) internal
                                                                returns (uint) {\n /* Fail if borrow not allowed */\n uint 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\u0027s 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() \u003c 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.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\n if (vars
                                                                .mathErr != MathError.NO_ERROR) {\n return failOpaque(Error.MATH_ERROR, FailureInfo.BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED, uint
                                                                (vars.mathErr));\n }\n\n (vars.mathErr, vars.accountBorrowsNew) = addUInt(vars.accountBorrows, borrowAmount);\n if (vars
                                                                .mathErr != MathError.NO_ERROR) {\n return failOpaque(Error.MATH_ERROR, FailureInfo.BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED
                                                                , uint(vars.mathErr));\n }\n\n (vars.mathErr, vars.totalBorrowsNew) = addUInt(totalBorrows, borrowAmount);\n if (vars.mathErr
                                                                != MathError.NO_ERROR) {\n return failOpaque(Error.MATH_ERROR, FailureInfo.BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED, uint(vars
                                                                .mathErr));\n }\n\n /////////////////////////\n // EFFECTS \u0026 INTERACTIONS\n // (No safe failures beyond this point
                                                                )\n\n /*\n * We invoke doTransferOut for the borrower and the borrowAmount.\n * Note: The sToken must handle variations
                                                                between ERC-20 and ETH underlying.\n * On success, the sToken borrowAmount less of cash.\n * doTransferOut reverts if anything
                                                                goes wrong, since we can\u0027t 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 uint(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(uint repayAmount) internal nonReentrant returns
                                                                (uint, uint) {\n uint error = accrueInterest();\n if (error != uint(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\u0027t
                                                                need to\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\n }\n\n /**\n * @notice Sender repays a borrow belonging
                                                                to borrower\n * @param borrower the account with the debt being payed off\n * @param repayAmount The amount to repay\n * @return (uint,
                                                                uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\n */\n function
                                                                repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\n uint error = accrueInterest
                                                                ();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an
                                                                attempted borrow failed\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\n }\n //
                                                                repayBorrowFresh emits repay-borrow-specific logs on errors, so we don\u0027t need to\n return repayBorrowFresh(msg.sender, borrower,
                                                                repayAmount);\n }\n\n struct RepayBorrowLocalVars {\n Error err;\n MathError mathErr;\n uint repayAmount;\n uint
                                                                borrowerIndex;\n uint accountBorrows;\n uint accountBorrowsNew;\n uint totalBorrowsNew;\n uint 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(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\n /* Fail if repayBorrow not allowed
                                                                */\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\n if (allowed != 0) {\n
                                                                return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed), 0);\n }\n\n /* Verify
                                                                market\u0027s 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.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal
                                                                (borrower);\n if (vars.mathErr != MathError.NO_ERROR) {\n return (failOpaque(Error.MATH_ERROR, FailureInfo
                                                                .REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED, uint(vars.mathErr)), 0);\n }\n\n /* If repayAmount == -1, repayAmount =
                                                                accountBorrows */\n if (repayAmount == uint(-1)) {\n vars.repayAmount = vars.accountBorrows;\n } else {\n vars
                                                                .repayAmount = repayAmount;\n }\n\n /////////////////////////\n // EFFECTS \u0026 INTERACTIONS\n // (No safe failures
                                                                beyond this point)\n\n /*\n * We call doTransferIn for the payer and the repayAmount\n * Note: The sToken must handle
                                                                variations between ERC-20 and ETH underlying.\n * On success, the sToken holds an additional repayAmount of cash.\n *
                                                                doTransferIn reverts if anything goes wrong, since we can\u0027t 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.mathErr, vars.accountBorrowsNew) = subUInt(vars
                                                                .accountBorrows, vars.actualRepayAmount);\n require(vars.mathErr == MathError.NO_ERROR,
                                                                \"REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED\");\n\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars
                                                                .actualRepayAmount);\n require(vars.mathErr == MathError.NO_ERROR, \"REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED\");\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 (uint
                                                                (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 sToken to be liquidated\n * @param
                                                                sTokenCollateral 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(address borrower, uint repayAmount, STokenInterface sTokenCollateral) internal nonReentrant returns (uint
                                                                , uint) {\n uint error = accrueInterest();\n if (error != uint(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 = sTokenCollateral.accrueInterest();\n if (error != uint(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\u0027t need to\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, sTokenCollateral
                                                                );\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 sToken to be liquidated\n * @param liquidator The address repaying the borrow and
                                                                seizing collateral\n * @param sTokenCollateral 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(address liquidator, address borrower, uint repayAmount, STokenInterface
                                                                sTokenCollateral) internal returns (uint, uint) {\n /* Fail if liquidate not allowed */\n uint allowed = comptroller
                                                                .liquidateBorrowAllowed(address(this), address(sTokenCollateral), liquidator, borrower, repayAmount);\n if (allowed != 0) {\n
                                                                return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\n }\n\n /* Verify
                                                                market\u0027s 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 sTokenCollateral market\u0027s block number equals
                                                                current block number */\n if (sTokenCollateral.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 == uint(-1)) {\n
                                                                return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\n }\n\n\n /* Fail if
                                                                repayBorrow fails */\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\n if
                                                                (repayBorrowError != uint(Error.NO_ERROR)) {\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0
                                                                );\n }\n\n /////////////////////////\n // EFFECTS \u0026 INTERACTIONS\n // (No safe failures beyond this point)\n\n
                                                                 /* We calculate the number of collateral tokens that will be seized */\n (uint amountSeizeError, uint seizeTokens) = comptroller
                                                                .liquidateCalculateSeizeTokens(address(this), address(sTokenCollateral), actualRepayAmount);\n require(amountSeizeError == uint(Error
                                                                .NO_ERROR), \"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\");\n\n /* Revert if borrower collateral token balance \u003c seizeTokens
                                                                */\n require(sTokenCollateral.balanceOf(borrower) \u003e= 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 uint seizeError;\n if (address(sTokenCollateral
                                                                ) == address(this)) {\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\n } else {\n
                                                                seizeError = sTokenCollateral.seize(liquidator, borrower, seizeTokens);\n }\n\n /* Revert if seize tokens fails (since we cannot be
                                                                sure of side effects) */\n require(seizeError == uint(Error.NO_ERROR), \"token seizure failed\");\n\n /* We emit a LiquidateBorrow
                                                                event */\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(sTokenCollateral), seizeTokens);\n\n /* We call the
                                                                defense hook */\n comptroller.liquidateBorrowVerify(address(this), address(sTokenCollateral), liquidator, borrower, actualRepayAmount,
                                                                seizeTokens);\n\n return (uint(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 sToken during the process of liquidation.\n * Its absolutely
                                                                critical to use msg.sender as the borrowed sToken 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 sTokens to seize\n * @return uint 0=success,
                                                                otherwise a failure (see ErrorReporter.sol for details)\n */\n function seize(address liquidator, address borrower, uint seizeTokens)
                                                                external nonReentrant returns (uint) {\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\n }\n\n struct
                                                                SeizeInternalLocalVars {\n MathError mathErr;\n uint borrowerTokensNew;\n uint liquidatorTokensNew;\n uint
                                                                liquidatorSeizeTokens;\n uint protocolSeizeTokens;\n uint protocolSeizeAmount;\n uint exchangeRateMantissa;\n uint
                                                                totalReservesNew;\n uint totalSupplyNew;\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 SToken.\n * Its absolutely
                                                                critical to use msg.sender as the seizer sToken and not a parameter.\n * @param seizerToken The contract seizing the collateral (i.e. borrowed
                                                                sToken)\n * @param liquidator The account receiving seized collateral\n * @param borrower The account having collateral seized\n *
                                                                @param seizeTokens The number of sTokens to seize\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n
                                                                */\n function seizeInternal(address seizerToken, address liquidator, address borrower, uint seizeTokens) internal returns (uint) {\n /*
                                                                Fail if seize not allowed */\n uint 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 // MathError mathErr;\n // uint borrowerTokensNew;\n //
                                                                uint liquidatorTokensNew;\n\n SeizeInternalLocalVars memory vars;\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 (vars.mathErr, vars.borrowerTokensNew) = subUInt
                                                                (accountTokens[borrower], seizeTokens);\n if (vars.mathErr != MathError.NO_ERROR) {\n return failOpaque(Error.MATH_ERROR,
                                                                FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(vars.mathErr));\n }\n\n vars.protocolSeizeTokens = mul_(seizeTokens, Exp
                                                                ({mantissa: protocolSeizeShareMantissa}));\n vars.liquidatorSeizeTokens = sub_(seizeTokens, vars.protocolSeizeTokens);\n\n (vars
                                                                .mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\n require(vars.mathErr == MathError.NO_ERROR, \"exchange rate math
                                                                error\");\n\n (vars.mathErr, vars.protocolSeizeAmount) = mulScalarTruncate(Exp({mantissa: vars.exchangeRateMantissa}), vars
                                                                .protocolSeizeTokens);\n if (vars.mathErr != MathError.NO_ERROR) {\n return failOpaque(Error.MATH_ERROR, FailureInfo
                                                                .LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(vars.mathErr));\n }\n\n vars.totalReservesNew = add_(totalReserves, vars
                                                                .protocolSeizeAmount);\n vars.totalSupplyNew = sub_(totalSupply, vars.protocolSeizeTokens);\n\n\n (vars.mathErr, vars
                                                                .liquidatorTokensNew) = addUInt(accountTokens[liquidator], vars.liquidatorSeizeTokens);\n if (vars.mathErr != MathError.NO_ERROR) {\n
                                                                 return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(vars.mathErr));\n }\n\n
                                                                /////////////////////////\n // EFFECTS \u0026 INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We write the
                                                                previously calculated values into storage */\n totalReserves = vars.totalReservesNew;\n totalSupply = vars.totalSupplyNew;\n
                                                                accountTokens[borrower] = vars.borrowerTokensNew;\n accountTokens[liquidator] = vars.liquidatorTokensNew;\n\n /* Emit a Transfer
                                                                event */\n emit Transfer(borrower, liquidator, vars.liquidatorSeizeTokens);\n emit Transfer(borrower, address(this), vars
                                                                .protocolSeizeTokens);\n emit ReservesAdded(address(this), vars.protocolSeizeAmount, vars.totalReservesNew);\n\n /* We call the
                                                                defense hook */\n comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\n\n return uint(Error
                                                                .NO_ERROR);\n }\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 (uint) {\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 uint(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 (uint) {\n //
                                                                Check caller is pendingAdmin and pendingAdmin ≠ 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 uint(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 (uint) {\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\u0027s comptroller to newComptroller\n
                                                                comptroller = newComptroller;\n\n // Emit NewComptroller(oldComptroller, newComptroller)\n emit NewComptroller(oldComptroller,
                                                                newComptroller);\n\n return uint(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(uint newReserveFactorMantissa) external
                                                                nonReentrant returns (uint) {\n uint error = accrueInterest();\n if (error != uint(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\u0027t 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(uint
                                                                newReserveFactorMantissa) internal returns (uint) {\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\u0027s 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 ≤ maxReserveFactor\n if (newReserveFactorMantissa \u003e
                                                                reserveFactorMaxMantissa) {\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\n }\n\n uint
                                                                oldReserveFactorMantissa = reserveFactorMantissa;\n reserveFactorMantissa = newReserveFactorMantissa;\n\n emit NewReserveFactor
                                                                (oldReserveFactorMantissa, newReserveFactorMantissa);\n\n return uint(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(uint addAmount) internal nonReentrant returns
                                                                (uint) {\n uint error = accrueInterest();\n if (error != uint(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\u0027t
                                                                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(uint addAmount) internal returns (uint, uint) {\n // totalReserves + actualAddAmount\n uint totalReservesNew;\n
                                                                 uint actualAddAmount;\n\n // We fail gracefully unless market\u0027s 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 \u0026 INTERACTIONS\n // (No safe failures beyond this point)\n\n
                                                                 /*\n * We call doTransferIn for the caller and the addAmount\n * Note: The sToken must handle variations between ERC-20 and
                                                                ETH underlying.\n * On success, the sToken holds an additional addAmount of cash.\n * doTransferIn reverts if anything goes wrong
                                                                , since we can\u0027t 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 = totalReserves + actualAddAmount;\n\n /* Revert
                                                                on overflow */\n require(totalReservesNew \u003e= totalReserves, \"add reserves unexpected overflow\");\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 (uint
                                                                (Error.NO_ERROR), actualAddAmount);\n }\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(uint reduceAmount) external nonReentrant returns (uint) {\n uint error = accrueInterest();\n if
                                                                (error != uint(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\u0027t 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(uint reduceAmount) internal returns (uint) {\n // totalReserves - reduceAmount\n uint 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\u0027s 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() \u003c reduceAmount) {\n return
                                                                fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\n }\n\n // Check reduceAmount ≤ reserves[n]
                                                                (totalReserves)\n if (reduceAmount \u003e totalReserves) {\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION
                                                                );\n }\n\n /////////////////////////\n // EFFECTS \u0026 INTERACTIONS\n // (No safe failures beyond this point)\n\n
                                                                 totalReservesNew = totalReserves - reduceAmount;\n // We checked reduceAmount \u003c= totalReserves above, so this should never revert
                                                                .\n require(totalReservesNew \u003c= totalReserves, \"reduce reserves unexpected underflow\");\n\n // Store reserves[n+1] =
                                                                reserves[n] - reduceAmount\n totalReserves = totalReservesNew;\n\n // doTransferOut reverts if anything goes wrong, since we
                                                                can\u0027t be sure if side effects occurred.\n doTransferOut(admin, reduceAmount);\n\n emit ReservesReduced(admin, reduceAmount,
                                                                totalReservesNew);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Accrues interest and reduces reserves by transferring
                                                                to reserve\n * @param reduceAmount Amount of reduction to reserves\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol
                                                                for details)\n */\n function _transferReserves(uint reduceAmount) external nonReentrant returns (uint) {\n uint error =
                                                                accrueInterest();\n if (error != uint(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.TRANSFER_RESERVES_ACCRUE_INTEREST_FAILED
                                                                );\n }\n // _transferReservesFresh emits reserve-reduction-specific logs on errors, so we don\u0027t need to.\n return
                                                                _transferReservesFresh(reduceAmount);\n }\n\n /**\n * @notice Reduces reserves by transferring to reserve\n * @param reduceAmount
                                                                Amount of reduction to reserves\n * @dev Requires fresh interest accrual\n * @return uint 0=success, otherwise a failure (see ErrorReporter
                                                                .sol for details)\n */\n function _transferReservesFresh(uint reduceAmount) internal returns (uint) {\n // totalReserves -
                                                                reduceAmount\n uint totalReservesNew;\n\n // Check caller is reserveGuardian\n if (msg.sender != IComptroller(address
                                                                (comptroller)).reserveGuardian()) {\n return fail(Error.UNAUTHORIZED, FailureInfo.TRANSFER_RESERVES_ADMIN_CHECK);\n }\n\n
                                                                // We fail gracefully unless market\u0027s block number equals current block number\n if (accrualBlockNumber != getBlockNumber()) {\n
                                                                 return fail(Error.MARKET_NOT_FRESH, FailureInfo.TRANSFER_RESERVES_FRESH_CHECK);\n }\n\n // Fail gracefully if protocol has
                                                                insufficient underlying cash\n if (getCashPrior() \u003c reduceAmount) {\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo
                                                                .TRANSFER_RESERVES_CASH_NOT_AVAILABLE);\n }\n\n // Check reduceAmount ≤ reserves[n] (totalReserves)\n if (reduceAmount \u003e
                                                                totalReserves) {\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_RESERVES_VALIDATION);\n }\n\n
                                                                /////////////////////////\n // EFFECTS \u0026 INTERACTIONS\n // (No safe failures beyond this point)\n\n totalReservesNew =
                                                                totalReserves - reduceAmount;\n // We checked reduceAmount \u003c= totalReserves above, so this should never revert.\n require
                                                                (totalReservesNew \u003c= totalReserves, \"reduce reserves unexpected underflow\");\n\n // Store reserves[n+1] = reserves[n] -
                                                                reduceAmount\n totalReserves = totalReservesNew;\n\n // doTransferOut reverts if anything goes wrong, since we can\u0027t be sure if
                                                                side effects occurred.\n doTransferOut(IComptroller(address(comptroller)).reserveAddress(), reduceAmount);\n\n emit TransferReserves
                                                                (IComptroller(address(comptroller)).reserveGuardian(), IComptroller(address(comptroller)).reserveAddress(), reduceAmount, totalReservesNew);\n\n
                                                                 return uint(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 (uint) {\n uint error = accrueInterest();\n if (error !=
                                                                uint(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\u0027t 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 (uint) {\n\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\u0027s
                                                                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\u0027s 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 uint(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 (uint
                                                                );\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, uint amount)
                                                                internal returns (uint);\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\u0027s balance, may revert due to insufficient cash held in the contract.\n * If
                                                                caller has checked protocol\u0027s balance, and verified it is \u003e= amount, this should not revert in normal conditions.\n */\n function
                                                                doTransferOut(address payable to, uint amount) internal;\n\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"},"STokenInterfaces.sol":{"content":"pragma
                                                                solidity ^0.5.16;\n\nimport \"./ComptrollerInterface.sol\";\nimport \"./InterestRateModel.sol\";\n\ncontract STokenStorage {\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 uint internal constant borrowRateMaxMantissa = 0.0005e16;\n\n /**\n * @notice Maximum fraction of
                                                                interest that can be set aside for reserves\n */\n uint 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-sToken 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 STokens (used when
                                                                totalSupply = 0)\n */\n uint internal initialExchangeRateMantissa;\n\n /**\n * @notice Fraction of interest currently set aside for
                                                                reserves\n */\n uint public reserveFactorMantissa;\n\n /**\n * @notice Block number that interest was last accrued at\n */\n
                                                                uint public accrualBlockNumber;\n\n /**\n * @notice Accumulator of the total earned interest rate since the opening of the market\n */\n
                                                                 uint public borrowIndex;\n\n /**\n * @notice Total amount of outstanding borrows of the underlying in this market\n */\n uint
                                                                public totalBorrows;\n\n /**\n * @notice Total amount of reserves of the underlying held in this market\n */\n uint public
                                                                totalReserves;\n\n /**\n * @notice Total number of tokens in circulation\n */\n uint public totalSupply;\n\n /**\n * @notice
                                                                Official record of token balances for each account\n */\n mapping (address =\u003e uint) internal accountTokens;\n\n /**\n * @notice
                                                                Approved token transfer amounts on behalf of others\n */\n mapping (address =\u003e mapping (address =\u003e uint)) 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 uint principal;\n uint interestIndex;\n }\n\n /**\n * @notice
                                                                Mapping of account addresses to outstanding borrow balances\n */\n mapping(address =\u003e BorrowSnapshot) internal accountBorrows;\n\n
                                                                /**\n * @notice Share of seized collateral that is added to reserves\n */\n uint public constant protocolSeizeShareMantissa = 5e16;
                                                                //5%\n\n}\n\ncontract STokenInterface is STokenStorage {\n /**\n * @notice Indicator that this is a SToken contract (for inspection)\n
                                                                */\n bool public constant isSToken = true;\n\n\n /*** Market Events ***/\n\n /**\n * @notice Event emitted when interest is accrued\n
                                                                 */\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\n\n /**\n * @notice Event
                                                                emitted when tokens are minted\n */\n event Mint(address minter, uint mintAmount, uint mintTokens);\n\n /**\n * @notice Event emitted
                                                                when tokens are redeemed\n */\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens);\n\n /**\n * @notice Event
                                                                emitted when underlying is borrowed\n */\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\n\n
                                                                 /**\n * @notice Event emitted when a borrow is repaid\n */\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint
                                                                accountBorrows, uint totalBorrows);\n\n /**\n * @notice Event emitted when a borrow is liquidated\n */\n event LiquidateBorrow
                                                                (address liquidator, address borrower, uint repayAmount, address sTokenCollateral, uint 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(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\n\n
                                                                 /**\n * @notice Event emitted when the reserves are added\n */\n event ReservesAdded(address benefactor, uint addAmount, uint
                                                                newTotalReserves);\n\n /**\n * @notice Event emitted when the reserves are reduced\n */\n event ReservesReduced(address admin, uint
                                                                reduceAmount, uint newTotalReserves);\n\n /**\n * @notice Event emitted when the reserves are transfered\n */\n event
                                                                TransferReserves(address guardian, address reserveAddress, uint reduceAmount, uint newTotalReserves);\n\n /**\n * @notice EIP20 Transfer
                                                                event\n */\n event Transfer(address indexed from, address indexed to, uint amount);\n\n /**\n * @notice EIP20 Approval event\n
                                                                */\n event Approval(address indexed owner, address indexed spender, uint amount);\n\n /**\n * @notice Failure event\n */\n event
                                                                Failure(uint error, uint info, uint detail);\n\n\n /*** User Interface ***/\n\n function transfer(address dst, uint amount) external returns
                                                                (bool);\n function transferFrom(address src, address dst, uint amount) external returns (bool);\n function approve(address spender, uint
                                                                amount) external returns (bool);\n function allowance(address owner, address spender) external view returns (uint);\n function balanceOf
                                                                (address owner) external view returns (uint);\n function balanceOfUnderlying(address owner) external returns (uint);\n function
                                                                getAccountSnapshot(address account) external view returns (uint, uint, uint, uint);\n function borrowRatePerBlock() external view returns (uint
                                                                );\n function supplyRatePerBlock() external view returns (uint);\n function totalBorrowsCurrent() external returns (uint);\n function
                                                                borrowBalanceCurrent(address account) external returns (uint);\n function borrowBalanceStored(address account) public view returns (uint);\n
                                                                function exchangeRateCurrent() public returns (uint);\n function exchangeRateStored() public view returns (uint);\n function getCash()
                                                                external view returns (uint);\n function accrueInterest() public returns (uint);\n function seize(address liquidator, address borrower, uint
                                                                seizeTokens) external returns (uint);\n\n\n /*** Admin Functions ***/\n\n function _setPendingAdmin(address payable newPendingAdmin) external
                                                                returns (uint);\n function _acceptAdmin() external returns (uint);\n function _setComptroller(ComptrollerInterface newComptroller) public
                                                                returns (uint);\n function _setReserveFactor(uint newReserveFactorMantissa) external returns (uint);\n function _reduceReserves(uint
                                                                reduceAmount) external returns (uint);\n function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint
                                                                );\n}\n\ncontract SErc20Storage {\n /**\n * @notice Underlying asset for this SToken\n */\n address public underlying;\n}\n\ncontract
                                                                SErc20Interface is SErc20Storage {\n\n /*** User Interface ***/\n\n function mint(uint mintAmount) external returns (uint);\n function
                                                                redeem(uint redeemTokens) external returns (uint);\n function redeemUnderlying(uint redeemAmount) external returns (uint);\n function borrow
                                                                (uint borrowAmount) external returns (uint);\n function repayBorrow(uint repayAmount) external returns (uint);\n function repayBorrowBehalf
                                                                (address borrower, uint repayAmount) external returns (uint);\n function liquidateBorrow(address borrower, uint repayAmount, STokenInterface
                                                                sTokenCollateral) external returns (uint);\n\n\n /*** Admin Functions ***/\n\n function _addReserves(uint addAmount) external returns (uint
                                                                );\n}\n\ncontract SDelegationStorage {\n /**\n * @notice Implementation address for this contract\n */\n address public
                                                                implementation;\n}\n\ncontract SDelegatorInterface is SDelegationStorage {\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(address implementation_, bool allowResign, bytes memory
                                                                becomeImplementationData) public;\n}\n\ncontract SDelegateInterface is SDelegationStorage {\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"},"STRK.sol":{"content"
                                                                :"pragma solidity ^0.5.16;\npragma experimental ABIEncoderV2;\n\ncontract STRK {\n /// @notice EIP-20 token name for this token\n string
                                                                public constant name = \"Strike Token\";\n\n /// @notice EIP-20 token symbol for this token\n string public constant symbol = \"STRK\";\n\n
                                                                 /// @notice EIP-20 token decimals for this token\n uint8 public constant decimals = 18;\n\n /// @notice Total number of tokens in
                                                                circulation\n uint public constant totalSupply = 6518828e18; // 6518828 STRK\n\n /// @notice Allowance amounts on behalf of others\n
                                                                mapping (address =\u003e mapping (address =\u003e uint96)) internal allowances;\n\n /// @notice Official record of token balances for each
                                                                account\n mapping (address =\u003e uint96) internal balances;\n\n /// @notice A record of each accounts delegate\n mapping (address
                                                                =\u003e address) public delegates;\n\n /// @notice A checkpoint for marking number of votes from a given block\n struct Checkpoint {\n
                                                                 uint32 fromBlock;\n uint96 votes;\n }\n\n /// @notice A record of votes checkpoints for each account, by index\n mapping (address
                                                                =\u003e mapping (uint32 =\u003e Checkpoint)) public checkpoints;\n\n /// @notice The number of checkpoints for each account\n mapping
                                                                (address =\u003e uint32) public numCheckpoints;\n\n /// @notice The EIP-712 typehash for the contract\u0027s domain\n bytes32 public constant
                                                                DOMAIN_TYPEHASH = keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n /// @notice The EIP-712 typehash for
                                                                the delegation struct used by the contract\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\"Delegation(address delegatee,uint256
                                                                nonce,uint256 expiry)\");\n\n /// @notice A record of states for signing / validating signatures\n mapping (address =\u003e uint) public
                                                                nonces;\n\n /// @notice An event thats emitted when an account changes its delegate\n event DelegateChanged(address indexed delegator,
                                                                address indexed fromDelegate, address indexed toDelegate);\n\n /// @notice An event thats emitted when a delegate account\u0027s vote balance
                                                                changes\n event DelegateVotesChanged(address indexed delegate, uint previousBalance, uint newBalance);\n\n /// @notice The standard EIP-20
                                                                transfer event\n event Transfer(address indexed from, address indexed to, uint256 amount);\n\n /// @notice The standard EIP-20 approval
                                                                event\n event Approval(address indexed owner, address indexed spender, uint256 amount);\n\n /**\n * @notice Construct a new Strk token\n
                                                                 * @param account The initial account to grant all the tokens\n */\n constructor(address account) public {\n balances[account] =
                                                                uint96(totalSupply);\n emit Transfer(address(0), account, totalSupply);\n }\n\n /**\n * @notice Get the number of tokens `spender`
                                                                is approved to spend on behalf of `account`\n * @param account The address of the account holding the funds\n * @param spender The address
                                                                of the account spending the funds\n * @return The number of tokens approved\n */\n function allowance(address account, address spender)
                                                                external view returns (uint) {\n return allowances[account][spender];\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 rawAmount The number
                                                                of tokens that are approved (2^256-1 means infinite)\n * @return Whether or not the approval succeeded\n */\n function approve(address
                                                                spender, uint rawAmount) external returns (bool) {\n uint96 amount;\n if (rawAmount == uint(-1)) {\n amount = uint96(-1
                                                                );\n } else {\n amount = safe96(rawAmount, \"Strk::approve: amount exceeds 96 bits\");\n }\n\n allowances[msg
                                                                .sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n /**\n * @notice Get the
                                                                number of tokens held by the `account`\n * @param account The address of the account to get the balance of\n * @return The number of tokens
                                                                held\n */\n function balanceOf(address account) external view returns (uint) {\n return balances[account];\n }\n\n /**\n *
                                                                @notice Transfer `amount` tokens from `msg.sender` to `dst`\n * @param dst The address of the destination account\n * @param rawAmount The
                                                                number of tokens to transfer\n * @return Whether or not the transfer succeeded\n */\n function transfer(address dst, uint rawAmount)
                                                                external returns (bool) {\n uint96 amount = safe96(rawAmount, \"Strk::transfer: amount exceeds 96 bits\");\n _transferTokens(msg
                                                                .sender, dst, amount);\n return true;\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 rawAmount The number of tokens to transfer\n
                                                                 * @return Whether or not the transfer succeeded\n */\n function transferFrom(address src, address dst, uint rawAmount) external returns
                                                                (bool) {\n address spender = msg.sender;\n uint96 spenderAllowance = allowances[src][spender];\n uint96 amount = safe96
                                                                (rawAmount, \"Strk::approve: amount exceeds 96 bits\");\n\n if (spender != src \u0026\u0026 spenderAllowance != uint96(-1)) {\n
                                                                uint96 newAllowance = sub96(spenderAllowance, amount, \"Strk::transferFrom: transfer amount exceeds spender allowance\");\n
                                                                allowances[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n }\n\n _transferTokens(src, dst,
                                                                amount);\n return true;\n }\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegatee The
                                                                address to delegate votes to\n */\n function delegate(address delegatee) public {\n return _delegate(msg.sender, delegatee);\n
                                                                }\n\n /**\n * @notice Delegates votes from signatory to `delegatee`\n * @param delegatee The address to delegate votes to\n * @param
                                                                nonce The contract state required to match the signature\n * @param expiry The time at which to expire the signature\n * @param v The
                                                                recovery byte of the signature\n * @param r Half of the ECDSA signature pair\n * @param s Half of the ECDSA signature pair\n */\n
                                                                function delegateBySig(address delegatee, uint nonce, uint expiry, uint8 v, bytes32 r, bytes32 s) public {\n bytes32 domainSeparator =
                                                                keccak256(abi.encode(DOMAIN_TYPEHASH, keccak256(bytes(name)), getChainId(), address(this)));\n bytes32 structHash = keccak256(abi.encode
                                                                (DELEGATION_TYPEHASH, delegatee, nonce, expiry));\n bytes32 digest = keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash
                                                                ));\n address signatory = ecrecover(digest, v, r, s);\n require(signatory != address(0), \"Strk::delegateBySig: invalid signature\"
                                                                );\n require(nonce == nonces[signatory]++, \"Strk::delegateBySig: invalid nonce\");\n require(now \u003c= expiry, \"Strk
                                                                ::delegateBySig: signature expired\");\n return _delegate(signatory, delegatee);\n }\n\n /**\n * @notice Gets the current votes
                                                                balance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\n
                                                                 function getCurrentVotes(address account) external view returns (uint96) {\n uint32 nCheckpoints = numCheckpoints[account];\n
                                                                return nCheckpoints \u003e 0 ? checkpoints[account][nCheckpoints - 1].votes : 0;\n }\n\n /**\n * @notice Determine the prior number of
                                                                votes for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent
                                                                misinformation.\n * @param account The address of the account to check\n * @param blockNumber The block number to get the vote balance at\n
                                                                 * @return The number of votes the account had as of the given block\n */\n function getPriorVotes(address account, uint blockNumber)
                                                                public view returns (uint96) {\n require(blockNumber \u003c block.number, \"Strk::getPriorVotes: not yet determined\");\n\n uint32
                                                                nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent
                                                                balance\n if (checkpoints[account][nCheckpoints - 1].fromBlock \u003c= blockNumber) {\n return checkpoints[account][nCheckpoints
                                                                - 1].votes;\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].fromBlock \u003e blockNumber) {\n
                                                                 return 0;\n }\n\n uint32 lower = 0;\n uint32 upper = nCheckpoints - 1;\n while (upper \u003e lower) {\n
                                                                 uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\n
                                                                 if (cp.fromBlock == blockNumber) {\n return cp.votes;\n } else if (cp.fromBlock \u003c blockNumber) {\n
                                                                 lower = center;\n } else {\n upper = center - 1;\n }\n }\n return checkpoints[account][lower]
                                                                .votes;\n }\n\n function _delegate(address delegator, address delegatee) internal {\n address currentDelegate = delegates[delegator]
                                                                ;\n uint96 delegatorBalance = balances[delegator];\n delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator,
                                                                currentDelegate, delegatee);\n\n _moveDelegates(currentDelegate, delegatee, delegatorBalance);\n }\n\n function _transferTokens
                                                                (address src, address dst, uint96 amount) internal {\n require(src != address(0), \"Strk::_transferTokens: cannot transfer from the zero
                                                                address\");\n require(dst != address(0), \"Strk::_transferTokens: cannot transfer to the zero address\");\n\n balances[src] = sub96
                                                                (balances[src], amount, \"Strk::_transferTokens: transfer amount exceeds balance\");\n balances[dst] = add96(balances[dst], amount, \"Strk
                                                                ::_transferTokens: transfer amount overflows\");\n emit Transfer(src, dst, amount);\n\n _moveDelegates(delegates[src], delegates[dst]
                                                                , amount);\n }\n\n function _moveDelegates(address srcRep, address dstRep, uint96 amount) internal {\n if (srcRep != dstRep
                                                                \u0026\u0026 amount \u003e 0) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n
                                                                 uint96 srcRepOld = srcRepNum \u003e 0 ? checkpoints[srcRep][srcRepNum - 1].votes : 0;\n uint96 srcRepNew = sub96(srcRepOld,
                                                                amount, \"Strk::_moveVotes: vote amount underflows\");\n _writeCheckpoint(srcRep, srcRepNum, srcRepOld, srcRepNew);\n
                                                                }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint96 dstRepOld =
                                                                dstRepNum \u003e 0 ? checkpoints[dstRep][dstRepNum - 1].votes : 0;\n uint96 dstRepNew = add96(dstRepOld, amount, \"Strk::_moveVotes:
                                                                vote amount overflows\");\n _writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew);\n }\n }\n }\n\n
                                                                function _writeCheckpoint(address delegatee, uint32 nCheckpoints, uint96 oldVotes, uint96 newVotes) internal {\n uint32 blockNumber = safe32
                                                                (block.number, \"Strk::_writeCheckpoint: block number exceeds 32 bits\");\n\n if (nCheckpoints \u003e 0 \u0026\u0026
                                                                checkpoints[delegatee][nCheckpoints - 1].fromBlock == blockNumber) {\n checkpoints[delegatee][nCheckpoints - 1].votes = newVotes;\n }
                                                                else {\n checkpoints[delegatee][nCheckpoints] = Checkpoint(blockNumber, newVotes);\n numCheckpoints[delegatee] = nCheckpoints + 1
                                                                ;\n }\n\n emit DelegateVotesChanged(delegatee, oldVotes, newVotes);\n }\n\n function safe32(uint n, string memory errorMessage)
                                                                internal pure returns (uint32) {\n require(n \u003c 2**32, errorMessage);\n return uint32(n);\n }\n\n function safe96(uint n,
                                                                string memory errorMessage) internal pure returns (uint96) {\n require(n \u003c 2**96, errorMessage);\n return uint96(n);\n }\n\n
                                                                 function add96(uint96 a, uint96 b, string memory errorMessage) internal pure returns (uint96) {\n uint96 c = a + b;\n require(c
                                                                \u003e= a, errorMessage);\n return c;\n }\n\n function sub96(uint96 a, uint96 b, string memory errorMessage) internal pure returns
                                                                (uint96) {\n require(b \u003c= a, errorMessage);\n return a - b;\n }\n\n function getChainId() internal pure returns (uint) {\n
                                                                 uint256 chainId;\n assembly { chainId := chainid() }\n return chainId;\n }\n}\n"},"Timelock.sol":{"content":"pragma
                                                                solidity ^0.5.16;\n\nimport \"./SafeMath.sol\";\n\ncontract Timelock {\n using SafeMath for uint;\n\n event NewAdmin(address indexed newAdmin
                                                                );\n event NewPendingAdmin(address indexed newPendingAdmin);\n event NewDelay(uint indexed newDelay);\n event CancelTransaction(bytes32
                                                                indexed txHash, address indexed target, uint value, string signature, bytes data, uint eta);\n event ExecuteTransaction(bytes32 indexed txHash,
                                                                address indexed target, uint value, string signature, bytes data, uint eta);\n event QueueTransaction(bytes32 indexed txHash, address indexed
                                                                target, uint value, string signature, bytes data, uint eta);\n\n uint public constant GRACE_PERIOD = 14 days;\n uint public constant
                                                                MINIMUM_DELAY = 2 days;\n uint public constant MAXIMUM_DELAY = 30 days;\n\n address public admin;\n address public pendingAdmin;\n uint
                                                                public delay;\n\n mapping (bytes32 =\u003e bool) public queuedTransactions;\n\n\n constructor(address admin_, uint delay_) public {\n
                                                                require(delay_ \u003e= MINIMUM_DELAY, \"Timelock::constructor: Delay must exceed minimum delay.\");\n require(delay_ \u003c= MAXIMUM_DELAY,
                                                                \"Timelock::setDelay: Delay must not exceed maximum delay.\");\n\n admin = admin_;\n delay = delay_;\n }\n\n function()
                                                                external payable { }\n\n function setDelay(uint delay_) public {\n require(msg.sender == address(this), \"Timelock::setDelay: Call must
                                                                come from Timelock.\");\n require(delay_ \u003e= MINIMUM_DELAY, \"Timelock::setDelay: Delay must exceed minimum delay.\");\n require
                                                                (delay_ \u003c= MAXIMUM_DELAY, \"Timelock::setDelay: Delay must not exceed maximum delay.\");\n delay = delay_;\n\n emit NewDelay
                                                                (delay);\n }\n\n function acceptAdmin() public {\n require(msg.sender == pendingAdmin, \"Timelock::acceptAdmin: Call must come from
                                                                pendingAdmin.\");\n admin = msg.sender;\n pendingAdmin = address(0);\n\n emit NewAdmin(admin);\n }\n\n function
                                                                setPendingAdmin(address pendingAdmin_) public {\n require(msg.sender == address(this), \"Timelock::setPendingAdmin: Call must come from
                                                                Timelock.\");\n pendingAdmin = pendingAdmin_;\n\n emit NewPendingAdmin(pendingAdmin);\n }\n\n function queueTransaction(address
                                                                target, uint value, string memory signature, bytes memory data, uint eta) public returns (bytes32) {\n require(msg.sender == admin,
                                                                \"Timelock::queueTransaction: Call must come from admin.\");\n require(eta \u003e= getBlockTimestamp().add(delay), \"Timelock
                                                                ::queueTransaction: Estimated execution block must satisfy delay.\");\n\n bytes32 txHash = keccak256(abi.encode(target, value, signature,
                                                                data, eta));\n queuedTransactions[txHash] = true;\n\n emit QueueTransaction(txHash, target, value, signature, data, eta);\n
                                                                return txHash;\n }\n\n function cancelTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public
                                                                {\n require(msg.sender == admin, \"Timelock::cancelTransaction: Call must come from admin.\");\n\n bytes32 txHash = keccak256(abi
                                                                .encode(target, value, signature, data, eta));\n queuedTransactions[txHash] = false;\n\n emit CancelTransaction(txHash, target, value
                                                                , signature, data, eta);\n }\n\n function executeTransaction(address target, uint value, string memory signature, bytes memory data, uint eta
                                                                ) public payable returns (bytes memory) {\n require(msg.sender == admin, \"Timelock::executeTransaction: Call must come from admin.\");\n\n
                                                                 bytes32 txHash = keccak256(abi.encode(target, value, signature, data, eta));\n require(queuedTransactions[txHash], \"Timelock
                                                                ::executeTransaction: Transaction hasn\u0027t been queued.\");\n require(getBlockTimestamp() \u003e= eta, \"Timelock::executeTransaction:
                                                                Transaction hasn\u0027t surpassed time lock.\");\n require(getBlockTimestamp() \u003c= eta.add(GRACE_PERIOD), \"Timelock::executeTransaction
                                                                : Transaction is stale.\");\n\n queuedTransactions[txHash] = false;\n\n bytes memory callData;\n\n if (bytes(signature).length
                                                                == 0) {\n callData = data;\n } else {\n callData = abi.encodePacked(bytes4(keccak256(bytes(signature))), data);\n
                                                                 }\n\n // solium-disable-next-line security/no-call-value\n (bool success, bytes memory returnData) = target.call.value(value
                                                                )(callData);\n require(success, \"Timelock::executeTransaction: Transaction execution reverted.\");\n\n emit ExecuteTransaction
                                                                (txHash, target, value, signature, data, eta);\n\n return returnData;\n }\n\n function getBlockTimestamp() internal view returns (uint
                                                                ) {\n // solium-disable-next-line security/no-block-members\n return block.timestamp;\n }\n}"},"Unitroller.sol":{"content":"pragma
                                                                solidity ^0.5.16;\n\nimport \"./ErrorReporter.sol\";\nimport \"./ComptrollerStorage.sol\";\n/**\n * @title ComptrollerCore\n * @dev Storage for the
                                                                comptroller is at this address, while execution is delegated to the `comptrollerImplementation`.\n * STokens should reference this contract as
                                                                their comptroller.\n */\ncontract Unitroller is UnitrollerAdminStorage, ComptrollerErrorReporter {\n\n /**\n * @notice Emitted when
                                                                pendingComptrollerImplementation is changed\n */\n event NewPendingImplementation(address oldPendingImplementation, address
                                                                newPendingImplementation);\n\n /**\n * @notice Emitted when pendingComptrollerImplementation is accepted, which means comptroller
                                                                implementation is updated\n */\n event NewImplementation(address oldImplementation, address newImplementation);\n\n /**\n * @notice
                                                                Emitted when pendingAdmin is changed\n */\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\n\n /**\n *
                                                                @notice Emitted when pendingAdmin is accepted, which means admin is updated\n */\n event NewAdmin(address oldAdmin, address newAdmin);\n\n
                                                                 constructor() public {\n // Set admin to caller\n admin = msg.sender;\n }\n\n /*** Admin Functions ***/\n function
                                                                _setPendingImplementation(address newPendingImplementation) public returns (uint) {\n\n if (msg.sender != admin) {\n return fail
                                                                (Error.UNAUTHORIZED, FailureInfo.SET_PENDING_IMPLEMENTATION_OWNER_CHECK);\n }\n\n address oldPendingImplementation =
                                                                pendingComptrollerImplementation;\n\n pendingComptrollerImplementation = newPendingImplementation;\n\n emit NewPendingImplementation
                                                                (oldPendingImplementation, pendingComptrollerImplementation);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Accepts new
                                                                implementation of comptroller. msg.sender must be pendingImplementation\n * @dev Admin function for new implementation to accept it\u0027s role
                                                                as implementation\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function
                                                                _acceptImplementation() public returns (uint) {\n // Check caller is pendingImplementation and pendingImplementation ≠ address(0)\n
                                                                if (msg.sender != pendingComptrollerImplementation || pendingComptrollerImplementation == address(0)) {\n return fail(Error.UNAUTHORIZED
                                                                , FailureInfo.ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK);\n }\n\n // Save current values for inclusion in log\n address
                                                                oldImplementation = comptrollerImplementation;\n address oldPendingImplementation = pendingComptrollerImplementation;\n\n
                                                                comptrollerImplementation = pendingComptrollerImplementation;\n\n pendingComptrollerImplementation = address(0);\n\n emit
                                                                NewImplementation(oldImplementation, comptrollerImplementation);\n emit NewPendingImplementation(oldPendingImplementation,
                                                                pendingComptrollerImplementation);\n\n return uint(Error.NO_ERROR);\n }\n\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 newPendingAdmin) public returns (uint) {\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 uint(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() public
                                                                returns (uint) {\n // Check caller is pendingAdmin and pendingAdmin ≠ 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 uint(Error.NO_ERROR);\n }\n\n
                                                                /**\n * @dev Delegates execution to an implementation contract.\n * It returns to the external caller whatever the implementation returns\n
                                                                 * or forwards reverts.\n */\n function () external payable {\n // delegate all other functions to current implementation\n
                                                                 (bool success, ) = comptrollerImplementation.delegatecall(msg.data);\n\n assembly {\n let free_mem_ptr := mload(0x40)\n
                                                                 returndatacopy(free_mem_ptr, 0, returndatasize)\n\n switch success\n case 0 { revert(free_mem_ptr, returndatasize)
                                                                }\n default { return(free_mem_ptr, returndatasize) }\n }\n }\n}\n"}}
                                                            XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

                                                            File 8 of 14: StrikeAggregatorPriceOracleV2
                                                            1
                                                            2
                                                            3
                                                            4
                                                            5
                                                            6
                                                            7
                                                            8
                                                            9
                                                            10
                                                            11
                                                            12
                                                            13
                                                            14
                                                            15
                                                            16
                                                            pragma solidity ^0.5.16;
                                                            pragma experimental ABIEncoderV2;
                                                            import "./PriceOracle.sol";
                                                            import "./SErc20.sol";
                                                            import "./EIP20Interface.sol";
                                                            import "./SafeMath.sol";
                                                            import "./AggregatorV2V3Interface.sol";
                                                            interface IStdReference {
                                                            /// A structure returned whenever someone requests for standard reference data.
                                                            struct ReferenceData {
                                                            uint256 rate; // base/quote exchange rate, multiplied by 1e18.
                                                            uint256 lastUpdatedBase; // UNIX epoch of the last time when base price gets updated.
                                                            uint256 lastUpdatedQuote; // UNIX epoch of the last time when quote price gets updated.
                                                            }
                                                            /// Returns the price data for the given base/quote pair. Revert if not available.
                                                            function getReferenceData(string calldata _base, string calldata _quote) external view returns (ReferenceData memory);
                                                            XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

                                                            File 9 of 14: EACAggregatorProxy
                                                            1
                                                            2
                                                            3
                                                            4
                                                            5
                                                            6
                                                            7
                                                            8
                                                            9
                                                            10
                                                            11
                                                            12
                                                            13
                                                            14
                                                            15
                                                            16
                                                            /**
                                                            *Submitted for verification at Etherscan.io on 2020-09-29
                                                            */
                                                            pragma solidity 0.6.6;
                                                            /**
                                                            * @title The Owned contract
                                                            * @notice A contract with helpers for basic contract ownership.
                                                            */
                                                            contract Owned {
                                                            address public owner;
                                                            address private pendingOwner;
                                                            XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

                                                            File 10 of 14: AccessControlledOCR2Aggregator
                                                            1
                                                            2
                                                            3
                                                            4
                                                            5
                                                            6
                                                            7
                                                            8
                                                            9
                                                            10
                                                            11
                                                            12
                                                            13
                                                            14
                                                            15
                                                            16
                                                            // SPDX-License-Identifier: MIT
                                                            pragma solidity =0.8.19;
                                                            import "./OCR2Aggregator.sol";
                                                            import "./SimpleReadAccessController.sol";
                                                            /**
                                                            * @notice Wrapper of OCR2Aggregator which checks read access on Aggregator-interface methods
                                                            */
                                                            contract AccessControlledOCR2Aggregator is OCR2Aggregator, SimpleReadAccessController {
                                                            constructor(
                                                            LinkTokenInterface _link,
                                                            int192 _minAnswer,
                                                            int192 _maxAnswer,
                                                            AccessControllerInterface _billingAccessController,
                                                            AccessControllerInterface _requesterAccessController,
                                                            uint8 _decimals,
                                                            string memory description
                                                            XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

                                                            File 11 of 14: SErc20Delegator
                                                            1
                                                            {"ComptrollerInterface.sol":{"content":"pragma solidity ^0.5.16;\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 sTokens) external returns (uint[] memory);\n function exitMarket(address sToken) external returns (uint);\n\n
                                                                 /*** Policy Hooks ***/\n\n function mintAllowed(address sToken, address minter, uint mintAmount) external returns (uint);\n function
                                                                mintVerify(address sToken, address minter, uint mintAmount, uint mintTokens) external;\n\n function redeemAllowed(address sToken, address
                                                                redeemer, uint redeemTokens) external returns (uint);\n function redeemVerify(address sToken, address redeemer, uint redeemAmount, uint
                                                                redeemTokens) external;\n\n function borrowAllowed(address sToken, address borrower, uint borrowAmount) external returns (uint);\n function
                                                                borrowVerify(address sToken, address borrower, uint borrowAmount) external;\n\n function repayBorrowAllowed(\n address sToken,\n
                                                                address payer,\n address borrower,\n uint repayAmount) external returns (uint);\n function repayBorrowVerify(\n address
                                                                sToken,\n address payer,\n address borrower,\n uint repayAmount,\n uint borrowerIndex) external;\n\n function
                                                                liquidateBorrowAllowed(\n address sTokenBorrowed,\n address sTokenCollateral,\n address liquidator,\n address borrower
                                                                ,\n uint repayAmount) external returns (uint);\n function liquidateBorrowVerify(\n address sTokenBorrowed,\n address
                                                                sTokenCollateral,\n address liquidator,\n address borrower,\n uint repayAmount,\n uint seizeTokens) external;\n\n
                                                                function seizeAllowed(\n address sTokenCollateral,\n address sTokenBorrowed,\n address liquidator,\n address borrower
                                                                ,\n uint seizeTokens) external returns (uint);\n function seizeVerify(\n address sTokenCollateral,\n address sTokenBorrowed
                                                                ,\n address liquidator,\n address borrower,\n uint seizeTokens) external;\n\n function transferAllowed(address sToken,
                                                                address src, address dst, uint transferTokens) external returns (uint);\n function transferVerify(address sToken, address src, address dst, uint
                                                                transferTokens) external;\n\n /*** Liquidity/Liquidation Calculations ***/\n\n function liquidateCalculateSeizeTokens(\n address
                                                                sTokenBorrowed,\n address sTokenCollateral,\n uint repayAmount) external view returns (uint, uint);\n}\n"},"InterestRateModel.sol"
                                                                :{"content":"pragma solidity ^0.5.16;\n\n/**\n * @title Strike\u0027s InterestRateModel Interface\n * @author Strike\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 amount of
                                                                reserves the market has\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\n */\n function getBorrowRate(uint
                                                                cash, uint borrows, uint reserves) external view returns (uint);\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 amount 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(uint cash, uint borrows,
                                                                uint reserves, uint reserveFactorMantissa) external view returns (uint);\n\n}\n"},"SErc20Delegator.sol":{"content":"pragma solidity ^0.5.16
                                                                ;\n\nimport \"./STokenInterfaces.sol\";\n\n/**\n * @title Strike\u0027s SErc20Delegator Contract\n * @notice STokens which wrap an EIP-20
                                                                underlying and delegate to an implementation\n * @author Strike\n */\ncontract SErc20Delegator is STokenInterface, SErc20Interface,
                                                                SDelegatorInterface {\n /**\n * @notice Construct a new money market\n * @param underlying_ The address of the underlying asset\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 * @param implementation_ The address of the implementation the contract delegates to\n * @param becomeImplementationData The
                                                                encoded args for becomeImplementation\n */\n constructor(address underlying_,\n ComptrollerInterface comptroller_,\n
                                                                 InterestRateModel interestRateModel_,\n uint initialExchangeRateMantissa_,\n string memory name_,\n
                                                                 string memory symbol_,\n uint8 decimals_,\n address payable admin_,\n address implementation_,\n
                                                                 bytes memory becomeImplementationData) public {\n // Creator of the contract is admin during initialization\n admin =
                                                                msg.sender;\n\n // First delegate gets to initialize the delegator (i.e. storage contract)\n delegateTo(implementation_, abi
                                                                .encodeWithSignature(\"initialize(address,address,address,uint256,string,string,uint8)\",\n
                                                                 underlying_,\n comptroller_,\n
                                                                 interestRateModel_,\n initialExchangeRateMantissa_,\n
                                                                 name_,\n symbol_,\n
                                                                 decimals_));\n\n // New implementations always get set via the settor (post-initialize)\n _setImplementation
                                                                (implementation_, false, becomeImplementationData);\n\n // Set the proper admin now that initialization is done\n admin = admin_;\n
                                                                 }\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(address
                                                                implementation_, bool allowResign, bytes memory becomeImplementationData) public {\n require(msg.sender == admin, \"SErc20Delegator
                                                                ::_setImplementation: Caller must be admin\");\n\n if (allowResign) {\n delegateToImplementation(abi.encodeWithSignature
                                                                (\"_resignImplementation()\"));\n }\n\n address oldImplementation = implementation;\n implementation = implementation_;\n\n
                                                                 delegateToImplementation(abi.encodeWithSignature(\"_becomeImplementation(bytes)\", becomeImplementationData));\n\n emit
                                                                NewImplementation(oldImplementation, implementation);\n }\n\n /**\n * @notice Sender supplies assets into the market and receives sTokens
                                                                in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param mintAmount The amount of the
                                                                underlying asset to supply\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function mint(uint
                                                                mintAmount) external returns (uint) {\n mintAmount; // Shh\n delegateAndReturn();\n }\n\n /**\n * @notice Sender redeems
                                                                sTokens in exchange for the underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param
                                                                redeemTokens The number of sTokens to redeem into underlying\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details
                                                                )\n */\n function redeem(uint redeemTokens) external returns (uint) {\n redeemTokens; // Shh\n delegateAndReturn();\n }\n\n
                                                                 /**\n * @notice Sender redeems sTokens 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(uint redeemAmount) external returns (uint) {\n
                                                                redeemAmount; // Shh\n delegateAndReturn();\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(uint borrowAmount) external returns (uint) {\n borrowAmount; // Shh\n
                                                                delegateAndReturn();\n }\n\n /**\n * @notice Sender repays their own borrow\n * @param repayAmount The amount to repay\n *
                                                                @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function repayBorrow(uint repayAmount) external
                                                                returns (uint) {\n repayAmount; // Shh\n delegateAndReturn();\n }\n\n /**\n * @notice Sender repays a borrow belonging to
                                                                borrower\n * @param borrower the account with the debt being payed off\n * @param repayAmount The amount to repay\n * @return uint 0
                                                                =success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function repayBorrowBehalf(address borrower, uint repayAmount)
                                                                external returns (uint) {\n borrower; repayAmount; // Shh\n delegateAndReturn();\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
                                                                sToken to be liquidated\n * @param sTokenCollateral 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 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n
                                                                 function liquidateBorrow(address borrower, uint repayAmount, STokenInterface sTokenCollateral) external returns (uint) {\n borrower;
                                                                repayAmount; sTokenCollateral; // Shh\n delegateAndReturn();\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, uint amount) external returns (bool) {\n dst; amount; // Shh\n
                                                                 delegateAndReturn();\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(address src, address dst, uint256 amount) external returns (bool) {\n src;
                                                                dst; amount; // Shh\n delegateAndReturn();\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 spender; amount; // Shh\n delegateAndReturn();\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 (uint) {\n owner; spender; // Shh\n delegateToViewAndReturn
                                                                ();\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 (uint) {\n owner; // Shh\n
                                                                 delegateToViewAndReturn();\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 (uint) {\n owner; // Shh\n delegateAndReturn();\n }\n\n /**\n
                                                                * @notice Get a snapshot of the account\u0027s 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) external view returns (uint, uint, uint, uint) {\n
                                                                account; // Shh\n delegateToViewAndReturn();\n }\n\n /**\n * @notice Returns the current per-block borrow interest rate for this
                                                                sToken\n * @return The borrow interest rate per block, scaled by 1e18\n */\n function borrowRatePerBlock() external view returns (uint)
                                                                {\n delegateToViewAndReturn();\n }\n\n /**\n * @notice Returns the current per-block supply interest rate for this sToken\n *
                                                                @return The supply interest rate per block, scaled by 1e18\n */\n function supplyRatePerBlock() external view returns (uint) {\n
                                                                delegateToViewAndReturn();\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 returns (uint) {\n delegateAndReturn();\n }\n\n /**\n
                                                                * @notice Accrue interest to updated borrowIndex and then calculate account\u0027s 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 returns (uint) {\n account; // Shh\n delegateAndReturn();\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 (uint) {\n account; // Shh\n
                                                                 delegateToViewAndReturn();\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 returns (uint) {\n delegateAndReturn();\n
                                                                }\n\n /**\n * @notice Calculates the exchange rate from the underlying to the SToken\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 (uint) {\n delegateToViewAndReturn();\n }\n\n /**\n * @notice Get cash balance of this sToken in the underlying
                                                                asset\n * @return The quantity of underlying asset owned by this contract\n */\n function getCash() external view returns (uint) {\n
                                                                 delegateToViewAndReturn();\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 (uint) {\n delegateAndReturn();\n }\n\n /**\n * @notice Transfers collateral
                                                                tokens (this market) to the liquidator.\n * @dev Will fail unless called by another sToken during the process of liquidation.\n * Its
                                                                absolutely critical to use msg.sender as the borrowed sToken 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 sTokens to seize\n * @return
                                                                uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function seize(address liquidator, address borrower, uint
                                                                seizeTokens) external returns (uint) {\n liquidator; borrower; seizeTokens; // Shh\n delegateAndReturn();\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 (uint) {\n newPendingAdmin; // Shh\n delegateAndReturn();\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 (uint) {\n newComptroller; // Shh\n delegateAndReturn();\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(uint
                                                                newReserveFactorMantissa) external returns (uint) {\n newReserveFactorMantissa; // Shh\n delegateAndReturn();\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 (uint) {\n delegateAndReturn();\n }\n\n /**\n * @notice Accrues interest and adds reserves by transferring from
                                                                admin\n * @param addAmount Amount of reserves to add\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n
                                                                 */\n function _addReserves(uint addAmount) external returns (uint) {\n addAmount; // Shh\n delegateAndReturn();\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(uint reduceAmount)
                                                                external returns (uint) {\n reduceAmount; // Shh\n delegateAndReturn();\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 (uint) {\n
                                                                newInterestRateModel; // Shh\n delegateAndReturn();\n }\n\n /**\n * @notice Internal method to delegate execution to another
                                                                contract\n * @dev It returns to the external caller whatever the implementation returns or forwards reverts\n * @param callee The contract
                                                                to delegatecall\n * @param data The raw data to delegatecall\n * @return The returned bytes from the delegatecall\n */\n function
                                                                delegateTo(address callee, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returnData) = callee
                                                                .delegatecall(data);\n assembly {\n if eq(success, 0) {\n revert(add(returnData, 0x20), returndatasize)\n
                                                                 }\n }\n return returnData;\n }\n\n /**\n * @notice Delegates execution to the implementation contract\n * @dev It
                                                                returns to the external caller whatever the implementation returns or forwards reverts\n * @param data The raw data to delegatecall\n *
                                                                @return The returned bytes from the delegatecall\n */\n function delegateToImplementation(bytes memory data) public returns (bytes memory)
                                                                {\n return delegateTo(implementation, data);\n }\n\n /**\n * @notice Delegates execution to an implementation contract\n *
                                                                @dev It returns to the external caller whatever the implementation returns or forwards reverts\n * There are an additional 2 prefix uints from
                                                                the wrapper returndata, which we ignore since we make an extra hop.\n * @param data The raw data to delegatecall\n * @return The returned
                                                                bytes from the delegatecall\n */\n function delegateToViewImplementation(bytes memory data) public view returns (bytes memory) {\n
                                                                (bool success, bytes memory returnData) = address(this).staticcall(abi.encodeWithSignature(\"delegateToImplementation(bytes)\", data));\n
                                                                assembly {\n if eq(success, 0) {\n revert(add(returnData, 0x20), returndatasize)\n }\n }\n
                                                                return abi.decode(returnData, (bytes));\n }\n\n function delegateToViewAndReturn() private view returns (bytes memory) {\n (bool
                                                                success, ) = address(this).staticcall(abi.encodeWithSignature(\"delegateToImplementation(bytes)\", msg.data));\n\n assembly {\n
                                                                let free_mem_ptr := mload(0x40)\n returndatacopy(free_mem_ptr, 0, returndatasize)\n\n switch success\n case 0 {
                                                                revert(free_mem_ptr, returndatasize) }\n default { return(add(free_mem_ptr, 0x40), returndatasize) }\n }\n }\n\n function
                                                                delegateAndReturn() private returns (bytes memory) {\n (bool success, ) = implementation.delegatecall(msg.data);\n\n assembly {\n
                                                                 let free_mem_ptr := mload(0x40)\n returndatacopy(free_mem_ptr, 0, returndatasize)\n\n switch success\n
                                                                case 0 { revert(free_mem_ptr, returndatasize) }\n default { return(free_mem_ptr, returndatasize) }\n }\n }\n\n /**\n *
                                                                @notice Delegates execution to an implementation contract\n * @dev It returns to the external caller whatever the implementation returns or
                                                                forwards reverts\n */\n function () external payable {\n require(msg.value == 0,\"SErc20Delegator:fallback: cannot send value to
                                                                fallback\");\n\n // delegate all other functions to current implementation\n delegateAndReturn();\n }\n}\n"},"STokenInterfaces
                                                                .sol":{"content":"pragma solidity ^0.5.16;\n\nimport \"./ComptrollerInterface.sol\";\nimport \"./InterestRateModel.sol\";\n\ncontract STokenStorage
                                                                {\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 uint internal constant borrowRateMaxMantissa = 0.0005e16;\n\n /**\n * @notice
                                                                Maximum fraction of interest that can be set aside for reserves\n */\n uint 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-sToken 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 STokens (used when
                                                                totalSupply = 0)\n */\n uint internal initialExchangeRateMantissa;\n\n /**\n * @notice Fraction of interest currently set aside for
                                                                reserves\n */\n uint public reserveFactorMantissa;\n\n /**\n * @notice Block number that interest was last accrued at\n */\n
                                                                uint public accrualBlockNumber;\n\n /**\n * @notice Accumulator of the total earned interest rate since the opening of the market\n */\n
                                                                 uint public borrowIndex;\n\n /**\n * @notice Total amount of outstanding borrows of the underlying in this market\n */\n uint
                                                                public totalBorrows;\n\n /**\n * @notice Total amount of reserves of the underlying held in this market\n */\n uint public
                                                                totalReserves;\n\n /**\n * @notice Total number of tokens in circulation\n */\n uint public totalSupply;\n\n /**\n * @notice
                                                                Official record of token balances for each account\n */\n mapping (address =\u003e uint) internal accountTokens;\n\n /**\n * @notice
                                                                Approved token transfer amounts on behalf of others\n */\n mapping (address =\u003e mapping (address =\u003e uint)) 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 uint principal;\n uint interestIndex;\n }\n\n /**\n * @notice
                                                                Mapping of account addresses to outstanding borrow balances\n */\n mapping(address =\u003e BorrowSnapshot) internal accountBorrows
                                                                ;\n}\n\ncontract STokenInterface is STokenStorage {\n /**\n * @notice Indicator that this is a SToken contract (for inspection)\n */\n
                                                                 bool public constant isSToken = true;\n\n\n /*** Market Events ***/\n\n /**\n * @notice Event emitted when interest is accrued\n
                                                                */\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\n\n /**\n * @notice Event
                                                                emitted when tokens are minted\n */\n event Mint(address minter, uint mintAmount, uint mintTokens);\n\n /**\n * @notice Event emitted
                                                                when tokens are redeemed\n */\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens);\n\n /**\n * @notice Event
                                                                emitted when underlying is borrowed\n */\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\n\n
                                                                 /**\n * @notice Event emitted when a borrow is repaid\n */\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint
                                                                accountBorrows, uint totalBorrows);\n\n /**\n * @notice Event emitted when a borrow is liquidated\n */\n event LiquidateBorrow
                                                                (address liquidator, address borrower, uint repayAmount, address sTokenCollateral, uint 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(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\n\n
                                                                 /**\n * @notice Event emitted when the reserves are added\n */\n event ReservesAdded(address benefactor, uint addAmount, uint
                                                                newTotalReserves);\n\n /**\n * @notice Event emitted when the reserves are reduced\n */\n event ReservesReduced(address admin, uint
                                                                reduceAmount, uint newTotalReserves);\n\n /**\n * @notice EIP20 Transfer event\n */\n event Transfer(address indexed from, address
                                                                indexed to, uint amount);\n\n /**\n * @notice EIP20 Approval event\n */\n event Approval(address indexed owner, address indexed
                                                                spender, uint amount);\n\n /**\n * @notice Failure event\n */\n event Failure(uint error, uint info, uint detail);\n\n\n /*** User
                                                                Interface ***/\n\n function transfer(address dst, uint amount) external returns (bool);\n function transferFrom(address src, address dst,
                                                                uint amount) external returns (bool);\n function approve(address spender, uint amount) external returns (bool);\n function allowance(address
                                                                owner, address spender) external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n function
                                                                balanceOfUnderlying(address owner) external returns (uint);\n function getAccountSnapshot(address account) external view returns (uint, uint,
                                                                uint, uint);\n function borrowRatePerBlock() external view returns (uint);\n function supplyRatePerBlock() external view returns (uint);\n
                                                                 function totalBorrowsCurrent() external returns (uint);\n function borrowBalanceCurrent(address account) external returns (uint);\n function
                                                                borrowBalanceStored(address account) public view returns (uint);\n function exchangeRateCurrent() public returns (uint);\n function
                                                                exchangeRateStored() public view returns (uint);\n function getCash() external view returns (uint);\n function accrueInterest() public
                                                                returns (uint);\n function seize(address liquidator, address borrower, uint seizeTokens) external returns (uint);\n\n\n /*** Admin Functions
                                                                ***/\n\n function _setPendingAdmin(address payable newPendingAdmin) external returns (uint);\n function _acceptAdmin() external returns (uint
                                                                );\n function _setComptroller(ComptrollerInterface newComptroller) public returns (uint);\n function _setReserveFactor(uint
                                                                newReserveFactorMantissa) external returns (uint);\n function _reduceReserves(uint reduceAmount) external returns (uint);\n function
                                                                _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint);\n}\n\ncontract SErc20Storage {\n /**\n * @notice
                                                                Underlying asset for this SToken\n */\n address public underlying;\n}\n\ncontract SErc20Interface is SErc20Storage {\n\n /*** User
                                                                Interface ***/\n\n function mint(uint mintAmount) external returns (uint);\n function redeem(uint redeemTokens) external returns (uint);\n
                                                                 function redeemUnderlying(uint redeemAmount) external returns (uint);\n function borrow(uint borrowAmount) external returns (uint);\n
                                                                function repayBorrow(uint repayAmount) external returns (uint);\n function repayBorrowBehalf(address borrower, uint repayAmount) external
                                                                returns (uint);\n function liquidateBorrow(address borrower, uint repayAmount, STokenInterface sTokenCollateral) external returns (uint);\n\n\n
                                                                 /*** Admin Functions ***/\n\n function _addReserves(uint addAmount) external returns (uint);\n}\n\ncontract SDelegationStorage {\n /**\n
                                                                 * @notice Implementation address for this contract\n */\n address public implementation;\n}\n\ncontract SDelegatorInterface is
                                                                SDelegationStorage {\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(address implementation_, bool allowResign, bytes memory becomeImplementationData)
                                                                public;\n}\n\ncontract SDelegateInterface is SDelegationStorage {\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"}}
                                                            XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

                                                            File 12 of 14: WBTC
                                                            1
                                                            2
                                                            3
                                                            4
                                                            5
                                                            6
                                                            7
                                                            8
                                                            9
                                                            10
                                                            11
                                                            12
                                                            13
                                                            14
                                                            15
                                                            16
                                                            pragma solidity 0.4.24;
                                                            // File: openzeppelin-solidity/contracts/token/ERC20/ERC20Basic.sol
                                                            /**
                                                            * @title ERC20Basic
                                                            * @dev Simpler version of ERC20 interface
                                                            * See https://github.com/ethereum/EIPs/issues/179
                                                            */
                                                            contract ERC20Basic {
                                                            function totalSupply() public view returns (uint256);
                                                            function balanceOf(address _who) public view returns (uint256);
                                                            function transfer(address _to, uint256 _value) public returns (bool);
                                                            event Transfer(address indexed from, address indexed to, uint256 value);
                                                            }
                                                            XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

                                                            File 13 of 14: EACAggregatorProxy
                                                            1
                                                            2
                                                            3
                                                            4
                                                            5
                                                            6
                                                            7
                                                            8
                                                            9
                                                            10
                                                            11
                                                            12
                                                            13
                                                            14
                                                            15
                                                            16
                                                            pragma solidity 0.6.6;
                                                            /**
                                                            * @title The Owned contract
                                                            * @notice A contract with helpers for basic contract ownership.
                                                            */
                                                            contract Owned {
                                                            address payable public owner;
                                                            address private pendingOwner;
                                                            event OwnershipTransferRequested(
                                                            address indexed from,
                                                            address indexed to
                                                            );
                                                            XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

                                                            File 14 of 14: AccessControlledOCR2Aggregator
                                                            1
                                                            2
                                                            3
                                                            4
                                                            5
                                                            6
                                                            7
                                                            8
                                                            9
                                                            10
                                                            11
                                                            12
                                                            13
                                                            14
                                                            15
                                                            16
                                                            // SPDX-License-Identifier: MIT
                                                            pragma solidity =0.8.19;
                                                            import "./OCR2Aggregator.sol";
                                                            import "./SimpleReadAccessController.sol";
                                                            /**
                                                            * @notice Wrapper of OCR2Aggregator which checks read access on Aggregator-interface methods
                                                            */
                                                            contract AccessControlledOCR2Aggregator is OCR2Aggregator, SimpleReadAccessController {
                                                            constructor(
                                                            LinkTokenInterface _link,
                                                            int192 _minAnswer,
                                                            int192 _maxAnswer,
                                                            AccessControllerInterface _billingAccessController,
                                                            AccessControllerInterface _requesterAccessController,
                                                            uint8 _decimals,
                                                            string memory description
                                                            XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX