Transaction Hash:
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 | ||
---|---|---|---|---|---|
0x3774E825...6FAa71DAB | |||||
0x94599741...208B5Db4b |
0.057262141146774777 Eth
Nonce: 156
|
0.056157334128491797 Eth
Nonce: 157
| 0.00110480701828298 | ||
0x95222290...5CC4BAfe5
Miner
| (beaverbuild) | 10.244844651002277708 Eth | 10.245820481002277708 Eth | 0.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
File 2 of 14: Unitroller
File 3 of 14: FiatTokenProxy
File 4 of 14: SErc20Delegate
File 5 of 14: FiatTokenV2_2
File 6 of 14: JumpRateModelV2
File 7 of 14: Comptroller
File 8 of 14: StrikeAggregatorPriceOracleV2
File 9 of 14: EACAggregatorProxy
File 10 of 14: AccessControlledOCR2Aggregator
File 11 of 14: SErc20Delegator
File 12 of 14: WBTC
File 13 of 14: EACAggregatorProxy
File 14 of 14: AccessControlledOCR2Aggregator
1{"ComptrollerInterface.sol":{"content":"pragma solidity ^0.5.16;\n\ncontract ComptrollerInterface {\n /// @notice Indicator that this is aComptroller contract (for inspection)\n bool public constant isComptroller = true;\n\n /*** Assets You Are In ***/\n\n functionenterMarkets(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 functionmintVerify(address sToken, address minter, uint mintAmount, uint mintTokens) external;\n\n function redeemAllowed(address sToken, addressredeemer, uint redeemTokens) external returns (uint);\n function redeemVerify(address sToken, address redeemer, uint redeemAmount, uintredeemTokens) external;\n\n function borrowAllowed(address sToken, address borrower, uint borrowAmount) external returns (uint);\n functionborrowVerify(address sToken, address borrower, uint borrowAmount) external;\n\n function repayBorrowAllowed(\n address sToken,\naddress payer,\n address borrower,\n uint repayAmount) external returns (uint);\n function repayBorrowVerify(\n addresssToken,\n address payer,\n address borrower,\n uint repayAmount,\n uint borrowerIndex) external;\n\n functionliquidateBorrowAllowed(\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 addresssTokenCollateral,\n address liquidator,\n address borrower,\n uint repayAmount,\n uint seizeTokens) external;\n\nfunction 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, uinttransferTokens) external;\n\n /*** Liquidity/Liquidation Calculations ***/\n\n function liquidateCalculateSeizeTokens(\n addresssTokenBorrowed,\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 */\ncontractInterestRateModel {\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\n bool public constantisInterestRateModel = true;\n\n /**\n * @notice Calculates the current borrow interest rate per block\n * @param cash The total amountof cash the market has\n * @param borrows The total amount of borrows the market has outstanding\n * @param reserves The total amount ofreserves the market has\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\n */\n function getBorrowRate(uintcash, uint borrows, uint reserves) external view returns (uint);\n\n /**\n * @notice Calculates the current supply interest rate perblock\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 markethas\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-20underlying 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 * @paraminitialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\n * @param name_ ERC-20 name of this token\n * @param symbol_ ERC-20symbol of this token\n * @param decimals_ ERC-20 decimal precision of this token\n * @param admin_ Address of the administrator of thistoken\n * @param implementation_ The address of the implementation the contract delegates to\n * @param becomeImplementationData Theencoded args for becomeImplementation\n */\n constructor(address underlying_,\n ComptrollerInterface comptroller_,\nInterestRateModel interestRateModel_,\n uint initialExchangeRateMantissa_,\n string memory name_,\nstring memory symbol_,\n uint8 decimals_,\n address payable admin_,\n address implementation_,\nbytes 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)\",\nunderlying_,\n comptroller_,\ninterestRateModel_,\n initialExchangeRateMantissa_,\nname_,\n symbol_,\ndecimals_));\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 thenew 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(addressimplementation_, 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\ndelegateToImplementation(abi.encodeWithSignature(\"_becomeImplementation(bytes)\", becomeImplementationData));\n\n emitNewImplementation(oldImplementation, implementation);\n }\n\n /**\n * @notice Sender supplies assets into the market and receives sTokensin exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param mintAmount The amount of theunderlying asset to supply\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function mint(uintmintAmount) external returns (uint) {\n mintAmount; // Shh\n delegateAndReturn();\n }\n\n /**\n * @notice Sender redeemssTokens in exchange for the underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @paramredeemTokens 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 notthe operation succeeds, unless reverted\n * @param redeemAmount The amount of underlying to redeem\n * @return uint 0=success, otherwise afailure (see ErrorReporter.sol for details)\n */\n function redeemUnderlying(uint redeemAmount) external returns (uint) {\nredeemAmount; // Shh\n delegateAndReturn();\n }\n\n /**\n * @notice Sender borrows assets from the protocol to their ownaddress\n * @param borrowAmount The amount of the underlying asset to borrow\n * @return uint 0=success, otherwise a failure (seeErrorReporter.sol for details)\n */\n function borrow(uint borrowAmount) external returns (uint) {\n borrowAmount; // Shh\ndelegateAndReturn();\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) externalreturns (uint) {\n repayAmount; // Shh\n delegateAndReturn();\n }\n\n /**\n * @notice Sender repays a borrow belonging toborrower\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 senderliquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param borrower The borrower of thissToken to be liquidated\n * @param sTokenCollateral The market in which to seize collateral from the borrower\n * @param repayAmount Theamount of the underlying borrowed asset to repay\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\nfunction 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 ornot the transfer succeeded\n */\n function transfer(address dst, uint amount) external returns (bool) {\n dst; amount; // Shh\ndelegateAndReturn();\n }\n\n /**\n * @notice Transfer `amount` tokens from `src` to `dst`\n * @param src The address of the sourceaccount\n * @param dst The address of the destination account\n * @param amount The number of tokens to transfer\n * @return Whether ornot 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 areapproved (-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 currentallowance from `owner` for `spender`\n * @param owner The address of the account which owns the tokens to be spent\n * @param spender Theaddress of the account which may transfer tokens\n * @return The number of tokens allowed to be spent (-1 means infinite)\n */\nfunction 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 * @returnThe number of tokens owned by `owner`\n */\n function balanceOf(address owner) external view returns (uint) {\n owner; // Shh\ndelegateToViewAndReturn();\n }\n\n /**\n * @notice Get the underlying balance of the `owner`\n * @dev This also accrues interest ina transaction\n * @param owner The address of the account to query\n * @return The amount of underlying owned by `owner`\n */\nfunction 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 efficientlyperform 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) {\naccount; // Shh\n delegateToViewAndReturn();\n }\n\n /**\n * @notice Returns the current per-block borrow interest rate for thissToken\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) {\ndelegateToViewAndReturn();\n }\n\n /**\n * @notice Returns the current total borrows plus accrued interest\n * @return The totalborrows 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 * @paramaccount The address whose balance should be calculated after updating borrowIndex\n * @return The calculated balance\n */\n functionborrowBalanceCurrent(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\ndelegateToViewAndReturn();\n }\n\n /**\n * @notice Accrue interest then return the up-to-date exchange rate\n * @returnCalculated 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 interestbefore calculating the exchange rate\n * @return Calculated exchange rate scaled by 1e18\n */\n function exchangeRateStored() publicview returns (uint) {\n delegateToViewAndReturn();\n }\n\n /**\n * @notice Get cash balance of this sToken in the underlyingasset\n * @return The quantity of underlying asset owned by this contract\n */\n function getCash() external view returns (uint) {\ndelegateToViewAndReturn();\n }\n\n /**\n * @notice Applies accrued interest to total borrows and reserves.\n * @dev Thiscalculates 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 collateraltokens (this market) to the liquidator.\n * @dev Will fail unless called by another sToken during the process of liquidation.\n * Itsabsolutely critical to use msg.sender as the borrowed sToken and not a parameter.\n * @param liquidator The account receiving seizedcollateral\n * @param borrower The account having collateral seized\n * @param seizeTokens The number of sTokens to seize\n * @returnuint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function seize(address liquidator, address borrower, uintseizeTokens) external returns (uint) {\n liquidator; borrower; seizeTokens; // Shh\n delegateAndReturn();\n }\n\n /*** AdminFunctions ***/\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 * @paramnewPendingAdmin 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 setsa 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(uintnewReserveFactorMantissa) 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 andupdate 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 fromadmin\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 andupdates the interest rate model using _setInterestRateModelFresh\n * @dev Admin function to accrue interest and update the interest ratemodel\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) {\nnewInterestRateModel; // Shh\n delegateAndReturn();\n }\n\n /**\n * @notice Internal method to delegate execution to anothercontract\n * @dev It returns to the external caller whatever the implementation returns or forwards reverts\n * @param callee The contractto delegatecall\n * @param data The raw data to delegatecall\n * @return The returned bytes from the delegatecall\n */\n functiondelegateTo(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 Itreturns 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 fromthe wrapper returndata, which we ignore since we make an extra hop.\n * @param data The raw data to delegatecall\n * @return The returnedbytes 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));\nassembly {\n if eq(success, 0) {\n revert(add(returnData, 0x20), returndatasize)\n }\n }\nreturn abi.decode(returnData, (bytes));\n }\n\n function delegateToViewAndReturn() private view returns (bytes memory) {\n (boolsuccess, ) = address(this).staticcall(abi.encodeWithSignature(\"delegateToImplementation(bytes)\", msg.data));\n\n assembly {\nlet 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 functiondelegateAndReturn() private returns (bytes memory) {\n (bool success, ) = implementation.delegatecall(msg.data);\n\n assembly {\nlet free_mem_ptr := mload(0x40)\n returndatacopy(free_mem_ptr, 0, returndatasize)\n\n switch success\ncase 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 orforwards reverts\n */\n function () external payable {\n require(msg.value == 0,\"SErc20Delegator:fallback: cannot send value tofallback\");\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 namefor 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 borrowrate that can ever be applied (.0005% / block)\n */\n\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\n\n /**\n * @noticeMaximum 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 thiscontract\n */\n address payable public pendingAdmin;\n\n /**\n * @notice Contract which oversees inter-sToken operations\n */\nComptrollerInterface public comptroller;\n\n /**\n * @notice Model which tells what the current interest rate should be\n */\nInterestRateModel public interestRateModel;\n\n /**\n * @notice Initial exchange rate used when minting the first STokens (used whentotalSupply = 0)\n */\n uint internal initialExchangeRateMantissa;\n\n /**\n * @notice Fraction of interest currently set aside forreserves\n */\n uint public reserveFactorMantissa;\n\n /**\n * @notice Block number that interest was last accrued at\n */\nuint public accrualBlockNumber;\n\n /**\n * @notice Accumulator of the total earned interest rate since the opening of the market\n */\nuint public borrowIndex;\n\n /**\n * @notice Total amount of outstanding borrows of the underlying in this market\n */\n uintpublic totalBorrows;\n\n /**\n * @notice Total amount of reserves of the underlying held in this market\n */\n uint publictotalReserves;\n\n /**\n * @notice Total number of tokens in circulation\n */\n uint public totalSupply;\n\n /**\n * @noticeOfficial record of token balances for each account\n */\n mapping (address =\u003e uint) internal accountTokens;\n\n /**\n * @noticeApproved token transfer amounts on behalf of others\n */\n mapping (address =\u003e mapping (address =\u003e uint)) internaltransferAllowances;\n\n /**\n * @notice Container for borrow balance information\n * @member principal Total balance (with accruedinterest), 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 * @noticeMapping 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 */\nbool 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 Eventemitted when tokens are minted\n */\n event Mint(address minter, uint mintAmount, uint mintTokens);\n\n /**\n * @notice Event emittedwhen tokens are redeemed\n */\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens);\n\n /**\n * @notice Eventemitted 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, uintaccountBorrows, 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(ComptrollerInterfaceoldComptroller, ComptrollerInterface newComptroller);\n\n /**\n * @notice Event emitted when interestRateModel is changed\n */\nevent NewMarketInterestRateModel(InterestRateModel oldInterestRateModel, InterestRateModel newInterestRateModel);\n\n /**\n * @notice Eventemitted 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, uintnewTotalReserves);\n\n /**\n * @notice Event emitted when the reserves are reduced\n */\n event ReservesReduced(address admin, uintreduceAmount, uint newTotalReserves);\n\n /**\n * @notice EIP20 Transfer event\n */\n event Transfer(address indexed from, addressindexed to, uint amount);\n\n /**\n * @notice EIP20 Approval event\n */\n event Approval(address indexed owner, address indexedspender, uint amount);\n\n /**\n * @notice Failure event\n */\n event Failure(uint error, uint info, uint detail);\n\n\n /*** UserInterface ***/\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(addressowner, address spender) external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n functionbalanceOfUnderlying(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);\nfunction totalBorrowsCurrent() external returns (uint);\n function borrowBalanceCurrent(address account) external returns (uint);\n functionborrowBalanceStored(address account) public view returns (uint);\n function exchangeRateCurrent() public returns (uint);\n functionexchangeRateStored() public view returns (uint);\n function getCash() external view returns (uint);\n function accrueInterest() publicreturns (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(uintnewReserveFactorMantissa) 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 * @noticeUnderlying asset for this SToken\n */\n address public underlying;\n}\n\ncontract SErc20Interface is SErc20Storage {\n\n /*** UserInterface ***/\n\n function mint(uint mintAmount) external returns (uint);\n function redeem(uint redeemTokens) external returns (uint);\nfunction redeemUnderlying(uint redeemAmount) external returns (uint);\n function borrow(uint borrowAmount) external returns (uint);\nfunction repayBorrow(uint repayAmount) external returns (uint);\n function repayBorrowBehalf(address borrower, uint repayAmount) externalreturns (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 isSDelegationStorage {\n /**\n * @notice Emitted when implementation is changed\n */\n event NewImplementation(addressoldImplementation, 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 itfor duty\n * @dev Should revert if any issues arise which make it unfit for delegation\n * @param data The encoded bytes data for anyinitialization\n */\n function _becomeImplementation(bytes memory data) public;\n\n /**\n * @notice Called by the delegator on adelegate to forfeit its responsibility\n */\n function _resignImplementation() public;\n}\n"}}
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 fromOpenZeppelin\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,\nDIVISION_BY_ZERO,\n INTEGER_OVERFLOW,\n INTEGER_UNDERFLOW\n }\n\n /**\n * @dev Multiplies two numbers, returns an erroron 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, truncatingthe 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(uinta, 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 subtractc\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 aComptroller contract (for inspection)\n bool public constant isComptroller = true;\n\n /*** Assets You Are In ***/\n\n functionenterMarkets(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 functionmintVerify(address sToken, address minter, uint mintAmount, uint mintTokens) external;\n\n function redeemAllowed(address sToken, addressredeemer, uint redeemTokens) external returns (uint);\n function redeemVerify(address sToken, address redeemer, uint redeemAmount, uintredeemTokens) external;\n\n function borrowAllowed(address sToken, address borrower, uint borrowAmount) external returns (uint);\n functionborrowVerify(address sToken, address borrower, uint borrowAmount) external;\n\n function repayBorrowAllowed(\n address sToken,\naddress payer,\n address borrower,\n uint repayAmount) external returns (uint);\n function repayBorrowVerify(\n addresssToken,\n address payer,\n address borrower,\n uint repayAmount,\n uint borrowerIndex) external;\n\n functionliquidateBorrowAllowed(\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 addresssTokenCollateral,\n address liquidator,\n address borrower,\n uint repayAmount,\n uint seizeTokens) external;\n\nfunction 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, uinttransferTokens) external;\n\n /*** Liquidity/Liquidation Calculations ***/\n\n function liquidateCalculateSeizeTokens(\n addresssTokenBorrowed,\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\ncontractComptrollerV1Storage is UnitrollerAdminStorage {\n\n /**\n * @notice Oracle which gives the price of any given asset\n */\nPriceOracle public oracle;\n\n /**\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\n */\nuint 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 oruse as collateral)\n */\n uint public maxAssets;\n\n /**\n * @notice Per-account mapping of \"assets you are in\", capped bymaxAssets\n */\n mapping(address =\u003e SToken[]) public accountAssets;\n\n}\n\ncontract ComptrollerV2Storage is ComptrollerV1Storage {\nstruct Market {\n /// @notice Whether or not this market is listed\n bool isListed;\n\n /**\n * @notice Multiplierrepresenting the most one can borrow against their collateral in this market.\n * For instance, 0.9 to allow borrowing 90% of collateralvalue.\n * Must be between 0 and 1, and stored as a mantissa.\n */\n uint collateralFactorMantissa;\n\n /// @noticePer-market mapping of \"accounts in this asset\"\n mapping(address =\u003e bool) accountMembership;\n\n /// @notice Whether or notthis 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 ThePause 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;\nmapping(address =\u003e bool) public mintGuardianPaused;\n mapping(address =\u003e bool) public borrowGuardianPaused;\n}\n\ncontractComptrollerV3Storage is ComptrollerV2Storage {\n struct StrikeMarketState {\n /// @notice The market\u0027s last updatedstrikeBorrowIndex or strikeSupplyIndex\n uint224 index;\n\n /// @notice The block number the index was last updated at\nuint32 block;\n }\n\n /// @notice A list of all markets\n SToken[] public allMarkets;\n\n /// @notice The rate at which the flywheeldistributes STRK, per block\n uint public strikeRate;\n\n /// @notice The portion of strikeRate that each market currently receives\nmapping(address =\u003e uint) public strikeSpeeds;\n\n /// @notice The STRK market supply state for each market\n mapping(address =\u003eStrikeMarketState) public strikeSupplyState;\n\n /// @notice The STRK market borrow state for each market\n mapping(address =\u003eStrikeMarketState) public strikeBorrowState;\n\n /// @notice The STRK borrow index for each market for each supplier as of the last time theyaccrued STRK\n mapping(address =\u003e mapping(address =\u003e uint)) public strikeSupplierIndex;\n\n /// @notice The STRK borrow index foreach market for each borrower as of the last time they accrued STRK\n mapping(address =\u003e mapping(address =\u003e uint)) publicstrikeBorrowerIndex;\n\n /// @notice The STRK accrued but not yet transferred to each user\n mapping(address =\u003e uint) publicstrikeAccrued;\n}\n\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\n // @notice The borrowCapGuardian can set borrowCaps to any numberfor any market. Lowering the borrow cap could disable borrowing on the given market.\n address public borrowCapGuardian;\n\n // @noticeBorrow 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 StandardInterface\n * https://eips.ethereum.org/EIPS/eip-20\n */\ninterface EIP20Interface {\n function name() external view returns (string memory);\nfunction symbol() external view returns (string memory);\n function decimals() external view returns (uint8);\n\n /**\n * @notice Getthe 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 beretrieved\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 Thenumber 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 thesource account\n * @param dst The address of the destination account\n * @param amount The number of tokens to transfer\n * @returnWhether 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 theaccount which may transfer tokens\n * @param amount The number of tokens that are approved (-1 means infinite)\n * @return Whether or notthe 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 meansinfinite)\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 ofERC20 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 ofthe specified address\n * @param owner The address from which the balance will be retrieved\n * @return The balance\n */\n functionbalanceOf(address owner) external view returns (uint256 balance);\n\n ///\n /// !!!!!!!!!!!!!!\n /// !!! NOTICE !!! `transfer` does notreturn 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 notreturn 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 * @paramamount 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 * andis subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\n * @param spender The address of the account which maytransfer tokens\n * @param amount The number of tokens that are approved\n * @return Whether or not the approval succeeded\n */\nfunction 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 theaccount 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);\nevent 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,\nINSUFFICIENT_SHORTFALL,\n INSUFFICIENT_LIQUIDITY,\n INVALID_CLOSE_FACTOR,\n INVALID_COLLATERAL_FACTOR,\nINVALID_LIQUIDATION_INCENTIVE,\n MARKET_NOT_ENTERED, // no longer possible\n MARKET_NOT_LISTED,\n MARKET_ALREADY_LISTED,\nMATH_ERROR,\n NONZERO_BORROW_BALANCE,\n PRICE_ERROR,\n REJECTION,\n SNAPSHOT_ERROR,\n TOO_MANY_ASSETS,\nTOO_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,\nSET_COLLATERAL_FACTOR_OWNER_CHECK,\n SET_COLLATERAL_FACTOR_NO_EXISTS,\n SET_COLLATERAL_FACTOR_VALIDATION,\nSET_COLLATERAL_FACTOR_WITHOUT_PRICE,\n SET_IMPLEMENTATION_OWNER_CHECK,\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\nSET_LIQUIDATION_INCENTIVE_VALIDATION,\n SET_MAX_ASSETS_OWNER_CHECK,\n SET_PENDING_ADMIN_OWNER_CHECK,\nSET_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 ora 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 upgradeablecollaborator contract\n */\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\n emitFailure(uint(err), uint(info), opaqueError);\n\n return uint(err);\n }\n}\n\ncontract TokenErrorReporter {\n enum Error {\nNO_ERROR,\n UNAUTHORIZED,\n BAD_INPUT,\n COMPTROLLER_REJECTION,\n COMPTROLLER_CALCULATION_ERROR,\nINTEREST_RATE_MODEL_ERROR,\n INVALID_ACCOUNT_PAIR,\n INVALID_CLOSE_AMOUNT_REQUESTED,\n INVALID_COLLATERAL_FACTOR,\nMATH_ERROR,\n MARKET_NOT_FRESH,\n MARKET_NOT_LISTED,\n TOKEN_INSUFFICIENT_ALLOWANCE,\n TOKEN_INSUFFICIENT_BALANCE,\nTOKEN_INSUFFICIENT_CASH,\n TOKEN_TRANSFER_IN_FAILED,\n TOKEN_TRANSFER_OUT_FAILED\n }\n\n /*\n * Note: FailureInfo (butnot Error) is kept in alphabetical order\n * This is because FailureInfo grows significantly faster, and\n * the order of Errorhas some meaning, while the order of FailureInfo\n * is entirely arbitrary.\n */\n enum FailureInfo {\nACCEPT_ADMIN_PENDING_ADMIN_CHECK,\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\nACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\nACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\nACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\nBORROW_ACCRUE_INTEREST_FAILED,\n BORROW_CASH_NOT_AVAILABLE,\n BORROW_FRESHNESS_CHECK,\nBORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\n BORROW_MARKET_NOT_LISTED,\nBORROW_COMPTROLLER_REJECTION,\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\nLIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\n LIQUIDATE_COMPTROLLER_REJECTION,\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\nLIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\n LIQUIDATE_FRESHNESS_CHECK,\nLIQUIDATE_LIQUIDATOR_IS_BORROWER,\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\nLIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\nLIQUIDATE_SEIZE_TOO_MUCH,\n MINT_ACCRUE_INTEREST_FAILED,\n MINT_COMPTROLLER_REJECTION,\n MINT_EXCHANGE_CALCULATION_FAILED,\nMINT_EXCHANGE_RATE_READ_FAILED,\n MINT_FRESHNESS_CHECK,\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\nMINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\n MINT_TRANSFER_IN_FAILED,\n MINT_TRANSFER_IN_NOT_POSSIBLE,\nREDEEM_ACCRUE_INTEREST_FAILED,\n REDEEM_COMPTROLLER_REJECTION,\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\nREDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\n REDEEM_EXCHANGE_RATE_READ_FAILED,\n REDEEM_FRESHNESS_CHECK,\nREDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\nREDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\n REDUCE_RESERVES_ADMIN_CHECK,\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\nREDUCE_RESERVES_FRESH_CHECK,\n REDUCE_RESERVES_VALIDATION,\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\nREPAY_BORROW_ACCRUE_INTEREST_FAILED,\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\n REPAY_BORROW_COMPTROLLER_REJECTION,\nREPAY_BORROW_FRESHNESS_CHECK,\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\nREPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\nSET_COLLATERAL_FACTOR_VALIDATION,\n SET_COMPTROLLER_OWNER_CHECK,\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\nSET_INTEREST_RATE_MODEL_FRESH_CHECK,\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\n SET_MAX_ASSETS_OWNER_CHECK,\nSET_ORACLE_MARKET_NOT_LISTED,\n SET_PENDING_ADMIN_OWNER_CHECK,\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\nSET_RESERVE_FACTOR_ADMIN_CHECK,\n SET_RESERVE_FACTOR_FRESH_CHECK,\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\nTRANSFER_COMPTROLLER_REJECTION,\n TRANSFER_NOT_ALLOWED,\n TRANSFER_NOT_ENOUGH,\n TRANSFER_TOO_MUCH,\nADD_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 thatenables 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, FailureInfoinfo, 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 storingfixed-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 */\ncontractExponential 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, Expmemory) {\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) internalpure 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(Expmemory 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 */\nfunction 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\nreturn (MathError.NO_ERROR, Exp({mantissa: scaledMantissa}));\n }\n\n /**\n * @dev Multiply an Exp by a scalar, then truncate to returnan 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\nreturn (MathError.NO_ERROR, truncate(product));\n }\n\n /**\n * @dev Multiply an Exp by a scalar, truncate, then add an to anunsigned integer, returning an unsigned integer.\n */\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internalpure returns (MathError, uint) {\n (MathError err, Exp memory product) = mulScalar(a, scalar);\n if (err != MathError.NO_ERROR) {\nreturn (err, 0);\n }\n\n return addUInt(truncate(product), addend);\n }\n\n /**\n * @dev Divide an Exp by ascalar, 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 ascalar by an Exp, returning a new Exp.\n */\n function divScalarByExp(uint scalar, Exp memory divisor) internal pure returns (MathError, Expmemory) {\n /*\n We are doing this as:\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\n\n How it works:\nExp = 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, thentruncate 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) {\nreturn (err, 0);\n }\n\n return (MathError.NO_ERROR, truncate(fraction));\n }\n\n /**\n * @dev Multiplies twoexponentials, 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) {\nreturn (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, Expmemory 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 twoexponentials, returning a new exponential.\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\n * which we can scale as an Expby 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 * Forexample, 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 purereturns (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 memoryright) internal pure returns (bool) {\n return left.mantissa \u003e right.mantissa;\n }\n\n /**\n * @dev returns true if Exp isexactly zero\n */\n function isZeroExp(Exp memory value) internal pure returns (bool) {\n return value.mantissa == 0;\n }\n\nfunction safe224(uint n, string memory errorMessage) internal pure returns (uint224) {\n require(n \u003c 2**224, errorMessage);\nreturn 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) {\nreturn 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 purereturns (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\nfunction 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);\nreturn 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 returnExp({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) {\nreturn 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) {\nreturn Double({mantissa: div_(a.mantissa, b)});\n }\n\n function div_(uint a, Double memory b) internal pure returns (uint) {\nreturn 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) {\nreturn 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 anInterestRateModel contract (for inspection)\n bool public constant isInterestRateModel = true;\n\n /**\n * @notice Calculates thecurrent borrow interest rate per block\n * @param cash The total amount of cash the market has\n * @param borrows The total amount ofborrows 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, andscaled 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 /// @noticeIndicator that this is a PriceOracle contract (for inspection)\n bool public constant isPriceOracle = true;\n\n /**\n * @notice Get theunderlying price of a sToken asset\n * @param sToken The sToken to get the underlying price of\n * @return The underlying asset pricemantissa (scaled by 1e18).\n * Zero means the price is unavailable.\n */\n function getUnderlyingPrice(SToken sToken) external viewreturns (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 * @authorStrike\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 * @paraminitialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\n * @param name_ EIP-20 name of this token\n * @param symbol_ EIP-20symbol of this token\n * @param decimals_ EIP-20 decimal precision of this token\n */\n function initialize(ComptrollerInterfacecomptroller_,\n InterestRateModel interestRateModel_,\n uint initialExchangeRateMantissa_,\nstring memory name_,\n string memory symbol_,\n uint8 decimals_) public {\nrequire(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 comptrollerfailed\");\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)\nerr = _setInterestRateModelFresh(interestRateModel_);\n require(err == uint(Error.NO_ERROR), \"setting interest rate model failed\");\n\nname = name_;\n symbol = symbol_;\n decimals = decimals_;\n\n // The counter starts true to prevent changing it fromzero 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 accountperforming 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(addressspender, 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, infinitefor 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 beyondthis point)\n\n accountTokens[src] = srsTokensNew;\n accountTokens[dst] = dstTokensNew;\n\n /* Eat some of the allowance (ifnecessary) */\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\nreturn uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\n * @param dst Theaddress 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 srcThe address of the source account\n * @param dst The address of the destination account\n * @param amount The number of tokens totransfer\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 * andis subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\n * @param spender The address of the account which maytransfer tokens\n * @param amount The number of tokens that are approved (-1 means infinite)\n * @return Whether or not the approvalsucceeded\n */\n function approve(address spender, uint256 amount) external returns (bool) {\n address src = msg.sender;\ntransferAllowances[src][spender] = amount;\n emit Approval(src, spender, amount);\n return true;\n }\n\n /**\n * @noticeGet 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 * @returnThe number of tokens owned by `owner`\n */\n function balanceOf(address owner) external view returns (uint256) {\n returnaccountTokens[owner];\n }\n\n /**\n * @notice Get the underlying balance of the `owner`\n * @dev This also accrues interest in atransaction\n * @param owner The address of the account to query\n * @return The amount of underlying owned by `owner`\n */\nfunction 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, andthe cached exchange rate\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\n * @param account Address ofthe account to snapshot\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\n */\n functiongetAccountSnapshot(address account) external view returns (uint, uint, uint, uint) {\n uint sTokenBalance = accountTokens[account];\nuint 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 * @devFunction to simply retrieve block number\n * This exists mainly for inheriting test contracts to stub this result.\n */\n functiongetBlockNumber() internal view returns (uint) {\n return block.number;\n }\n\n /**\n * @notice Returns the current per-blockborrow 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 Accrueinterest to updated borrowIndex and then calculate account\u0027s borrow balance using the updated borrowIndex\n * @param account The addresswhose 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\");\nreturn 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 * @noticeReturn 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) internalview returns (MathError, uint) {\n /* Note: we do not assert that the market is up to date */\n MathError mathErr;\n uintprincipalTimesIndex;\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 witha 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\nreturn (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 * @noticeCalculates the exchange rate from the underlying to the SToken\n * @dev This function does not accrue interest before calculating the exchangerate\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 tothe SToken\n * @dev This function does not accrue interest before calculating the exchange rate\n * @return (error code, calculatedexchange 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 */\nuint totalCash = getCashPrior();\n uint cashPlusBorrowsMinusReserves;\n Exp memory exchangeRate;\nMathError 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 sTokenin the underlying asset\n * @return The quantity of underlying asset owned by this contract\n */\n function getCash() external viewreturns (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 outof storage */\n uint cashPrior = getCashPrior();\n uint borrowsPrior = totalBorrows;\n uint reservesPrior = totalReserves;\nuint 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, uintblockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\n require(mathErr == MathError.NO_ERROR, \"could not calculate blockdelta\");\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 uintinterestAccumulated;\n uint totalBorrowsNew;\n uint totalReservesNew;\n uint borrowIndexNew;\n\n (mathErr,simpleInterestFactor) = mulScalar(Exp({mantissa: borrowRateMantissa}), blockDelta);\n if (mathErr != MathError.NO_ERROR) {\nreturn 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) {\nreturn 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 returnfailOpaque(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);\nif (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 \u0026INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We write the previously calculated values into storage */\naccrualBlockNumber = 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 receivessTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param mintAmount The amount ofthe underlying asset to supply\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actualmint 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 anattempted borrow failed\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\n }\n // mintFreshemits 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;\nuint totalSupplyNew;\n uint accountTokensNew;\n uint actualMintAmount;\n }\n\n /**\n * @notice User supplies assetsinto the market and receives sTokens in exchange\n * @dev Assumes interest has already been accrued up to the current block\n * @paramminter 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 functionmintFresh(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 equalscurrent 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 wecan\u0027t be sure if\n * side-effects occurred. The function returns the amount actually transferred,\n * in case of a fee. Onsuccess, 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 previouslycalculated 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 Senderredeems 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 fordetails)\n */\n function redeemInternal(uint redeemTokens) internal nonReentrant returns (uint) {\n uint error = accrueInterest();\nif (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but we still want to log the fact that anattempted redeem failed\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\n }\n // redeemFresh emitsredeem-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 operationsucceeds, 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 nonReentrantreturns (uint) {\n uint error = accrueInterest();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs onerrors, 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 returnredeemFresh(msg.sender, 0, redeemAmount);\n }\n\n struct RedeemLocalVars {\n Error err;\n MathError mathErr;\n uintexchangeRateMantissa;\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 tothe current block\n * @param redeemer The address of the account which is redeeming the tokens\n * @param redeemTokensIn The number ofsTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\n * @param redeemAmountIn The number ofunderlying 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, uintredeemAmountIn) internal returns (uint) {\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \"one of redeemTokensIn or redeemAmountInmust 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 thecurrent 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 hasinsufficient 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 safefailures beyond this point)\n\n /*\n * We invoke doTransferOut for the redeemer and the redeemAmount.\n * Note: The sTokenmust 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;\naccountTokens[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 theunderlying asset to borrow\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n functionborrowInternal(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\nreturn fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\n }\n // borrowFresh emits borrow-specific logs on errors, sowe don\u0027t need to\n return borrowFresh(msg.sender, borrowAmount);\n }\n\n struct BorrowLocalVars {\n MathError mathErr;\nuint accountBorrows;\n uint accountBorrowsNew;\n uint totalBorrowsNew;\n }\n\n /**\n * @notice Users borrow assetsfrom 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) internalreturns (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()) {\nreturn fail(Error.MARKET_NOT_FRESH, FailureInfo.BORROW_FRESHNESS_CHECK);\n }\n\n /* Fail gracefully if protocol hasinsufficient 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 borrowerand 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 variationsbetween ERC-20 and ETH underlying.\n * On success, the sToken borrowAmount less of cash.\n * doTransferOut reverts if anythinggoes wrong, since we can\u0027t be sure if side effects occurred.\n */\n doTransferOut(borrower, borrowAmount);\n\n /* Wewrite the previously calculated values into storage */\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\naccountBorrows[borrower].interestIndex = borrowIndex;\n totalBorrows = vars.totalBorrowsNew;\n\n /* We emit a Borrow event */\nemit 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 theirown borrow\n * @param repayAmount The amount to repay\n * @return (uint, uint) An error code (0=success, otherwise a failure, seeErrorReporter.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 onerrors, 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\u0027tneed to\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\n }\n\n /**\n * @notice Sender repays a borrow belongingto 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 functionrepayBorrowBehalfInternal(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 anattempted 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 uintborrowerIndex;\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 functionrepayBorrowFresh(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) {\nreturn (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed), 0);\n }\n\n /* Verifymarket\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 rememberthe original borrowerIndex for verification purposes */\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\n\n /* Wefetch 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 failuresbeyond this point)\n\n /*\n * We call doTransferIn for the payer and the repayAmount\n * Note: The sToken must handlevariations 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 actuallytransferred, in case of a fee.\n */\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\n\n /*\n * Wecalculate 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 /* Wewrite the previously calculated values into storage */\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\naccountBorrows[borrower].interestIndex = borrowIndex;\n totalBorrows = vars.totalBorrowsNew;\n\n /* We emit a RepayBorrow event */\nemit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\n\n /* We call the defensehook */\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 * Thecollateral seized is transferred to the liquidator.\n * @param borrower The borrower of this sToken to be liquidated\n * @paramsTokenCollateral The market in which to seize collateral from the borrower\n * @param repayAmount The amount of the underlying borrowed assetto 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\nreturn (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\n }\n\n // liquidateBorrowFresh emitsborrow-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 theliquidator.\n * @param borrower The borrower of this sToken to be liquidated\n * @param liquidator The address repaying the borrow andseizing collateral\n * @param sTokenCollateral The market in which to seize collateral from the borrower\n * @param repayAmount The amountof the underlying borrowed asset to repay\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), andthe actual repayment amount.\n */\n function liquidateBorrowFresh(address liquidator, address borrower, uint repayAmount, STokenInterfacesTokenCollateral) 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) {\nreturn (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\n }\n\n /* Verifymarket\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 equalscurrent 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)) {\nreturn (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\n }\n\n\n /* Fail ifrepayBorrow 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 thecollateral, 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 {\nseizeError = sTokenCollateral.seize(liquidator, borrower, seizeTokens);\n }\n\n /* Revert if seize tokens fails (since we cannot besure of side effects) */\n require(seizeError == uint(Error.NO_ERROR), \"token seizure failed\");\n\n /* We emit a LiquidateBorrowevent */\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(sTokenCollateral), seizeTokens);\n\n /* We call thedefense 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 (thismarket) to the liquidator.\n * @dev Will fail unless called by another sToken during the process of liquidation.\n * Its absolutelycritical 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 liquidateBorrowduring 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, addressborrower, 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 */\nif (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 thenew 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 \u0026INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We write the previously calculated values into storage */\naccountTokens[borrower] = borrowerTokensNew;\n accountTokens[liquidator] = liquidatorTokensNew;\n\n /* Emit a Transfer event */\nemit 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 tobegin 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 payablenewPendingAdmin) 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\naddress 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 returnuint(Error.NO_ERROR);\n }\n\n /**\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\n * @dev Adminfunction 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)\nif (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;\naddress oldPendingAdmin = pendingAdmin;\n\n // Store admin with value pendingAdmin\n admin = pendingAdmin;\n\n // Clear thepending 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 Adminfunction 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 methodreturned false\");\n\n // Set market\u0027s comptroller to newComptroller\n comptroller = newComptroller;\n\n // EmitNewComptroller(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 * @devAdmin function to accrue interest and set a new reserve factor\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol fordetails)\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 tolog 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 wedon\u0027t need to.\n return _setReserveFactorFresh(newReserveFactorMantissa);\n }\n\n /**\n * @notice Sets a new reserve factorfor 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) internalreturns (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) {\nreturn 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 bytransferring from msg.sender\n * @param addAmount Amount of addition to reserves\n * @return uint 0=success, otherwise a failure (seeErrorReporter.sol for details)\n */\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\n uinterror = accrueInterest();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but on top of that wewant 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\u0027tneed to.\n (error, ) = _addReservesFresh(addAmount);\n return error;\n }\n\n /**\n * @notice Add reserves by transferringfrom caller\n * @dev Requires fresh interest accrual\n * @param addAmount Amount of addition to reserves\n * @return (uint, uint) Anerror 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;\nuint 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 andETH 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\nactualAddAmount = doTransferIn(msg.sender, addAmount);\n\n totalReservesNew = totalReserves + actualAddAmount;\n\n /* Reverton 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]) */\nemit 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 attemptedreduce 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 * @paramreduceAmount Amount of reduction to reserves\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\nfunction _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\nif (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 returnfail(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\ntotalReservesNew = 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 wecan\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 modelusing _setInterestRateModelFresh\n * @dev Admin function to accrue interest and update the interest rate model\n * @paramnewInterestRateModel 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();\nif (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that anattempted 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.\nreturn _setInterestRateModelFresh(newInterestRateModel);\n }\n\n /**\n * @notice updates the interest rate model (*requires freshinterest accrual)\n * @dev Admin function to update the interest rate model\n * @param newInterestRateModel the new interest rate model touse\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 onsuccess\n InterestRateModel oldInterestRateModel;\n\n // Check caller is admin\n if (msg.sender != admin) {\nreturn fail(Error.UNAUTHORIZED, FailureInfo.SET_INTEREST_RATE_MODEL_OWNER_CHECK);\n }\n\n // We fail gracefully unless market\u0027sblock 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\noldInterestRateModel = 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\ninterestRateModel = newInterestRateModel;\n\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\nemit 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 currentmessage, 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 afee.\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 thanreverting.\n * If caller has not called checked protocol\u0027s balance, may revert due to insufficient cash held in the contract.\n * Ifcaller has checked protocol\u0027s balance, and verified it is \u003e= amount, this should not revert in normal conditions.\n */\n functiondoTransferOut(address payable to, uint amount) internal;\n\n\n /*** Reentrancy Guard ***/\n\n /**\n * @dev Prevents a contract fromcalling 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":"pragmasolidity ^0.5.16;\n\nimport \"./ComptrollerInterface.sol\";\nimport \"./InterestRateModel.sol\";\n\ncontract STokenStorage {\n /**\n * @devGuard 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 beapplied (.0005% / block)\n */\n\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\n\n /**\n * @notice Maximum fraction ofinterest that can be set aside for reserves\n */\n uint internal constant reserveFactorMaxMantissa = 1e18;\n\n /**\n * @noticeAdministrator 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 */\nComptrollerInterface public comptroller;\n\n /**\n * @notice Model which tells what the current interest rate should be\n */\nInterestRateModel public interestRateModel;\n\n /**\n * @notice Initial exchange rate used when minting the first STokens (used whentotalSupply = 0)\n */\n uint internal initialExchangeRateMantissa;\n\n /**\n * @notice Fraction of interest currently set aside forreserves\n */\n uint public reserveFactorMantissa;\n\n /**\n * @notice Block number that interest was last accrued at\n */\nuint public accrualBlockNumber;\n\n /**\n * @notice Accumulator of the total earned interest rate since the opening of the market\n */\nuint public borrowIndex;\n\n /**\n * @notice Total amount of outstanding borrows of the underlying in this market\n */\n uintpublic totalBorrows;\n\n /**\n * @notice Total amount of reserves of the underlying held in this market\n */\n uint publictotalReserves;\n\n /**\n * @notice Total number of tokens in circulation\n */\n uint public totalSupply;\n\n /**\n * @noticeOfficial record of token balances for each account\n */\n mapping (address =\u003e uint) internal accountTokens;\n\n /**\n * @noticeApproved token transfer amounts on behalf of others\n */\n mapping (address =\u003e mapping (address =\u003e uint)) internaltransferAllowances;\n\n /**\n * @notice Container for borrow balance information\n * @member principal Total balance (with accruedinterest), 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 * @noticeMapping 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 */\nbool 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 Eventemitted when tokens are minted\n */\n event Mint(address minter, uint mintAmount, uint mintTokens);\n\n /**\n * @notice Event emittedwhen tokens are redeemed\n */\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens);\n\n /**\n * @notice Eventemitted 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, uintaccountBorrows, 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(ComptrollerInterfaceoldComptroller, ComptrollerInterface newComptroller);\n\n /**\n * @notice Event emitted when interestRateModel is changed\n */\nevent NewMarketInterestRateModel(InterestRateModel oldInterestRateModel, InterestRateModel newInterestRateModel);\n\n /**\n * @notice Eventemitted 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, uintnewTotalReserves);\n\n /**\n * @notice Event emitted when the reserves are reduced\n */\n event ReservesReduced(address admin, uintreduceAmount, uint newTotalReserves);\n\n /**\n * @notice EIP20 Transfer event\n */\n event Transfer(address indexed from, addressindexed to, uint amount);\n\n /**\n * @notice EIP20 Approval event\n */\n event Approval(address indexed owner, address indexedspender, uint amount);\n\n /**\n * @notice Failure event\n */\n event Failure(uint error, uint info, uint detail);\n\n\n /*** UserInterface ***/\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(addressowner, address spender) external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n functionbalanceOfUnderlying(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);\nfunction totalBorrowsCurrent() external returns (uint);\n function borrowBalanceCurrent(address account) external returns (uint);\n functionborrowBalanceStored(address account) public view returns (uint);\n function exchangeRateCurrent() public returns (uint);\n functionexchangeRateStored() public view returns (uint);\n function getCash() external view returns (uint);\n function accrueInterest() publicreturns (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(uintnewReserveFactorMantissa) 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 * @noticeUnderlying asset for this SToken\n */\n address public underlying;\n}\n\ncontract SErc20Interface is SErc20Storage {\n\n /*** UserInterface ***/\n\n function mint(uint mintAmount) external returns (uint);\n function redeem(uint redeemTokens) external returns (uint);\nfunction redeemUnderlying(uint redeemAmount) external returns (uint);\n function borrow(uint borrowAmount) external returns (uint);\nfunction repayBorrow(uint repayAmount) external returns (uint);\n function repayBorrowBehalf(address borrower, uint repayAmount) externalreturns (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 isSDelegationStorage {\n /**\n * @notice Emitted when implementation is changed\n */\n event NewImplementation(addressoldImplementation, 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 itfor duty\n * @dev Should revert if any issues arise which make it unfit for delegation\n * @param data The encoded bytes data for anyinitialization\n */\n function _becomeImplementation(bytes memory data) public;\n\n /**\n * @notice Called by the delegator on adelegate 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 thecomptroller is at this address, while execution is delegated to the `comptrollerImplementation`.\n * STokens should reference this contract astheir comptroller.\n */\ncontract Unitroller is UnitrollerAdminStorage, ComptrollerErrorReporter {\n\n /**\n * @notice Emitted whenpendingComptrollerImplementation is changed\n */\n event NewPendingImplementation(address oldPendingImplementation, addressnewPendingImplementation);\n\n /**\n * @notice Emitted when pendingComptrollerImplementation is accepted, which means comptrollerimplementation is updated\n */\n event NewImplementation(address oldImplementation, address newImplementation);\n\n /**\n * @noticeEmitted 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\nconstructor() 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 newimplementation of comptroller. msg.sender must be pendingImplementation\n * @dev Admin function for new implementation to accept it\u0027s roleas 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)\nif (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 addressoldImplementation = comptrollerImplementation;\n address oldPendingImplementation = pendingComptrollerImplementation;\n\ncomptrollerImplementation = pendingComptrollerImplementation;\n\n pendingComptrollerImplementation = address(0);\n\n emitNewImplementation(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 newPendingAdminmust call `_acceptAdmin` to finalize the transfer.\n * @param newPendingAdmin New pending admin.\n * @return uint 0=success, otherwise afailure (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 // StorependingAdmin 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 andupdate admin\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _acceptAdmin() publicreturns (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 currentvalues for inclusion in log\n address oldAdmin = admin;\n address oldPendingAdmin = pendingAdmin;\n\n // Store admin withvalue pendingAdmin\n admin = pendingAdmin;\n\n // Clear the pending value\n pendingAdmin = address(0);\n\n emitNewAdmin(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)\nreturndatacopy(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"}}
File 3 of 14: FiatTokenProxy
12345678910111213141516pragma 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`.*/
File 4 of 14: SErc20Delegate
12345678910111213141516// File: contracts/ComptrollerInterface.solpragma 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);
File 5 of 14: FiatTokenV2_2
12345678910111213141516/*** 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.
File 6 of 14: JumpRateModelV2
12345678910111213141516pragma 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)
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 fromOpenZeppelin\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,\nDIVISION_BY_ZERO,\n INTEGER_OVERFLOW,\n INTEGER_UNDERFLOW\n }\n\n /**\n * @dev Multiplies two numbers, returns an erroron 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, truncatingthe 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(uinta, 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 subtractc\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 */\ncontractComptroller is ComptrollerV7Storage, ComptrollerInterface, ComptrollerErrorReporter, Exponential {\n /// @notice Emitted when an admin supportsa 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 eventNewPriceOracle(PriceOracle oldPriceOracle, PriceOracle newPriceOracle);\n\n /// @notice Emitted when pause guardian is changed\n eventNewPauseGuardian(address oldPauseGuardian, address newPauseGuardian);\n\n /// @notice Emitted when an action is paused globally\n eventActionPaused(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(boolstate);\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 newSTRK speed is calculated for a market\n event StrikeSpeedUpdated(SToken indexed sToken, uint newSpeed);\n\n /// @notice Emitted when STRK isdistributed to a supplier\n event DistributedSupplierStrike(SToken indexed sToken, address indexed supplier, uint strikeDelta, uintstrikeSupplyIndex);\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 eventContributorStrikeSpeedUpdated(address indexed contributor, uint newStrikeSpeed);\n\n /// @notice Emitted when Strike is granted\n eventStrikeGranted(address recipient, uint amount);\n\n /// @notice Emitted when a new borrow-side Strike speed is calculated for a market\nevent StrikeBorrowSpeedUpdated(SToken indexed sToken, uint newSpeed);\n\n /// @notice Emitted when a new supply-side Strike speed is calculatedfor a market\n event StrikeSupplySpeedUpdated(SToken indexed sToken, uint newSpeed);\n\n /// @notice Emitted when reserve guardian ischanged\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, addressnewMarketCapGuardian);\n\n /// @notice The initial STRK index for a market\n uint224 public constant strikeInitialIndex = 1e36;\n\n // NocollateralFactorMantissa 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 guardianand 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 */\nfunction getAssetsIn(address account) external view returns (SToken[] memory) {\n SToken[] memory assetsIn = accountAssets[account];\n\nreturn assetsIn;\n }\n\n /**\n * @notice Returns whether the given account is entered in the given asset\n * @param account Theaddress 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 sTokensThe 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\nresults[i] = uint(addToMarketInternal(sToken, msg.sender));\n }\n\n return results;\n }\n\n /**\n * @notice Add the marketto the borrower\u0027s \"assets in\" for liquidity calculations\n * @param sToken The market to enter\n * @param borrower The address ofthe 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 thegauntlet, add to list\n // NOTE: we store these somewhat redundantly as a significant optimization\n // this avoids having toiterate through the list for the most common use cases\n // that is, only when we need to perform liquidity checks\n // and notwhenever we want to check if an account is in a particular market\n marketToJoin.accountMembership[borrower] = true;\naccountAssets[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) {\nreturn fail(Error.NONZERO_BORROW_BALANCE, FailureInfo.EXIT_MARKET_BALANCE_OWED);\n }\n\n /* Fail if the sender is notpermitted 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 storagemarketToExit = 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 */\ndelete marketToExit.accountMembership[msg.sender];\n\n /* Delete sToken from the account’s list of assets */\n // load intomemory for faster iteration\n SToken[] memory userAssetList = accountAssets[msg.sender];\n uint len = userAssetList.length;\nuint 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 isbroken\n assert(assetIndex \u003c len);\n\n // copy last item in list to location of item to be removed, reduce length by 1\nSToken[] 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 mintagainst\n * @param minter The account which would get the minted tokens\n * @param mintAmount The amount of underlying being supplied tothe market in exchange for tokens\n * @return 0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\n */\nfunction mintAllowed(address sToken, address minter, uint mintAmount) external onlyProtocolAllowed returns (uint) {\n // Pausing is a veryserious 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();\nuint 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 beingminted\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, uintmintTokens) 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 toverify the redeem against\n * @param redeemer The account which would redeem the tokens\n * @param redeemTokens The number of sTokens toexchange 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) {\nuint allowed = redeemAllowedInternal(sToken, redeemer, redeemTokens);\n if (allowed != uint(Error.NO_ERROR)) {\n returnallowed;\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 liquiditycheck 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) {\nreturn uint(Error.INSUFFICIENT_LIQUIDITY);\n }\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Validates redeemand 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 */\nfunction redeemVerify(address sToken, address redeemer, uint redeemAmount, uint redeemTokens) external {\n // Shh - currently unused\nsToken;\n redeemer;\n\n // Require tokens is zero or amount is also zero\n if (redeemTokens == 0 \u0026\u0026redeemAmount \u003e 0) {\n revert(\"redeemTokens zero\");\n }\n }\n\n /**\n * @notice Checks if the account should beallowed to borrow the underlying asset of the given market\n * @param sToken The market to verify the borrow against\n * @param borrowerThe account which would borrow the asset\n * @param borrowAmount The amount of underlying the account would borrow\n * @return 0 if theborrow 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 thealarms\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 callborrowAllowed if borrower not in market\n require(msg.sender == sToken, \"sender must be sToken\");\n\n // attempt to addborrower to the market\n Error err = addToMarketInternal(SToken(msg.sender), borrower);\n if (err != Error.NO_ERROR) {\nreturn 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\nif (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 theflywheel 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 * @paramborrower The address borrowing the underlying\n * @param borrowAmount The amount of the underlying asset requested to borrow\n */\nfunction borrowVerify(address sToken, address borrower, uint borrowAmount) external {\n // Shh - currently unused\n sToken;\nborrower;\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 Theaccount which would borrowed the asset\n * @param repayAmount The amount of the underlying asset the account would repay\n * @return 0 ifthe 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\nreturn uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Validates repayBorrow and reverts on rejection. May emit logs.\n * @paramsToken Asset being repaid\n * @param payer The address repaying the borrow\n * @param borrower The address of the borrower\n * @paramactualRepayAmount 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\nsToken;\n payer;\n borrower;\n actualRepayAmount;\n borrowerIndex;\n }\n\n /**\n * @notice Checks if theliquidation should be allowed to occur\n * @param sTokenBorrowed Asset which was borrowed by the borrower\n * @param sTokenCollateral Assetwhich was used as collateral and will be seized\n * @param liquidator The address repaying the borrow and seizing the collateral\n * @paramborrower 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 uintrepayAmount) 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 uintborrowBalance = 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 }\nif (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 wasborrowed by the borrower\n * @param sTokenCollateral Asset which was used as collateral and will be seized\n * @param liquidator Theaddress repaying the borrow and seizing the collateral\n * @param borrower The address of the borrower\n * @param actualRepayAmount Theamount 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;\nseizeTokens;\n }\n\n /**\n * @notice Checks if the seizing of assets should be allowed to occur\n * @param sTokenCollateral Assetwhich was used as collateral and will be seized\n * @param sTokenBorrowed Asset which was borrowed by the borrower\n * @param liquidatorThe address repaying the borrow and seizing the collateral\n * @param borrower The address of the borrower\n * @param seizeTokens Thenumber of collateral tokens to seize\n */\n function seizeAllowed(\n address sTokenCollateral,\n address sTokenBorrowed,\naddress liquidator,\n address borrower,\n uint seizeTokens) external onlyProtocolAllowed returns (uint) {\n // Pausing isa 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\nif (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 collateraland will be seized\n * @param sTokenBorrowed Asset which was borrowed by the borrower\n * @param liquidator The address repaying the borrowand seizing the collateral\n * @param borrower The address of the borrower\n * @param seizeTokens The number of collateral tokens toseize\n */\n function seizeVerify(\n address sTokenCollateral,\n address sTokenBorrowed,\n address liquidator,\naddress borrower,\n uint seizeTokens) external {\n // Shh - currently unused\n sTokenCollateral;\n sTokenBorrowed;\nliquidator;\n borrower;\n seizeTokens;\n }\n\n /**\n * @notice Checks if the account should be allowed to transfertokens in the given market\n * @param sToken The market to verify the transfer against\n * @param src The account which sources thetokens\n * @param dst The account which receives the tokens\n * @param transferTokens The number of sTokens to transfer\n * @return 0if 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 - werevert to sound the alarms\n\n // Currently the only consideration is whether or not\n // the src is allowed to redeem this manytokens\n uint allowed = redeemAllowedInternal(sToken, src, transferTokens);\n if (allowed != uint(Error.NO_ERROR)) {\nreturn 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 Validatestransfer and reverts on rejection. May emit logs.\n * @param sToken Asset being transferred\n * @param src The account which sources thetokens\n * @param dst The account which receives the tokens\n * @param transferTokens The number of sTokens to transfer\n */\nfunction transferVerify(address sToken, address src, address dst, uint transferTokens) external {\n // Shh - currently unused\nsToken;\n src;\n dst;\n transferTokens;\n }\n\n /*** Liquidity/Liquidation Calculations ***/\n\n /**\n * @devLocal vars for avoiding stack-depth limits in calculating account liquidity.\n * Note that `sTokenBalance` is the number of sTokens theaccount owns in the market,\n * whereas `borrowBalance` is the amount of underlying that the account has borrowed.\n */\n structAccountLiquidityLocalVars {\n uint sumCollateral;\n uint sumBorrowPlusEffects;\n uint sTokenBalance;\n uintborrowBalance;\n uint exchangeRateMantissa;\n uint oraclePriceMantissa;\n Exp collateralFactor;\n Exp exchangeRate;\nExp oraclePrice;\n Exp tokensToDenom;\n }\n\n /**\n * @notice Determine the current account liquidity wrt collateralrequirements\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\nreturn (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 shortfallbelow collateral requirements)\n */\n function getAccountLiquidityInternal(address account) internal view returns (Error, uint, uint) {\nreturn getHypotheticalAccountLiquidityInternal(account, SToken(0), 0, 0);\n }\n\n /**\n * @notice Determine what the accountliquidity 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 * @paramborrowAmount The amount of underlying to hypothetically borrow\n * @return (possible error code (semi-opaque),\n hypotheticalaccount liquidity in excess of collateral requirements,\n * hypothetical account shortfall below collateral requirements)\n */\nfunction getHypotheticalAccountLiquidity(\n address account,\n address sTokenModify,\n uint redeemTokens,\n uintborrowAmount) 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 * @paramredeemTokens 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 addressaccount,\n SToken sTokenModify,\n uint redeemTokens,\n uint borrowAmount) internal view returns (Error, uint, uint) {\n\nAccountLiquidityLocalVars memory vars; // Holds all our calculation results\n uint oErr;\n MathError mErr;\n\n // For eachasset the account is in\n SToken[] memory assets = accountAssets[account];\n for (uint i = 0; i \u003c assets.length; i++) {\nSToken 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 assumeNO_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);\nif (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);\nif (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) {\nreturn (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 seizegiven an underlying amount\n * @dev Used in liquidation (called in sToken.liquidateBorrowFresh)\n * @param sTokenBorrowed The address ofthe borrowed sToken\n * @param sTokenCollateral The address of the collateral sToken\n * @param actualRepayAmount The amount ofsTokenBorrowed underlying to convert into sTokenCollateral tokens\n * @return (errorCode, number of sTokenCollateral tokens to be seized in aliquidation)\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));\nif (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;\nExp memory ratio;\n MathError mathErr;\n\n (mathErr, numerator) = mulExp(liquidationIncentiveMantissa, priceBorrowedMantissa);\nif (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 priceoracle\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setPriceOracle(PriceOraclenewOracle) 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 PriceOracleoldOracle = 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 newCloseFactorMantissaNew close factor, scaled by 1e18\n * @return uint 0=success, otherwise a failure\n */\n function _setCloseFactor(uintnewCloseFactorMantissa) external returns (uint) {\n // Check caller is admin\n \trequire(msg.sender == admin, \"only admin can set closefactor\");\n\n uint oldCloseFactorMantissa = closeFactorMantissa;\n closeFactorMantissa = newCloseFactorMantissa;\n emitNewCloseFactor(oldCloseFactorMantissa, closeFactorMantissa);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Sets thecollateralFactor for a market\n * @dev Admin function to set per-market collateralFactor\n * @param sToken The market to set the factoron\n * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18\n * @return uint 0=success, otherwise a failure. (SeeErrorReporter 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)];\nif (!market.isListed) {\n return fail(Error.MARKET_NOT_LISTED, FailureInfo.SET_COLLATERAL_FACTOR_NO_EXISTS);\n }\n\nExp memory newCollateralFactorExp = Exp({mantissa: newCollateralFactorMantissa});\n\n // Check collateral factor \u003c= 0.9\n Expmemory highLimit = Exp({mantissa: collateralFactorMaxMantissa});\n if (lessThanExp(highLimit, newCollateralFactorExp)) {\n returnfail(Error.INVALID_COLLATERAL_FACTOR, FailureInfo.SET_COLLATERAL_FACTOR_VALIDATION);\n }\n\n // If collateral factor != 0, fail ifprice == 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 collateralfactor, 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 emitNewCollateralFactor(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 newLiquidationIncentiveMantissaNew liquidationIncentive scaled by 1e18\n * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\n */\nfunction _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 liquidationincentive 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 setisListed and add support for the market\n * @param sToken The address of the market (token) to list\n * @return uint 0=success, otherwisea 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 emitMarketListed(sToken);\n\n return uint(Error.NO_ERROR);\n }\n\n function _initializeMarket(address sToken) internal {\n uint32blockNumber = safe32(getBlockNumber(), \"block number exceeds 32 bits\");\n\n StrikeMarketState storage supplyState =strikeSupplyState[sToken];\n StrikeMarketState storage borrowState = strikeBorrowState[sToken];\n\n /*\n * Update marketstate indices\n */\n if (supplyState.index == 0) {\n // Initialize supply state index with default value\nsupplyState.index = strikeInitialIndex;\n }\n\n if (borrowState.index == 0) {\n // Initialize borrow state index withdefault 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 * @noticeAdmin 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) {\nif (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 valuenewPauseGuardian\n pauseGuardian = newPauseGuardian;\n\n // Emit NewPauseGuardian(OldPauseGuardian, NewPauseGuardian)\n emitNewPauseGuardian(oldPauseGuardian, pauseGuardian);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Set whole protocolpause/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) publicreturns (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, \"onlyadmin can unpause\");\n\n borrowGuardianPaused[address(sToken)] = state;\n emit ActionPaused(sToken, \"Borrow\", state);\nreturn 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 returnfail(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)\nemit 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 setstrk staking info\");\n\n address oldStrkStaking = strkStaking;\n\n strkStaking = newStrkStaking;\n\n // EmitNewStrkStakingInfo(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 ofthe 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 ormarketCapGuardian 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 * @paramnewBorrowCaps 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 \u003cnumMarkets; 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 becomingthe 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 * @paramborrowSpeeds 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::_setCompSpeedsinvalid 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 {\nMarket 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));\nstrikeSupplySpeeds[address(sToken)] = supplySpeed;\n emit StrikeSupplySpeedUpdated(sToken, supplySpeed);\n }\n\n if(strikeBorrowSpeeds[address(sToken)] != borrowSpeed) {\n Exp memory borrowIndex = Exp({mantissa: sToken.borrowIndex()});\nupdateStrikeBorrowIndex(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 themarket 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 uintsupplyTokens = 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 byupdating the borrow index\n * @param sToken The market whose borrow index to update\n */\n function updateStrikeBorrowIndex(addresssToken, Exp memory marketBorrowIndex) internal {\n StrikeMarketState storage borrowState = strikeBorrowState[sToken];\n uintborrowSpeed = strikeBorrowSpeeds[sToken];\n uint32 blockNumber = safe32(getBlockNumber(), \"block number exceeds 32 bits\");\n uintdeltaBlocks = sub_(uint(blockNumber), uint(borrowState.block));\n if (deltaBlocks \u003e 0 \u0026\u0026 borrowSpeed \u003e 0) {\nuint borrowAmount = div_(SToken(sToken).totalBorrows(), marketBorrowIndex);\n uint strikeAccrued = mul_(deltaBlocks, borrowSpeed);\nDouble 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 * @noticeCalculate 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;\nuint 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\nDouble 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);\nstrikeAccrued[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 toaccrue until after the first interaction with the protocol.\n * @param sToken The market in which the borrower is interacting\n * @paramborrower The address of the borrower to distribute STRK to\n */\n function distributeBorrowerStrike(address sToken, address borrower, Expmemory 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 uintborrowerAmount = 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 Theaddress 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 {\naddress[] 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 ofmarkets to claim STRK in\n * @param borrowers Whether or not to claim STRK earned by borrowing\n * @param suppliers Whether or not to claimSTRK 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++) {\ndistributeSupplierStrike(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 andstaking 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, uintamount) internal returns (uint) {\n if (strkStaking != address(0)) {\n STRK strk = STRK(getSTRKAddress());\n uintstrkRemaining = 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 STRKto 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 totransfer STRK to\n * @param amount The amount of STRK to (possibly) transfer\n * @return The amount of STRK which was NOT transferred tothe 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) {\nstrk.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 contributorrewards\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\nstrikeAccrued[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 strikeSpeedNew 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\nupdateContributorRewards(contributor);\n\n if (strikeSpeed == 0) {\n // release storage\n deletelastContributorBlock[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 transferSTRK 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);\nrequire(amountLeft == 0, \"Insufficient STRK for grant\");\n\n emit StrikeGranted(recipient, amount);\n }\n\n /**\n * @noticeReturn all of the markets\n * @dev The automatic getter may be used to access an individual market.\n * @return The list of marketaddresses\n */\n function getAllMarkets() public view returns (SToken[] memory) {\n return allMarkets;\n }\n\n functiongetBlockNumber() public view returns (uint) {\n return block.number;\n }\n\n /**\n * @notice Return the address of the STRKtoken\n * @return The address of STRK\n */\n function getSTRKAddress() public view returns (address) {\n return0x74232704659ef37c08995e386A2E26cc27a8d7B1;\n }\n\n}\n"},"ComptrollerInterface.sol":{"content":"pragma solidity ^0.5.16;\n\ncontractComptrollerInterface {\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 functionexitMarket(address sToken) external returns (uint);\n\n /*** Policy Hooks ***/\n\n function mintAllowed(address sToken, address minter, uintmintAmount) external returns (uint);\n function mintVerify(address sToken, address minter, uint mintAmount, uint mintTokens) external;\n\nfunction 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 functionrepayBorrowAllowed(\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,\nuint borrowerIndex) external;\n\n function liquidateBorrowAllowed(\n address sTokenBorrowed,\n address sTokenCollateral,\naddress liquidator,\n address borrower,\n uint repayAmount) external returns (uint);\n function liquidateBorrowVerify(\naddress sTokenBorrowed,\n address sTokenCollateral,\n address liquidator,\n address borrower,\n uint repayAmount,\nuint seizeTokens) external;\n\n function seizeAllowed(\n address sTokenCollateral,\n address sTokenBorrowed,\n addressliquidator,\n address borrower,\n uint seizeTokens) external returns (uint);\n function seizeVerify(\n addresssTokenCollateral,\n address sTokenBorrowed,\n address liquidator,\n address borrower,\n uint seizeTokens) external;\n\nfunction 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 functionliquidateCalculateSeizeTokens(\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);\nfunction 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 thiscontract\n */\n address public admin;\n\n /**\n * @notice Pending administrator for this contract\n */\n address publicpendingAdmin;\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 isUnitrollerAdminStorage {\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 publicliquidationIncentiveMantissa;\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 */\nmapping(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 onecan borrow against their collateral in this market.\n * For instance, 0.9 to allow borrowing 90% of collateral value.\n * Must bebetween 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 receivesSTRK\n bool isStriked;\n }\n\n /**\n * @notice Official mapping of sTokens -\u003e Market metadata\n * @dev Used e.g. todetermine if a market is supported\n */\n mapping(address =\u003e Market) public markets;\n\n\n /**\n * @notice The Pause Guardiancan 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;\nmapping(address =\u003e bool) public mintGuardianPaused;\n mapping(address =\u003e bool) public borrowGuardianPaused;\n}\n\ncontractComptrollerV3Storage is ComptrollerV2Storage {\n struct StrikeMarketState {\n /// @notice The market\u0027s last updatedstrikeBorrowIndex or strikeSupplyIndex\n uint224 index;\n\n /// @notice The block number the index was last updated at\nuint32 block;\n }\n\n /// @notice A list of all markets\n SToken[] public allMarkets;\n\n /// @notice The rate at which the flywheeldistributes STRK, per block\n uint public strikeRate;\n\n /// @notice The portion of strikeRate that each market currently receives\nmapping(address =\u003e uint) public strikeSpeeds;\n\n /// @notice The STRK market supply state for each market\n mapping(address =\u003eStrikeMarketState) public strikeSupplyState;\n\n /// @notice The STRK market borrow state for each market\n mapping(address =\u003eStrikeMarketState) public strikeBorrowState;\n\n /// @notice The STRK borrow index for each market for each supplier as of the last time theyaccrued STRK\n mapping(address =\u003e mapping(address =\u003e uint)) public strikeSupplierIndex;\n\n /// @notice The STRK borrow index foreach market for each borrower as of the last time they accrued STRK\n mapping(address =\u003e mapping(address =\u003e uint)) publicstrikeBorrowerIndex;\n\n /// @notice The STRK accrued but not yet transferred to each user\n mapping(address =\u003e uint) publicstrikeAccrued;\n}\n\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\n /// @notice The portion of STRK that each constributor receivesper block\n mapping(address =\u003e uint) public strikeContributorSpeeds;\n\n /// @notice Last block at which a contributor\u0027s STRKrewards have been allocated\n mapping(address =\u003e uint) public lastContributorBlock;\n}\n\ncontract ComptrollerV5Storage isComptrollerV4Storage {\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 /// @noticeReserve 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 // @noticeThe marketCapGuardian can set marketCaps to any number for any market.\n address public marketCapGuardian;\n\n // @notice Supply capsenforced 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 unlimitedborrowing.\n mapping(address =\u003e uint) public borrowCaps;\n\n /**\n * @notice The Pause Guardian can pause protocol.\n */\nbool 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 functionsymbol() external view returns (string memory);\n function decimals() external view returns (uint8);\n\n /**\n * @notice Get the totalnumber 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 tokensto 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 thetransfer 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 maytransfer tokens\n * @param amount The number of tokens that are approved (-1 means infinite)\n * @return Whether or not the approvalsucceeded\n */\n function approve(address spender, uint256 amount) external returns (bool success);\n\n /**\n * @notice Get thecurrent allowance from `owner` for `spender`\n * @param owner The address of the account which owns the tokens to be spent\n * @paramspender 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 noreturn 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 * @returnThe supply of tokens\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @notice Gets the balance of thespecified address\n * @param owner The address from which the balance will be retrieved\n * @return The balance\n */\n functionbalanceOf(address owner) external view returns (uint256 balance);\n\n ///\n /// !!!!!!!!!!!!!!\n /// !!! NOTICE !!! `transfer` does notreturn 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 notreturn 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 * @paramamount 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 * andis subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\n * @param spender The address of the account which maytransfer tokens\n * @param amount The number of tokens that are approved\n * @return Whether or not the approval succeeded\n */\nfunction 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 theaccount 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);\nevent 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,\nINSUFFICIENT_SHORTFALL,\n INSUFFICIENT_LIQUIDITY,\n INVALID_CLOSE_FACTOR,\n INVALID_COLLATERAL_FACTOR,\nINVALID_LIQUIDATION_INCENTIVE,\n MARKET_NOT_ENTERED, // no longer possible\n MARKET_NOT_LISTED,\n MARKET_ALREADY_LISTED,\nMATH_ERROR,\n NONZERO_BORROW_BALANCE,\n PRICE_ERROR,\n REJECTION,\n SNAPSHOT_ERROR,\n TOO_MANY_ASSETS,\nTOO_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,\nSET_COLLATERAL_FACTOR_OWNER_CHECK,\n SET_COLLATERAL_FACTOR_NO_EXISTS,\n SET_COLLATERAL_FACTOR_VALIDATION,\nSET_COLLATERAL_FACTOR_WITHOUT_PRICE,\n SET_IMPLEMENTATION_OWNER_CHECK,\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\nSET_LIQUIDATION_INCENTIVE_VALIDATION,\n SET_MAX_ASSETS_OWNER_CHECK,\n SET_PENDING_ADMIN_OWNER_CHECK,\nSET_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 enumError; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\n * contract-specific code that enables us to report opaque errorcodes from upgradeable contracts.\n **/\n event Failure(uint error, uint info, uint detail);\n\n /**\n * @dev use this whenreporting a known error from the money market or a non-upgradeable collaborator\n */\n function fail(Error err, FailureInfo info) internalreturns (uint) {\n emit Failure(uint(err), uint(info), 0);\n\n return uint(err);\n }\n\n /**\n * @dev use this whenreporting an opaque error from an upgradeable collaborator contract\n */\n function failOpaque(Error err, FailureInfo info, uintopaqueError) 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,\nCOMPTROLLER_REJECTION,\n COMPTROLLER_CALCULATION_ERROR,\n INTEREST_RATE_MODEL_ERROR,\n INVALID_ACCOUNT_PAIR,\nINVALID_CLOSE_AMOUNT_REQUESTED,\n INVALID_COLLATERAL_FACTOR,\n MATH_ERROR,\n MARKET_NOT_FRESH,\n MARKET_NOT_LISTED,\nTOKEN_INSUFFICIENT_ALLOWANCE,\n TOKEN_INSUFFICIENT_BALANCE,\n TOKEN_INSUFFICIENT_CASH,\n TOKEN_TRANSFER_IN_FAILED,\nTOKEN_TRANSFER_OUT_FAILED\n }\n\n /*\n * Note: FailureInfo (but not Error) is kept in alphabetical order\n * This isbecause 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,\nACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\nACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\nACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\nBORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\n BORROW_ACCRUE_INTEREST_FAILED,\n BORROW_CASH_NOT_AVAILABLE,\nBORROW_FRESHNESS_CHECK,\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\nBORROW_MARKET_NOT_LISTED,\n BORROW_COMPTROLLER_REJECTION,\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\nLIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\n LIQUIDATE_COMPTROLLER_REJECTION,\nLIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\nLIQUIDATE_FRESHNESS_CHECK,\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\nLIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\nLIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\n LIQUIDATE_SEIZE_TOO_MUCH,\n MINT_ACCRUE_INTEREST_FAILED,\nMINT_COMPTROLLER_REJECTION,\n MINT_EXCHANGE_CALCULATION_FAILED,\n MINT_EXCHANGE_RATE_READ_FAILED,\n MINT_FRESHNESS_CHECK,\nMINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\n MINT_TRANSFER_IN_FAILED,\nMINT_TRANSFER_IN_NOT_POSSIBLE,\n REDEEM_ACCRUE_INTEREST_FAILED,\n REDEEM_COMPTROLLER_REJECTION,\nREDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\n REDEEM_EXCHANGE_RATE_READ_FAILED,\nREDEEM_FRESHNESS_CHECK,\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\nREDEEM_TRANSFER_OUT_NOT_POSSIBLE,\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\n REDUCE_RESERVES_ADMIN_CHECK,\nREDUCE_RESERVES_CASH_NOT_AVAILABLE,\n REDUCE_RESERVES_FRESH_CHECK,\n REDUCE_RESERVES_VALIDATION,\nREPAY_BEHALF_ACCRUE_INTEREST_FAILED,\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\nREPAY_BORROW_COMPTROLLER_REJECTION,\n REPAY_BORROW_FRESHNESS_CHECK,\nREPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\nREPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\n SET_COLLATERAL_FACTOR_VALIDATION,\nSET_COMPTROLLER_OWNER_CHECK,\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\nSET_INTEREST_RATE_MODEL_OWNER_CHECK,\n SET_MAX_ASSETS_OWNER_CHECK,\n SET_ORACLE_MARKET_NOT_LISTED,\nSET_PENDING_ADMIN_OWNER_CHECK,\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\n SET_RESERVE_FACTOR_ADMIN_CHECK,\nSET_RESERVE_FACTOR_FRESH_CHECK,\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\n TRANSFER_COMPTROLLER_REJECTION,\n TRANSFER_NOT_ALLOWED,\nTRANSFER_NOT_ENOUGH,\n TRANSFER_TOO_MUCH,\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\n ADD_RESERVES_FRESH_CHECK,\nADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE,\n TRANSFER_RESERVES_ACCRUE_INTEREST_FAILED,\n TRANSFER_RESERVES_ADMIN_CHECK,\nTRANSFER_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 thatenables 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, FailureInfoinfo, 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 storingfixed-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 */\ncontractExponential 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, Expmemory) {\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) internalpure 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(Expmemory 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 */\nfunction 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\nreturn (MathError.NO_ERROR, Exp({mantissa: scaledMantissa}));\n }\n\n /**\n * @dev Multiply an Exp by a scalar, then truncate to returnan 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\nreturn (MathError.NO_ERROR, truncate(product));\n }\n\n /**\n * @dev Multiply an Exp by a scalar, truncate, then add an to anunsigned integer, returning an unsigned integer.\n */\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internalpure returns (MathError, uint) {\n (MathError err, Exp memory product) = mulScalar(a, scalar);\n if (err != MathError.NO_ERROR) {\nreturn (err, 0);\n }\n\n return addUInt(truncate(product), addend);\n }\n\n /**\n * @dev Divide an Exp by ascalar, 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 ascalar by an Exp, returning a new Exp.\n */\n function divScalarByExp(uint scalar, Exp memory divisor) internal pure returns (MathError, Expmemory) {\n /*\n We are doing this as:\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\n\n How it works:\nExp = 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, thentruncate 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) {\nreturn (err, 0);\n }\n\n return (MathError.NO_ERROR, truncate(fraction));\n }\n\n /**\n * @dev Multiplies twoexponentials, 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) {\nreturn (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, Expmemory 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 twoexponentials, returning a new exponential.\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\n * which we can scale as an Expby 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 * Forexample, 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 purereturns (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 memoryright) internal pure returns (bool) {\n return left.mantissa \u003e right.mantissa;\n }\n\n /**\n * @dev returns true if Exp isexactly zero\n */\n function isZeroExp(Exp memory value) internal pure returns (bool) {\n return value.mantissa == 0;\n }\n\nfunction safe224(uint n, string memory errorMessage) internal pure returns (uint224) {\n require(n \u003c 2**224, errorMessage);\nreturn 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) {\nreturn 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 purereturns (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\nfunction 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);\nreturn 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 returnExp({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) {\nreturn 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) {\nreturn Double({mantissa: div_(a.mantissa, b)});\n }\n\n function div_(uint a, Double memory b) internal pure returns (uint) {\nreturn 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) {\nreturn 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 anInterestRateModel contract (for inspection)\n bool public constant isInterestRateModel = true;\n\n /**\n * @notice Calculates thecurrent borrow interest rate per block\n * @param cash The total amount of cash the market has\n * @param borrows The total amount ofborrows 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, andscaled 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\nfunction 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 functiongetUnderlyingPrice(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 overSolidity\u0027s arithmetic operations with added overflow\n * checks.\n *\n * Arithmetic operations in Solidity wrap on overflow. This can easilyresult\n * in bugs, because programmers usually assume that an overflow raises an\n * error, which is the standard behavior in high levelprogramming languages.\n * `SafeMath` restores this intuition by reverting the transaction when an\n * operation overflows.\n *\n * Using thislibrary instead of the unchecked operations eliminates an entire\n * class of bugs, so it\u0027s recommended to use it always.\n */\nlibrarySafeMath {\n /**\n * @dev Returns the addition of two unsigned integers, reverting on overflow.\n *\n * Counterpart toSolidity\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 isnegative).\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 */\nfunction sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b \u003c= a, errorMessage);\nuint256 c = a - b;\n\n return c;\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, reverting onoverflow.\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 cannotoverflow.\n */\n function mul(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n // Gasoptimization: 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\nuint256 c = a * b;\n require(c / a == b, errorMessage);\n\n return c;\n }\n\n /**\n * @dev Returns the integer division oftwo 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 opcodeto 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 theinteger 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) whileSolidity\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 onlyautomatically 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 twounsigned 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 ofdividing two unsigned integers. (unsigned integer modulo),\n * Reverts with custom message when dividing by zero.\n *\n * Counterpartto 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 functionmod(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 * @noticeInitialize the new money market\n * @param underlying_ The address of the underlying asset\n * @param comptroller_ The address of theComptroller\n * @param interestRateModel_ The address of the interest rate model\n * @param initialExchangeRateMantissa_ The initialexchange rate, scaled by 1e18\n * @param name_ ERC-20 name of this token\n * @param symbol_ ERC-20 symbol of this token\n * @paramdecimals_ ERC-20 decimal precision of this token\n */\n function initialize(address underlying_,\nComptrollerInterface comptroller_,\n InterestRateModel interestRateModel_,\n uintinitialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\nuint8 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_;\nEIP20Interface(underlying).totalSupply();\n }\n\n /*** User Interface ***/\n\n /**\n * @notice Sender supplies assets into themarket and receives sTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @parammintAmount 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 operationsucceeds, unless reverted\n * @param redeemTokens The number of sTokens to redeem into underlying\n * @return uint 0=success, otherwise afailure (see ErrorReporter.sol for details)\n */\n function redeem(uint redeemTokens) external returns (uint) {\n returnredeemInternal(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 theprotocol to their own address\n * @param borrowAmount The amount of the underlying asset to borrow\n * @return uint 0=success, otherwisea failure (see ErrorReporter.sol for details)\n */\n function borrow(uint borrowAmount) external returns (uint) {\n returnborrowInternal(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) externalreturns (uint) {\n (uint err,) = repayBorrowInternal(repayAmount);\n return err;\n }\n\n /**\n * @notice Sender repays aborrow 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, uintrepayAmount) 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 * @paramborrower 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 (seeErrorReporter.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 uint0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _addReserves(uint addAmount) external returns (uint) {\nreturn _addReservesInternal(addAmount);\n }\n\n /*** Safe Token ***/\n\n /**\n * @notice Gets balance of this contract in termsof the underlying\n * @dev This excludes the value of the current message, if any\n * @return The quantity of underlying tokens owned bythis contract\n */\n function getCashPrior() internal view returns (uint) {\n EIP20Interface token = EIP20Interface(underlying);\nreturn 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 * Thisfunction 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;\nassembly {\n switch returndatasize()\n case 0 { // This is a non-standard ERC-20\nsuccess := 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.\nrevert(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 cashheld in this contract. If caller has checked protocol\u0027s balance prior to this call, and verified\n * it is \u003e= amount, thisshould not revert in normal conditions.\n *\n * Note: This wrapper safely handles non-standard ERC-20 tokens that do not return avalue.\n * See here: https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\n */\nfunction 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 }\ncase 32 { // This is a complaint ERC-20\n returndatacopy(0, 0, 32)\nsuccess := mload(0) // Set `success = returndata` of external call\n }\n default { // Thisis 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 anyinitialization\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\nrequire(msg.sender == admin, \"only the admin may call _becomeImplementation\");\n }\n\n /**\n * @notice Called by the delegator on adelegate to forfeit its responsibility\n */\n function _resignImplementation() public {\n // Shh -- we don\u0027t ever want this hookto be marked pure\n if (false) {\n implementation = address(0);\n }\n\n require(msg.sender == admin, \"only theadmin 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 animplementation\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 theComptroller\n * @param interestRateModel_ The address of the interest rate model\n * @param initialExchangeRateMantissa_ The initialexchange rate, scaled by 1e18\n * @param name_ ERC-20 name of this token\n * @param symbol_ ERC-20 symbol of this token\n * @paramdecimals_ 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_,\nuint8 decimals_,\n address payable admin_,\n address implementation_,\n bytes memorybecomeImplementationData) 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_,\ncomptroller_,\n interestRateModel_,\ninitialExchangeRateMantissa_,\nname_,\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 fordelegation\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\n * @parambecomeImplementationData The encoded bytes data to be passed to _becomeImplementation\n */\n function _setImplementation(addressimplementation_, 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\ndelegateToImplementation(abi.encodeWithSignature(\"_becomeImplementation(bytes)\", becomeImplementationData));\n\n emitNewImplementation(oldImplementation, implementation);\n }\n\n /**\n * @notice Sender supplies assets into the market and receives sTokensin exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param mintAmount The amount of theunderlying asset to supply\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function mint(uintmintAmount) 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 intounderlying\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));\nreturn abi.decode(data, (uint));\n }\n\n /**\n * @notice Sender redeems sTokens in exchange for a specified amount of underlyingasset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemAmount The amount of underlying toredeem\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function redeemUnderlying(uintredeemAmount) 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 ownaddress\n * @param borrowAmount The amount of the underlying asset to borrow\n * @return uint 0=success, otherwise a failure (seeErrorReporter.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 * @paramrepayAmount The amount to repay\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n functionrepayBorrowBehalf(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 * @paramborrower 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 * @returnWhether or not the transfer succeeded\n */\n function transfer(address dst, uint amount) external returns (bool) {\n bytes memorydata = 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 dstThe address of the destination account\n * @param amount The number of tokens to transfer\n * @return Whether or not the transfersucceeded\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 approvalamount for `spender`\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\n * @param spender Theaddress of the account which may transfer tokens\n * @param amount The number of tokens that are approved (-1 means infinite)\n * @returnWhether or not the approval succeeded\n */\n function approve(address spender, uint256 amount) external returns (bool) {\n bytesmemory 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 accountwhich owns the tokens to be spent\n * @param spender The address of the account which may transfer tokens\n * @return The number of tokensallowed to be spent (-1 means infinite)\n */\n function allowance(address owner, address spender) external view returns (uint) {\nbytes 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 toquery\n * @return The number of tokens owned by `owner`\n */\n function balanceOf(address owner) external view returns (uint) {\nbytes 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 functionbalanceOfUnderlying(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 theaccount\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 interestrate 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 currenttotal 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 theupdated borrowIndex\n * @param account The address whose balance should be calculated after updating borrowIndex\n * @return The calculatedbalance\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 becalculated\n * @return The calculated balance\n */\n function borrowBalanceStored(address account) public view returns (uint) {\nbytes 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 ratescaled 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 theexchange 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 andreserves.\n * @dev This calculates interest accrued from the last checkpointed block\n * up to the current block and writes newcheckpoint 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 collateraltokens (this market) to the liquidator.\n * @dev Will fail unless called by another sToken during the process of liquidation.\n * Itsabsolutely critical to use msg.sender as the borrowed sToken and not a parameter.\n * @param liquidator The account receiving seizedcollateral\n * @param borrower The account having collateral seized\n * @param seizeTokens The number of sTokens to seize\n * @returnuint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function seize(address liquidator, address borrower, uintseizeTokens) 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 functionto 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 payablenewPendingAdmin) 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 */\nfunction _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 * @noticeaccrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh\n * @dev Admin function to accrue interest andset 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 andupdate 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 addAmountAmount 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 bytransferring to admin\n * @param reduceAmount Amount of reduction to reserves\n * @return uint 0=success, otherwise a failure (seeErrorReporter.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 toreserves\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _transferReserves(uintreduceAmount) 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 ratemodel using _setInterestRateModelFresh\n * @dev Admin function to accrue interest and update the interest rate model\n * @paramnewInterestRateModel 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 callerwhatever the implementation returns or forwards reverts\n * @param callee The contract to delegatecall\n * @param data The raw data todelegatecall\n * @return The returned bytes from the delegatecall\n */\n function delegateTo(address callee, bytes memory data) internalreturns (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 implementationreturns or forwards reverts\n * @param data The raw data to delegatecall\n * @return The returned bytes from the delegatecall\n */\nfunction 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 implementationreturns 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 functiondelegateToViewImplementation(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) {\nrevert(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 implementationreturns or forwards reverts\n */\n function () external payable {\n require(msg.value == 0,\"SErc20Delegator:fallback: cannot sendvalue 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\nswitch 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 * @authorStrike\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 * @paraminitialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\n * @param name_ EIP-20 name of this token\n * @param symbol_ EIP-20symbol of this token\n * @param decimals_ EIP-20 decimal precision of this token\n */\n function initialize(ComptrollerInterfacecomptroller_,\n InterestRateModel interestRateModel_,\n uint initialExchangeRateMantissa_,\nstring memory name_,\n string memory symbol_,\n uint8 decimals_) public {\nrequire(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 comptrollerfailed\");\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)\nerr = _setInterestRateModelFresh(interestRateModel_);\n require(err == uint(Error.NO_ERROR), \"setting interest rate model failed\");\n\nname = name_;\n symbol = symbol_;\n decimals = decimals_;\n\n // The counter starts true to prevent changing it fromzero 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 accountperforming 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(addressspender, 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, infinitefor 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 beyondthis point)\n\n accountTokens[src] = srsTokensNew;\n accountTokens[dst] = dstTokensNew;\n\n /* Eat some of the allowance (ifnecessary) */\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\nreturn uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\n * @param dst Theaddress 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 srcThe address of the source account\n * @param dst The address of the destination account\n * @param amount The number of tokens totransfer\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 * andis subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\n * @param spender The address of the account which maytransfer tokens\n * @param amount The number of tokens that are approved (-1 means infinite)\n * @return Whether or not the approvalsucceeded\n */\n function approve(address spender, uint256 amount) external returns (bool) {\n address src = msg.sender;\ntransferAllowances[src][spender] = amount;\n emit Approval(src, spender, amount);\n return true;\n }\n\n /**\n * @noticeGet 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 * @returnThe number of tokens owned by `owner`\n */\n function balanceOf(address owner) external view returns (uint256) {\n returnaccountTokens[owner];\n }\n\n /**\n * @notice Get the underlying balance of the `owner`\n * @dev This also accrues interest in atransaction\n * @param owner The address of the account to query\n * @return The amount of underlying owned by `owner`\n */\nfunction 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, andthe cached exchange rate\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\n * @param account Address ofthe account to snapshot\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\n */\n functiongetAccountSnapshot(address account) external view returns (uint, uint, uint, uint) {\n uint sTokenBalance = accountTokens[account];\nuint 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 * @devFunction to simply retrieve block number\n * This exists mainly for inheriting test contracts to stub this result.\n */\n functiongetBlockNumber() internal view returns (uint) {\n return block.number;\n }\n\n /**\n * @notice Returns the current per-blockborrow 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 Accrueinterest to updated borrowIndex and then calculate account\u0027s borrow balance using the updated borrowIndex\n * @param account The addresswhose 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\");\nreturn 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 * @noticeReturn 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) internalview returns (MathError, uint) {\n /* Note: we do not assert that the market is up to date */\n MathError mathErr;\n uintprincipalTimesIndex;\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 witha 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\nreturn (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 * @noticeCalculates the exchange rate from the underlying to the SToken\n * @dev This function does not accrue interest before calculating the exchangerate\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 tothe SToken\n * @dev This function does not accrue interest before calculating the exchange rate\n * @return (error code, calculatedexchange 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 */\nuint totalCash = getCashPrior();\n uint cashPlusBorrowsMinusReserves;\n Exp memory exchangeRate;\nMathError 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 sTokenin the underlying asset\n * @return The quantity of underlying asset owned by this contract\n */\n function getCash() external viewreturns (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 outof storage */\n uint cashPrior = getCashPrior();\n uint borrowsPrior = totalBorrows;\n uint reservesPrior = totalReserves;\nuint 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, uintblockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\n require(mathErr == MathError.NO_ERROR, \"could not calculate blockdelta\");\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 uintinterestAccumulated;\n uint totalBorrowsNew;\n uint totalReservesNew;\n uint borrowIndexNew;\n\n (mathErr,simpleInterestFactor) = mulScalar(Exp({mantissa: borrowRateMantissa}), blockDelta);\n if (mathErr != MathError.NO_ERROR) {\nreturn 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) {\nreturn 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 returnfailOpaque(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);\nif (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 \u0026INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We write the previously calculated values into storage */\naccrualBlockNumber = 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 receivessTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param mintAmount The amount ofthe underlying asset to supply\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actualmint 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 anattempted borrow failed\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\n }\n // mintFreshemits 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;\nuint totalSupplyNew;\n uint accountTokensNew;\n uint actualMintAmount;\n }\n\n /**\n * @notice User supplies assetsinto the market and receives sTokens in exchange\n * @dev Assumes interest has already been accrued up to the current block\n * @paramminter 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 functionmintFresh(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 equalscurrent 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 wecan\u0027t be sure if\n * side-effects occurred. The function returns the amount actually transferred,\n * in case of a fee. Onsuccess, 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 previouslycalculated 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 Senderredeems 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 fordetails)\n */\n function redeemInternal(uint redeemTokens) internal nonReentrant returns (uint) {\n uint error = accrueInterest();\nif (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but we still want to log the fact that anattempted redeem failed\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\n }\n // redeemFresh emitsredeem-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 operationsucceeds, 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 nonReentrantreturns (uint) {\n uint error = accrueInterest();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs onerrors, 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 returnredeemFresh(msg.sender, 0, redeemAmount);\n }\n\n struct RedeemLocalVars {\n Error err;\n MathError mathErr;\n uintexchangeRateMantissa;\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 tothe current block\n * @param redeemer The address of the account which is redeeming the tokens\n * @param redeemTokensIn The number ofsTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\n * @param redeemAmountIn The number ofunderlying 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, uintredeemAmountIn) internal returns (uint) {\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \"one of redeemTokensIn or redeemAmountInmust 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 thecurrent 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 hasinsufficient 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 safefailures beyond this point)\n\n /*\n * We invoke doTransferOut for the redeemer and the redeemAmount.\n * Note: The sTokenmust 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;\naccountTokens[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 theunderlying asset to borrow\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n functionborrowInternal(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\nreturn fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\n }\n // borrowFresh emits borrow-specific logs on errors, sowe don\u0027t need to\n return borrowFresh(msg.sender, borrowAmount);\n }\n\n struct BorrowLocalVars {\n MathError mathErr;\nuint accountBorrows;\n uint accountBorrowsNew;\n uint totalBorrowsNew;\n }\n\n /**\n * @notice Users borrow assetsfrom 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) internalreturns (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()) {\nreturn fail(Error.MARKET_NOT_FRESH, FailureInfo.BORROW_FRESHNESS_CHECK);\n }\n\n /* Fail gracefully if protocol hasinsufficient 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 borrowerand 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 variationsbetween ERC-20 and ETH underlying.\n * On success, the sToken borrowAmount less of cash.\n * doTransferOut reverts if anythinggoes wrong, since we can\u0027t be sure if side effects occurred.\n */\n doTransferOut(borrower, borrowAmount);\n\n /* Wewrite the previously calculated values into storage */\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\naccountBorrows[borrower].interestIndex = borrowIndex;\n totalBorrows = vars.totalBorrowsNew;\n\n /* We emit a Borrow event */\nemit 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 theirown borrow\n * @param repayAmount The amount to repay\n * @return (uint, uint) An error code (0=success, otherwise a failure, seeErrorReporter.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 onerrors, 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\u0027tneed to\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\n }\n\n /**\n * @notice Sender repays a borrow belongingto 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 functionrepayBorrowBehalfInternal(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 anattempted 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 uintborrowerIndex;\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 functionrepayBorrowFresh(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) {\nreturn (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed), 0);\n }\n\n /* Verifymarket\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 rememberthe original borrowerIndex for verification purposes */\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\n\n /* Wefetch 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 failuresbeyond this point)\n\n /*\n * We call doTransferIn for the payer and the repayAmount\n * Note: The sToken must handlevariations 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 actuallytransferred, in case of a fee.\n */\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\n\n /*\n * Wecalculate 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 /* Wewrite the previously calculated values into storage */\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\naccountBorrows[borrower].interestIndex = borrowIndex;\n totalBorrows = vars.totalBorrowsNew;\n\n /* We emit a RepayBorrow event */\nemit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\n\n /* We call the defensehook */\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 * Thecollateral seized is transferred to the liquidator.\n * @param borrower The borrower of this sToken to be liquidated\n * @paramsTokenCollateral The market in which to seize collateral from the borrower\n * @param repayAmount The amount of the underlying borrowed assetto 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\nreturn (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\n }\n\n // liquidateBorrowFresh emitsborrow-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 theliquidator.\n * @param borrower The borrower of this sToken to be liquidated\n * @param liquidator The address repaying the borrow andseizing collateral\n * @param sTokenCollateral The market in which to seize collateral from the borrower\n * @param repayAmount The amountof the underlying borrowed asset to repay\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), andthe actual repayment amount.\n */\n function liquidateBorrowFresh(address liquidator, address borrower, uint repayAmount, STokenInterfacesTokenCollateral) 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) {\nreturn (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\n }\n\n /* Verifymarket\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 equalscurrent 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)) {\nreturn (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\n }\n\n\n /* Fail ifrepayBorrow 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 thecollateral, 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 {\nseizeError = sTokenCollateral.seize(liquidator, borrower, seizeTokens);\n }\n\n /* Revert if seize tokens fails (since we cannot besure of side effects) */\n require(seizeError == uint(Error.NO_ERROR), \"token seizure failed\");\n\n /* We emit a LiquidateBorrowevent */\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(sTokenCollateral), seizeTokens);\n\n /* We call thedefense 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 (thismarket) to the liquidator.\n * @dev Will fail unless called by another sToken during the process of liquidation.\n * Its absolutelycritical 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 structSeizeInternalLocalVars {\n MathError mathErr;\n uint borrowerTokensNew;\n uint liquidatorTokensNew;\n uintliquidatorSeizeTokens;\n uint protocolSeizeTokens;\n uint protocolSeizeAmount;\n uint exchangeRateMantissa;\n uinttotalReservesNew;\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 absolutelycritical to use msg.sender as the seizer sToken and not a parameter.\n * @param seizerToken The contract seizing the collateral (i.e. borrowedsToken)\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);\nif (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 liquidatortoken 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 matherror\");\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) {\nreturn 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 thepreviously calculated values into storage */\n totalReserves = vars.totalReservesNew;\n totalSupply = vars.totalSupplyNew;\naccountTokens[borrower] = vars.borrowerTokensNew;\n accountTokens[liquidator] = vars.liquidatorTokensNew;\n\n /* Emit a Transferevent */\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 thedefense 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` tofinalize 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 withvalue newPendingAdmin\n pendingAdmin = newPendingAdmin;\n\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\n emitNewPendingAdmin(oldPendingAdmin, newPendingAdmin);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Accepts transfer ofadmin rights. msg.sender must be pendingAdmin\n * @dev Admin function for pending admin to accept role and update admin\n * @return uint0=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)) {\nreturn fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\n }\n\n // Save current values for inclusion in log\naddress 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 emitNewPendingAdmin(oldPendingAdmin, pendingAdmin);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Sets a new comptrollerfor the market\n * @dev Admin function to set a new comptroller\n * @return uint 0=success, otherwise a failure (see ErrorReporter.solfor details)\n */\n function _setComptroller(ComptrollerInterface newComptroller) public returns (uint) {\n // Check caller isadmin\n if (msg.sender != admin) {\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_COMPTROLLER_OWNER_CHECK);\n }\n\nComptrollerInterface 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\ncomptroller = 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 theprotocol 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) externalnonReentrant returns (uint) {\n uint error = accrueInterest();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterestemits 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 logson errors, so we don\u0027t need to.\n return _setReserveFactorFresh(newReserveFactorMantissa);\n }\n\n /**\n * @notice Sets anew reserve factor for the protocol (*requires fresh interest accrual)\n * @dev Admin function to set a new reserve factor\n * @returnuint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setReserveFactorFresh(uintnewReserveFactorMantissa) 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 blocknumber\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 \u003ereserveFactorMaxMantissa) {\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\n }\n\n uintoldReserveFactorMantissa = reserveFactorMantissa;\n reserveFactorMantissa = newReserveFactorMantissa;\n\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Accrues interestand 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\u0027tneed to.\n (error, ) = _addReservesFresh(addAmount);\n return error;\n }\n\n /**\n * @notice Add reserves by transferringfrom caller\n * @dev Requires fresh interest accrual\n * @param addAmount Amount of addition to reserves\n * @return (uint, uint) Anerror 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;\nuint 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 andETH 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\nactualAddAmount = doTransferIn(msg.sender, addAmount);\n\n totalReservesNew = totalReserves + actualAddAmount;\n\n /* Reverton 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]) */\nemit 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 attemptedreduce 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 * @paramreduceAmount Amount of reduction to reserves\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\nfunction _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\nif (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 returnfail(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\ntotalReservesNew = 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 wecan\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 transferringto reserve\n * @param reduceAmount Amount of reduction to reserves\n * @return uint 0=success, otherwise a failure (see ErrorReporter.solfor 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 tolog 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 reduceAmountAmount 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()) {\nreturn fail(Error.MARKET_NOT_FRESH, FailureInfo.TRANSFER_RESERVES_FRESH_CHECK);\n }\n\n // Fail gracefully if protocol hasinsufficient 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 \u003etotalReserves) {\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 ifside effects occurred.\n doTransferOut(IComptroller(address(comptroller)).reserveAddress(), reduceAmount);\n\n emit TransferReserves(IComptroller(address(comptroller)).reserveGuardian(), IComptroller(address(comptroller)).reserveAddress(), reduceAmount, totalReservesNew);\n\nreturn 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 newInterestRateModelthe 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 ofinterest 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 interestaccrual)\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 onsuccess\n InterestRateModel oldInterestRateModel;\n\n // Check caller is admin\n if (msg.sender != admin) {\nreturn fail(Error.UNAUTHORIZED, FailureInfo.SET_INTEREST_RATE_MODEL_OWNER_CHECK);\n }\n\n // We fail gracefully unless market\u0027sblock 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\noldInterestRateModel = 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\ninterestRateModel = newInterestRateModel;\n\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\nemit 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 currentmessage, 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 afee.\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 thanreverting.\n * If caller has not called checked protocol\u0027s balance, may revert due to insufficient cash held in the contract.\n * Ifcaller has checked protocol\u0027s balance, and verified it is \u003e= amount, this should not revert in normal conditions.\n */\n functiondoTransferOut(address payable to, uint amount) internal;\n\n\n /*** Reentrancy Guard ***/\n\n /**\n * @dev Prevents a contract fromcalling 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":"pragmasolidity ^0.5.16;\n\nimport \"./ComptrollerInterface.sol\";\nimport \"./InterestRateModel.sol\";\n\ncontract STokenStorage {\n /**\n * @devGuard 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 beapplied (.0005% / block)\n */\n\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\n\n /**\n * @notice Maximum fraction ofinterest that can be set aside for reserves\n */\n uint internal constant reserveFactorMaxMantissa = 1e18;\n\n /**\n * @noticeAdministrator 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 */\nComptrollerInterface public comptroller;\n\n /**\n * @notice Model which tells what the current interest rate should be\n */\nInterestRateModel public interestRateModel;\n\n /**\n * @notice Initial exchange rate used when minting the first STokens (used whentotalSupply = 0)\n */\n uint internal initialExchangeRateMantissa;\n\n /**\n * @notice Fraction of interest currently set aside forreserves\n */\n uint public reserveFactorMantissa;\n\n /**\n * @notice Block number that interest was last accrued at\n */\nuint public accrualBlockNumber;\n\n /**\n * @notice Accumulator of the total earned interest rate since the opening of the market\n */\nuint public borrowIndex;\n\n /**\n * @notice Total amount of outstanding borrows of the underlying in this market\n */\n uintpublic totalBorrows;\n\n /**\n * @notice Total amount of reserves of the underlying held in this market\n */\n uint publictotalReserves;\n\n /**\n * @notice Total number of tokens in circulation\n */\n uint public totalSupply;\n\n /**\n * @noticeOfficial record of token balances for each account\n */\n mapping (address =\u003e uint) internal accountTokens;\n\n /**\n * @noticeApproved token transfer amounts on behalf of others\n */\n mapping (address =\u003e mapping (address =\u003e uint)) internaltransferAllowances;\n\n /**\n * @notice Container for borrow balance information\n * @member principal Total balance (with accruedinterest), 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 * @noticeMapping 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 Eventemitted when tokens are minted\n */\n event Mint(address minter, uint mintAmount, uint mintTokens);\n\n /**\n * @notice Event emittedwhen tokens are redeemed\n */\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens);\n\n /**\n * @notice Eventemitted 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, uintaccountBorrows, 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(ComptrollerInterfaceoldComptroller, ComptrollerInterface newComptroller);\n\n /**\n * @notice Event emitted when interestRateModel is changed\n */\nevent NewMarketInterestRateModel(InterestRateModel oldInterestRateModel, InterestRateModel newInterestRateModel);\n\n /**\n * @notice Eventemitted 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, uintnewTotalReserves);\n\n /**\n * @notice Event emitted when the reserves are reduced\n */\n event ReservesReduced(address admin, uintreduceAmount, uint newTotalReserves);\n\n /**\n * @notice Event emitted when the reserves are transfered\n */\n eventTransferReserves(address guardian, address reserveAddress, uint reduceAmount, uint newTotalReserves);\n\n /**\n * @notice EIP20 Transferevent\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 eventFailure(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, uintamount) 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 functiongetAccountSnapshot(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 functionborrowBalanceCurrent(address account) external returns (uint);\n function borrowBalanceStored(address account) public view returns (uint);\nfunction 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, uintseizeTokens) external returns (uint);\n\n\n /*** Admin Functions ***/\n\n function _setPendingAdmin(address payable newPendingAdmin) externalreturns (uint);\n function _acceptAdmin() external returns (uint);\n function _setComptroller(ComptrollerInterface newComptroller) publicreturns (uint);\n function _setReserveFactor(uint newReserveFactorMantissa) external returns (uint);\n function _reduceReserves(uintreduceAmount) 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\ncontractSErc20Interface is SErc20Storage {\n\n /*** User Interface ***/\n\n function mint(uint mintAmount) external returns (uint);\n functionredeem(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, STokenInterfacesTokenCollateral) 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 publicimplementation;\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 theimplementation of the delegator\n * @param implementation_ The address of the new implementation for delegation\n * @param allowResign Flagto indicate whether to call _resignImplementation on the old implementation\n * @param becomeImplementationData The encoded bytes data to bepassed to _becomeImplementation\n */\n function _setImplementation(address implementation_, bool allowResign, bytes memorybecomeImplementationData) public;\n}\n\ncontract SDelegateInterface is SDelegationStorage {\n /**\n * @notice Called by the delegator on adelegate to initialize it for duty\n * @dev Should revert if any issues arise which make it unfit for delegation\n * @param data Theencoded bytes data for any initialization\n */\n function _becomeImplementation(bytes memory data) public;\n\n /**\n * @notice Calledby 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 stringpublic 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 incirculation\n uint public constant totalSupply = 6518828e18; // 6518828 STRK\n\n /// @notice Allowance amounts on behalf of others\nmapping (address =\u003e mapping (address =\u003e uint96)) internal allowances;\n\n /// @notice Official record of token balances for eachaccount\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 {\nuint32 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 constantDOMAIN_TYPEHASH = keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n /// @notice The EIP-712 typehash forthe delegation struct used by the contract\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\"Delegation(address delegatee,uint256nonce,uint256 expiry)\");\n\n /// @notice A record of states for signing / validating signatures\n mapping (address =\u003e uint) publicnonces;\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 balancechanges\n event DelegateVotesChanged(address indexed delegate, uint previousBalance, uint newBalance);\n\n /// @notice The standard EIP-20transfer event\n event Transfer(address indexed from, address indexed to, uint256 amount);\n\n /// @notice The standard EIP-20 approvalevent\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 addressof 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 numberof tokens that are approved (2^256-1 means infinite)\n * @return Whether or not the approval succeeded\n */\n function approve(addressspender, 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 thenumber of tokens held by the `account`\n * @param account The address of the account to get the balance of\n * @return The number of tokensheld\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 Thenumber 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 Theaddress 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)) {\nuint96 newAllowance = sub96(spenderAllowance, amount, \"Strk::transferFrom: transfer amount exceeds spender allowance\");\nallowances[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 Theaddress 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 * @paramnonce The contract state required to match the signature\n * @param expiry The time at which to expire the signature\n * @param v Therecovery byte of the signature\n * @param r Half of the ECDSA signature pair\n * @param s Half of the ECDSA signature pair\n */\nfunction 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 votesbalance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\nfunction getCurrentVotes(address account) external view returns (uint96) {\n uint32 nCheckpoints = numCheckpoints[account];\nreturn nCheckpoints \u003e 0 ? checkpoints[account][nCheckpoints - 1].votes : 0;\n }\n\n /**\n * @notice Determine the prior number ofvotes for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to preventmisinformation.\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 uint32nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recentbalance\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) {\nreturn 0;\n }\n\n uint32 lower = 0;\n uint32 upper = nCheckpoints - 1;\n while (upper \u003e lower) {\nuint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\nif (cp.fromBlock == blockNumber) {\n return cp.votes;\n } else if (cp.fromBlock \u003c blockNumber) {\nlower = 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 zeroaddress\");\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];\nuint96 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\nfunction _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\u0026checkpoints[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\nfunction 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) {\nuint256 chainId;\n assembly { chainId := chainid() }\n return chainId;\n }\n}\n"},"Timelock.sol":{"content":"pragmasolidity ^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(bytes32indexed 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 indexedtarget, uint value, string signature, bytes data, uint eta);\n\n uint public constant GRACE_PERIOD = 14 days;\n uint public constantMINIMUM_DELAY = 2 days;\n uint public constant MAXIMUM_DELAY = 30 days;\n\n address public admin;\n address public pendingAdmin;\n uintpublic delay;\n\n mapping (bytes32 =\u003e bool) public queuedTransactions;\n\n\n constructor(address admin_, uint delay_) public {\nrequire(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 mustcome 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 frompendingAdmin.\");\n admin = msg.sender;\n pendingAdmin = address(0);\n\n emit NewAdmin(admin);\n }\n\n functionsetPendingAdmin(address pendingAdmin_) public {\n require(msg.sender == address(this), \"Timelock::setPendingAdmin: Call must come fromTimelock.\");\n pendingAdmin = pendingAdmin_;\n\n emit NewPendingAdmin(pendingAdmin);\n }\n\n function queueTransaction(addresstarget, 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);\nreturn 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\nbytes32 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":"pragmasolidity ^0.5.16;\n\nimport \"./ErrorReporter.sol\";\nimport \"./ComptrollerStorage.sol\";\n/**\n * @title ComptrollerCore\n * @dev Storage for thecomptroller is at this address, while execution is delegated to the `comptrollerImplementation`.\n * STokens should reference this contract astheir comptroller.\n */\ncontract Unitroller is UnitrollerAdminStorage, ComptrollerErrorReporter {\n\n /**\n * @notice Emitted whenpendingComptrollerImplementation is changed\n */\n event NewPendingImplementation(address oldPendingImplementation, addressnewPendingImplementation);\n\n /**\n * @notice Emitted when pendingComptrollerImplementation is accepted, which means comptrollerimplementation is updated\n */\n event NewImplementation(address oldImplementation, address newImplementation);\n\n /**\n * @noticeEmitted 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\nconstructor() 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 newimplementation of comptroller. msg.sender must be pendingImplementation\n * @dev Admin function for new implementation to accept it\u0027s roleas 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)\nif (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 addressoldImplementation = comptrollerImplementation;\n address oldPendingImplementation = pendingComptrollerImplementation;\n\ncomptrollerImplementation = pendingComptrollerImplementation;\n\n pendingComptrollerImplementation = address(0);\n\n emitNewImplementation(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 newPendingAdminmust call `_acceptAdmin` to finalize the transfer.\n * @param newPendingAdmin New pending admin.\n * @return uint 0=success, otherwise afailure (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 // StorependingAdmin 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 andupdate admin\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _acceptAdmin() publicreturns (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 currentvalues for inclusion in log\n address oldAdmin = admin;\n address oldPendingAdmin = pendingAdmin;\n\n // Store admin withvalue pendingAdmin\n admin = pendingAdmin;\n\n // Clear the pending value\n pendingAdmin = address(0);\n\n emitNewAdmin(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)\nreturndatacopy(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"}}
File 8 of 14: StrikeAggregatorPriceOracleV2
12345678910111213141516pragma 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);
File 9 of 14: EACAggregatorProxy
12345678910111213141516/***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;
File 10 of 14: AccessControlledOCR2Aggregator
12345678910111213141516// SPDX-License-Identifier: MITpragma 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
File 11 of 14: SErc20Delegator
1{"ComptrollerInterface.sol":{"content":"pragma solidity ^0.5.16;\n\ncontract ComptrollerInterface {\n /// @notice Indicator that this is aComptroller contract (for inspection)\n bool public constant isComptroller = true;\n\n /*** Assets You Are In ***/\n\n functionenterMarkets(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 functionmintVerify(address sToken, address minter, uint mintAmount, uint mintTokens) external;\n\n function redeemAllowed(address sToken, addressredeemer, uint redeemTokens) external returns (uint);\n function redeemVerify(address sToken, address redeemer, uint redeemAmount, uintredeemTokens) external;\n\n function borrowAllowed(address sToken, address borrower, uint borrowAmount) external returns (uint);\n functionborrowVerify(address sToken, address borrower, uint borrowAmount) external;\n\n function repayBorrowAllowed(\n address sToken,\naddress payer,\n address borrower,\n uint repayAmount) external returns (uint);\n function repayBorrowVerify(\n addresssToken,\n address payer,\n address borrower,\n uint repayAmount,\n uint borrowerIndex) external;\n\n functionliquidateBorrowAllowed(\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 addresssTokenCollateral,\n address liquidator,\n address borrower,\n uint repayAmount,\n uint seizeTokens) external;\n\nfunction 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, uinttransferTokens) external;\n\n /*** Liquidity/Liquidation Calculations ***/\n\n function liquidateCalculateSeizeTokens(\n addresssTokenBorrowed,\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 */\ncontractInterestRateModel {\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\n bool public constantisInterestRateModel = true;\n\n /**\n * @notice Calculates the current borrow interest rate per block\n * @param cash The total amountof cash the market has\n * @param borrows The total amount of borrows the market has outstanding\n * @param reserves The total amount ofreserves the market has\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\n */\n function getBorrowRate(uintcash, uint borrows, uint reserves) external view returns (uint);\n\n /**\n * @notice Calculates the current supply interest rate perblock\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 markethas\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-20underlying 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 * @paraminitialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\n * @param name_ ERC-20 name of this token\n * @param symbol_ ERC-20symbol of this token\n * @param decimals_ ERC-20 decimal precision of this token\n * @param admin_ Address of the administrator of thistoken\n * @param implementation_ The address of the implementation the contract delegates to\n * @param becomeImplementationData Theencoded args for becomeImplementation\n */\n constructor(address underlying_,\n ComptrollerInterface comptroller_,\nInterestRateModel interestRateModel_,\n uint initialExchangeRateMantissa_,\n string memory name_,\nstring memory symbol_,\n uint8 decimals_,\n address payable admin_,\n address implementation_,\nbytes 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)\",\nunderlying_,\n comptroller_,\ninterestRateModel_,\n initialExchangeRateMantissa_,\nname_,\n symbol_,\ndecimals_));\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 thenew 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(addressimplementation_, 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\ndelegateToImplementation(abi.encodeWithSignature(\"_becomeImplementation(bytes)\", becomeImplementationData));\n\n emitNewImplementation(oldImplementation, implementation);\n }\n\n /**\n * @notice Sender supplies assets into the market and receives sTokensin exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param mintAmount The amount of theunderlying asset to supply\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function mint(uintmintAmount) external returns (uint) {\n mintAmount; // Shh\n delegateAndReturn();\n }\n\n /**\n * @notice Sender redeemssTokens in exchange for the underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @paramredeemTokens 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 notthe operation succeeds, unless reverted\n * @param redeemAmount The amount of underlying to redeem\n * @return uint 0=success, otherwise afailure (see ErrorReporter.sol for details)\n */\n function redeemUnderlying(uint redeemAmount) external returns (uint) {\nredeemAmount; // Shh\n delegateAndReturn();\n }\n\n /**\n * @notice Sender borrows assets from the protocol to their ownaddress\n * @param borrowAmount The amount of the underlying asset to borrow\n * @return uint 0=success, otherwise a failure (seeErrorReporter.sol for details)\n */\n function borrow(uint borrowAmount) external returns (uint) {\n borrowAmount; // Shh\ndelegateAndReturn();\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) externalreturns (uint) {\n repayAmount; // Shh\n delegateAndReturn();\n }\n\n /**\n * @notice Sender repays a borrow belonging toborrower\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 senderliquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param borrower The borrower of thissToken to be liquidated\n * @param sTokenCollateral The market in which to seize collateral from the borrower\n * @param repayAmount Theamount of the underlying borrowed asset to repay\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\nfunction 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 ornot the transfer succeeded\n */\n function transfer(address dst, uint amount) external returns (bool) {\n dst; amount; // Shh\ndelegateAndReturn();\n }\n\n /**\n * @notice Transfer `amount` tokens from `src` to `dst`\n * @param src The address of the sourceaccount\n * @param dst The address of the destination account\n * @param amount The number of tokens to transfer\n * @return Whether ornot 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 areapproved (-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 currentallowance from `owner` for `spender`\n * @param owner The address of the account which owns the tokens to be spent\n * @param spender Theaddress of the account which may transfer tokens\n * @return The number of tokens allowed to be spent (-1 means infinite)\n */\nfunction 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 * @returnThe number of tokens owned by `owner`\n */\n function balanceOf(address owner) external view returns (uint) {\n owner; // Shh\ndelegateToViewAndReturn();\n }\n\n /**\n * @notice Get the underlying balance of the `owner`\n * @dev This also accrues interest ina transaction\n * @param owner The address of the account to query\n * @return The amount of underlying owned by `owner`\n */\nfunction 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 efficientlyperform 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) {\naccount; // Shh\n delegateToViewAndReturn();\n }\n\n /**\n * @notice Returns the current per-block borrow interest rate for thissToken\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) {\ndelegateToViewAndReturn();\n }\n\n /**\n * @notice Returns the current total borrows plus accrued interest\n * @return The totalborrows 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 * @paramaccount The address whose balance should be calculated after updating borrowIndex\n * @return The calculated balance\n */\n functionborrowBalanceCurrent(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\ndelegateToViewAndReturn();\n }\n\n /**\n * @notice Accrue interest then return the up-to-date exchange rate\n * @returnCalculated 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 interestbefore calculating the exchange rate\n * @return Calculated exchange rate scaled by 1e18\n */\n function exchangeRateStored() publicview returns (uint) {\n delegateToViewAndReturn();\n }\n\n /**\n * @notice Get cash balance of this sToken in the underlyingasset\n * @return The quantity of underlying asset owned by this contract\n */\n function getCash() external view returns (uint) {\ndelegateToViewAndReturn();\n }\n\n /**\n * @notice Applies accrued interest to total borrows and reserves.\n * @dev Thiscalculates 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 collateraltokens (this market) to the liquidator.\n * @dev Will fail unless called by another sToken during the process of liquidation.\n * Itsabsolutely critical to use msg.sender as the borrowed sToken and not a parameter.\n * @param liquidator The account receiving seizedcollateral\n * @param borrower The account having collateral seized\n * @param seizeTokens The number of sTokens to seize\n * @returnuint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function seize(address liquidator, address borrower, uintseizeTokens) external returns (uint) {\n liquidator; borrower; seizeTokens; // Shh\n delegateAndReturn();\n }\n\n /*** AdminFunctions ***/\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 * @paramnewPendingAdmin 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 setsa 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(uintnewReserveFactorMantissa) 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 andupdate 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 fromadmin\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 andupdates the interest rate model using _setInterestRateModelFresh\n * @dev Admin function to accrue interest and update the interest ratemodel\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) {\nnewInterestRateModel; // Shh\n delegateAndReturn();\n }\n\n /**\n * @notice Internal method to delegate execution to anothercontract\n * @dev It returns to the external caller whatever the implementation returns or forwards reverts\n * @param callee The contractto delegatecall\n * @param data The raw data to delegatecall\n * @return The returned bytes from the delegatecall\n */\n functiondelegateTo(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 Itreturns 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 fromthe wrapper returndata, which we ignore since we make an extra hop.\n * @param data The raw data to delegatecall\n * @return The returnedbytes 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));\nassembly {\n if eq(success, 0) {\n revert(add(returnData, 0x20), returndatasize)\n }\n }\nreturn abi.decode(returnData, (bytes));\n }\n\n function delegateToViewAndReturn() private view returns (bytes memory) {\n (boolsuccess, ) = address(this).staticcall(abi.encodeWithSignature(\"delegateToImplementation(bytes)\", msg.data));\n\n assembly {\nlet 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 functiondelegateAndReturn() private returns (bytes memory) {\n (bool success, ) = implementation.delegatecall(msg.data);\n\n assembly {\nlet free_mem_ptr := mload(0x40)\n returndatacopy(free_mem_ptr, 0, returndatasize)\n\n switch success\ncase 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 orforwards reverts\n */\n function () external payable {\n require(msg.value == 0,\"SErc20Delegator:fallback: cannot send value tofallback\");\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 namefor 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 borrowrate that can ever be applied (.0005% / block)\n */\n\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\n\n /**\n * @noticeMaximum 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 thiscontract\n */\n address payable public pendingAdmin;\n\n /**\n * @notice Contract which oversees inter-sToken operations\n */\nComptrollerInterface public comptroller;\n\n /**\n * @notice Model which tells what the current interest rate should be\n */\nInterestRateModel public interestRateModel;\n\n /**\n * @notice Initial exchange rate used when minting the first STokens (used whentotalSupply = 0)\n */\n uint internal initialExchangeRateMantissa;\n\n /**\n * @notice Fraction of interest currently set aside forreserves\n */\n uint public reserveFactorMantissa;\n\n /**\n * @notice Block number that interest was last accrued at\n */\nuint public accrualBlockNumber;\n\n /**\n * @notice Accumulator of the total earned interest rate since the opening of the market\n */\nuint public borrowIndex;\n\n /**\n * @notice Total amount of outstanding borrows of the underlying in this market\n */\n uintpublic totalBorrows;\n\n /**\n * @notice Total amount of reserves of the underlying held in this market\n */\n uint publictotalReserves;\n\n /**\n * @notice Total number of tokens in circulation\n */\n uint public totalSupply;\n\n /**\n * @noticeOfficial record of token balances for each account\n */\n mapping (address =\u003e uint) internal accountTokens;\n\n /**\n * @noticeApproved token transfer amounts on behalf of others\n */\n mapping (address =\u003e mapping (address =\u003e uint)) internaltransferAllowances;\n\n /**\n * @notice Container for borrow balance information\n * @member principal Total balance (with accruedinterest), 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 * @noticeMapping 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 */\nbool 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 Eventemitted when tokens are minted\n */\n event Mint(address minter, uint mintAmount, uint mintTokens);\n\n /**\n * @notice Event emittedwhen tokens are redeemed\n */\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens);\n\n /**\n * @notice Eventemitted 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, uintaccountBorrows, 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(ComptrollerInterfaceoldComptroller, ComptrollerInterface newComptroller);\n\n /**\n * @notice Event emitted when interestRateModel is changed\n */\nevent NewMarketInterestRateModel(InterestRateModel oldInterestRateModel, InterestRateModel newInterestRateModel);\n\n /**\n * @notice Eventemitted 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, uintnewTotalReserves);\n\n /**\n * @notice Event emitted when the reserves are reduced\n */\n event ReservesReduced(address admin, uintreduceAmount, uint newTotalReserves);\n\n /**\n * @notice EIP20 Transfer event\n */\n event Transfer(address indexed from, addressindexed to, uint amount);\n\n /**\n * @notice EIP20 Approval event\n */\n event Approval(address indexed owner, address indexedspender, uint amount);\n\n /**\n * @notice Failure event\n */\n event Failure(uint error, uint info, uint detail);\n\n\n /*** UserInterface ***/\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(addressowner, address spender) external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n functionbalanceOfUnderlying(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);\nfunction totalBorrowsCurrent() external returns (uint);\n function borrowBalanceCurrent(address account) external returns (uint);\n functionborrowBalanceStored(address account) public view returns (uint);\n function exchangeRateCurrent() public returns (uint);\n functionexchangeRateStored() public view returns (uint);\n function getCash() external view returns (uint);\n function accrueInterest() publicreturns (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(uintnewReserveFactorMantissa) 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 * @noticeUnderlying asset for this SToken\n */\n address public underlying;\n}\n\ncontract SErc20Interface is SErc20Storage {\n\n /*** UserInterface ***/\n\n function mint(uint mintAmount) external returns (uint);\n function redeem(uint redeemTokens) external returns (uint);\nfunction redeemUnderlying(uint redeemAmount) external returns (uint);\n function borrow(uint borrowAmount) external returns (uint);\nfunction repayBorrow(uint repayAmount) external returns (uint);\n function repayBorrowBehalf(address borrower, uint repayAmount) externalreturns (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 isSDelegationStorage {\n /**\n * @notice Emitted when implementation is changed\n */\n event NewImplementation(addressoldImplementation, 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 itfor duty\n * @dev Should revert if any issues arise which make it unfit for delegation\n * @param data The encoded bytes data for anyinitialization\n */\n function _becomeImplementation(bytes memory data) public;\n\n /**\n * @notice Called by the delegator on adelegate to forfeit its responsibility\n */\n function _resignImplementation() public;\n}\n"}}
File 12 of 14: WBTC
12345678910111213141516pragma 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);}
File 13 of 14: EACAggregatorProxy
12345678910111213141516pragma 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);
File 14 of 14: AccessControlledOCR2Aggregator
12345678910111213141516// SPDX-License-Identifier: MITpragma 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