diff --git a/.circleci/config.yml b/.circleci/config.yml index dd0f40844..163fd5016 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -11,7 +11,7 @@ jobs: steps: - run: | - sudo wget https://github.com/ethereum/solidity/releases/download/v0.5.16/solc-static-linux -O /usr/local/bin/solc + sudo wget https://github.com/ethereum/solidity/releases/download/v0.8.10/solc-static-linux -O /usr/local/bin/solc sudo chmod +x /usr/local/bin/solc - checkout - restore_cache: @@ -43,7 +43,7 @@ jobs: - run: shell: /bin/bash -eox pipefail -O globstar name: yarn test - command: JEST_JUNIT_OUTPUT_DIR=~/junit JEST_JUNIT_OUTPUT_NAME=test-results.xml yarn test $(circleci tests glob 'tests/**/**Test.js' | circleci tests split --split-by=timings) + command: NODE_OPTIONS="--max-old-space-size=12228" JEST_JUNIT_OUTPUT_DIR=~/junit JEST_JUNIT_OUTPUT_NAME=test-results.xml yarn test $(circleci tests glob 'tests/**/**Test.js' | circleci tests split --split-by=timings) - save_cache: paths: - .build @@ -79,7 +79,7 @@ jobs: steps: - run: | - sudo wget https://github.com/ethereum/solidity/releases/download/v0.5.16/solc-static-linux -O /usr/local/bin/solc + sudo wget https://github.com/ethereum/solidity/releases/download/v0.8.10/solc-static-linux -O /usr/local/bin/solc sudo chmod +x /usr/local/bin/solc - checkout - restore_cache: @@ -112,7 +112,7 @@ jobs: shell: /bin/bash -eox pipefail -O globstar name: yarn test no_output_timeout: 30m - command: JEST_JUNIT_OUTPUT_DIR=~/junit JEST_JUNIT_OUTPUT_NAME=test-results.xml script/coverage $(circleci tests glob 'tests/**/**Test.js' | circleci tests split --split-by=timings) -- --maxWorkers=4 + command: NODE_OPTIONS="--max-old-space-size=12228" JEST_JUNIT_OUTPUT_DIR=~/junit JEST_JUNIT_OUTPUT_NAME=test-results.xml script/coverage $(circleci tests glob 'tests/**/**Test.js' | circleci tests split --split-by=timings) -- --maxWorkers=4 - save_cache: paths: - .build diff --git a/.gitignore b/.gitignore index d668da6b6..f9dd6b2dd 100644 --- a/.gitignore +++ b/.gitignore @@ -36,8 +36,10 @@ scenario/build/webpack.js scenario/.tscache script/certora tests/scenarios/ +tests/Scenarios/ junit.xml .build .last_confs .saddle_history -node_modules_tmp \ No newline at end of file +node_modules_tmp +.idea diff --git a/.solhint.json b/.solhint.json new file mode 100644 index 000000000..16a5038c2 --- /dev/null +++ b/.solhint.json @@ -0,0 +1,15 @@ +{ + "extends": "solhint:recommended", + "rules": { + "quotes": ["error", "double"], + "max-line-length": ["error", 200], + "compiler-version": ["error", "^0.8.0"], + "reason-string": ["warn", { "maxLength": 128 }], + "not-rely-on-block-hash": "off", + "not-rely-on-time": "off", + "no-inline-assembly": "off", + "avoid-low-level-calls": "off", + "avoid-tx-origin": "off", + "imports-on-top": "off" + } +} diff --git a/.soliumignore b/.solhintignore similarity index 100% rename from .soliumignore rename to .solhintignore diff --git a/.soliumrc.json b/.soliumrc.json deleted file mode 100644 index fdf4be8b4..000000000 --- a/.soliumrc.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "extends": "solium:recommended", - "plugins": [ - "security" - ], - "rules": { - "quotes": [ - "error", - "double" - ], - "indentation": "off", - "max-len": [ - "error", - 200 - ], - "security/no-block-members": "off", - "security/no-inline-assembly": "off", - "security/no-low-level-calls": "off", - "security/no-tx-origin": "off", - "imports-on-top": "off" - } -} diff --git a/Dockerfile b/Dockerfile index 3bef01fa0..0f8cd2a1e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ FROM mhart/alpine-node:13.8.0 RUN apk update && apk add --no-cache --virtual build-dependencies git python g++ make -RUN wget https://github.com/ethereum/solidity/releases/download/v0.5.16/solc-static-linux -O /bin/solc && chmod +x /bin/solc +RUN wget https://github.com/ethereum/solidity/releases/download/v0.8.10/solc-static-linux -O /bin/solc && chmod +x /bin/solc RUN mkdir -p /compound-protocol WORKDIR /compound-protocol diff --git a/contracts/BaseJumpRateModelV2.sol b/contracts/BaseJumpRateModelV2.sol index 5981ac3bc..4d6828c39 100644 --- a/contracts/BaseJumpRateModelV2.sol +++ b/contracts/BaseJumpRateModelV2.sol @@ -1,17 +1,18 @@ -pragma solidity ^0.5.16; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; -import "./SafeMath.sol"; +import "./InterestRateModel.sol"; /** * @title Logic for Compound's JumpRateModel Contract V2. * @author Compound (modified by Dharma Labs, refactored by Arr00) * @notice Version 2 modifies Version 1 by enabling updateable parameters. */ -contract BaseJumpRateModelV2 { - using SafeMath for uint; - +abstract contract BaseJumpRateModelV2 is InterestRateModel { event NewInterestParams(uint baseRatePerBlock, uint multiplierPerBlock, uint jumpMultiplierPerBlock, uint kink); + uint256 private constant BASE = 1e18; + /** * @notice The address of the owner, i.e. the Timelock contract, which can update parameters directly */ @@ -44,8 +45,8 @@ contract BaseJumpRateModelV2 { /** * @notice Construct an interest rate model - * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by 1e18) - * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by 1e18) + * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by BASE) + * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by BASE) * @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point * @param kink_ The utilization point at which the jump multiplier is applied * @param owner_ The address of the owner, i.e. the Timelock contract (which has the ability to update parameters directly) @@ -58,12 +59,12 @@ contract BaseJumpRateModelV2 { /** * @notice Update the parameters of the interest rate model (only callable by owner, i.e. Timelock) - * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by 1e18) - * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by 1e18) + * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by BASE) + * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by BASE) * @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point * @param kink_ The utilization point at which the jump multiplier is applied */ - function updateJumpRateModel(uint baseRatePerYear, uint multiplierPerYear, uint jumpMultiplierPerYear, uint kink_) external { + function updateJumpRateModel(uint baseRatePerYear, uint multiplierPerYear, uint jumpMultiplierPerYear, uint kink_) virtual external { require(msg.sender == owner, "only the owner may call this function."); updateJumpRateModelInternal(baseRatePerYear, multiplierPerYear, jumpMultiplierPerYear, kink_); @@ -74,7 +75,7 @@ contract BaseJumpRateModelV2 { * @param cash The amount of cash in the market * @param borrows The amount of borrows in the market * @param reserves The amount of reserves in the market (currently unused) - * @return The utilization rate as a mantissa between [0, 1e18] + * @return The utilization rate as a mantissa between [0, BASE] */ function utilizationRate(uint cash, uint borrows, uint reserves) public pure returns (uint) { // Utilization rate is 0 when there are no borrows @@ -82,7 +83,7 @@ contract BaseJumpRateModelV2 { return 0; } - return borrows.mul(1e18).div(cash.add(borrows).sub(reserves)); + return borrows * BASE / (cash + borrows - reserves); } /** @@ -90,17 +91,17 @@ contract BaseJumpRateModelV2 { * @param cash The amount of cash in the market * @param borrows The amount of borrows in the market * @param reserves The amount of reserves in the market - * @return The borrow rate percentage per block as a mantissa (scaled by 1e18) + * @return The borrow rate percentage per block as a mantissa (scaled by BASE) */ function getBorrowRateInternal(uint cash, uint borrows, uint reserves) internal view returns (uint) { uint util = utilizationRate(cash, borrows, reserves); if (util <= kink) { - return util.mul(multiplierPerBlock).div(1e18).add(baseRatePerBlock); + return ((util * multiplierPerBlock) / BASE) + baseRatePerBlock; } else { - uint normalRate = kink.mul(multiplierPerBlock).div(1e18).add(baseRatePerBlock); - uint excessUtil = util.sub(kink); - return excessUtil.mul(jumpMultiplierPerBlock).div(1e18).add(normalRate); + uint normalRate = ((kink * multiplierPerBlock) / BASE) + baseRatePerBlock; + uint excessUtil = util - kink; + return ((excessUtil * jumpMultiplierPerBlock) / BASE) + normalRate; } } @@ -110,26 +111,26 @@ contract BaseJumpRateModelV2 { * @param borrows The amount of borrows in the market * @param reserves The amount of reserves in the market * @param reserveFactorMantissa The current reserve factor for the market - * @return The supply rate percentage per block as a mantissa (scaled by 1e18) + * @return The supply rate percentage per block as a mantissa (scaled by BASE) */ - function getSupplyRate(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) public view returns (uint) { - uint oneMinusReserveFactor = uint(1e18).sub(reserveFactorMantissa); + function getSupplyRate(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) virtual override public view returns (uint) { + uint oneMinusReserveFactor = BASE - reserveFactorMantissa; uint borrowRate = getBorrowRateInternal(cash, borrows, reserves); - uint rateToPool = borrowRate.mul(oneMinusReserveFactor).div(1e18); - return utilizationRate(cash, borrows, reserves).mul(rateToPool).div(1e18); + uint rateToPool = borrowRate * oneMinusReserveFactor / BASE; + return utilizationRate(cash, borrows, reserves) * rateToPool / BASE; } /** * @notice Internal function to update the parameters of the interest rate model - * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by 1e18) - * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by 1e18) + * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by BASE) + * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by BASE) * @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point * @param kink_ The utilization point at which the jump multiplier is applied */ function updateJumpRateModelInternal(uint baseRatePerYear, uint multiplierPerYear, uint jumpMultiplierPerYear, uint kink_) internal { - baseRatePerBlock = baseRatePerYear.div(blocksPerYear); - multiplierPerBlock = (multiplierPerYear.mul(1e18)).div(blocksPerYear.mul(kink_)); - jumpMultiplierPerBlock = jumpMultiplierPerYear.div(blocksPerYear); + baseRatePerBlock = baseRatePerYear / blocksPerYear; + multiplierPerBlock = (multiplierPerYear * BASE) / (blocksPerYear * kink_); + jumpMultiplierPerBlock = jumpMultiplierPerYear / blocksPerYear; kink = kink_; emit NewInterestParams(baseRatePerBlock, multiplierPerBlock, jumpMultiplierPerBlock, kink); diff --git a/contracts/CDaiDelegate.sol b/contracts/CDaiDelegate.sol index 363285abb..423640c51 100644 --- a/contracts/CDaiDelegate.sol +++ b/contracts/CDaiDelegate.sol @@ -1,4 +1,5 @@ -pragma solidity ^0.5.16; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; import "./CErc20Delegate.sol"; @@ -27,7 +28,7 @@ contract CDaiDelegate is CErc20Delegate { * @notice Delegate interface to become the implementation * @param data The encoded arguments for becoming */ - function _becomeImplementation(bytes memory data) public { + function _becomeImplementation(bytes memory data) override public { require(msg.sender == admin, "only the admin may initialize the implementation"); (address daiJoinAddress_, address potAddress_) = abi.decode(data, (address, address)); @@ -53,7 +54,7 @@ contract CDaiDelegate is CErc20Delegate { vatAddress = address(vat); // Approve moving our DAI into the vat through daiJoin - dai.approve(daiJoinAddress, uint(-1)); + dai.approve(daiJoinAddress, type(uint).max); // Approve the pot to transfer our funds within the vat vat.hope(potAddress); @@ -69,7 +70,7 @@ contract CDaiDelegate is CErc20Delegate { /** * @notice Delegate interface to resign the implementation */ - function _resignImplementation() public { + function _resignImplementation() override public { require(msg.sender == admin, "only the admin may abandon the implementation"); // Transfer all cash out of the DSR - note that this relies on self-transfer @@ -98,7 +99,7 @@ contract CDaiDelegate is CErc20Delegate { * @dev This calculates interest accrued from the last checkpointed block * up to the current block and writes new checkpoint to storage. */ - function accrueInterest() public returns (uint) { + function accrueInterest() override public returns (uint) { // Accumulate DSR interest PotLike(potAddress).drip(); @@ -113,7 +114,7 @@ contract CDaiDelegate is CErc20Delegate { * @dev This excludes the value of the current message, if any * @return The quantity of underlying tokens owned by this contract */ - function getCashPrior() internal view returns (uint) { + function getCashPrior() override internal view returns (uint) { PotLike pot = PotLike(potAddress); uint pie = pot.pie(address(this)); return mul(pot.chi(), pie) / RAY; @@ -125,13 +126,15 @@ contract CDaiDelegate is CErc20Delegate { * @param amount Amount of underlying to transfer * @return The actual amount that is transferred */ - function doTransferIn(address from, uint amount) internal returns (uint) { + function doTransferIn(address from, uint amount) override internal returns (uint) { + // Read from storage once + address underlying_ = underlying; // Perform the EIP-20 transfer in - EIP20Interface token = EIP20Interface(underlying); + EIP20Interface token = EIP20Interface(underlying_); require(token.transferFrom(from, address(this), amount), "unexpected EIP-20 transfer in return"); DaiJoinLike daiJoin = DaiJoinLike(daiJoinAddress); - GemLike dai = GemLike(underlying); + GemLike dai = GemLike(underlying_); PotLike pot = PotLike(potAddress); VatLike vat = VatLike(vatAddress); @@ -154,7 +157,7 @@ contract CDaiDelegate is CErc20Delegate { * @param to Address to transfer funds to * @param amount Amount of underlying to transfer */ - function doTransferOut(address payable to, uint amount) internal { + function doTransferOut(address payable to, uint amount) override internal { DaiJoinLike daiJoin = DaiJoinLike(daiJoinAddress); PotLike pot = PotLike(potAddress); diff --git a/contracts/CErc20.sol b/contracts/CErc20.sol index ddf625bcd..940cc2638 100644 --- a/contracts/CErc20.sol +++ b/contracts/CErc20.sol @@ -1,9 +1,10 @@ -pragma solidity ^0.5.16; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; import "./CToken.sol"; interface CompLike { - function delegate(address delegatee) external; + function delegate(address delegatee) external; } /** @@ -45,9 +46,9 @@ contract CErc20 is CToken, CErc20Interface { * @param mintAmount The amount of the underlying asset to supply * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ - function mint(uint mintAmount) external returns (uint) { - (uint err,) = mintInternal(mintAmount); - return err; + function mint(uint mintAmount) override external returns (uint) { + mintInternal(mintAmount); + return NO_ERROR; } /** @@ -56,8 +57,9 @@ contract CErc20 is CToken, CErc20Interface { * @param redeemTokens The number of cTokens to redeem into underlying * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ - function redeem(uint redeemTokens) external returns (uint) { - return redeemInternal(redeemTokens); + function redeem(uint redeemTokens) override external returns (uint) { + redeemInternal(redeemTokens); + return NO_ERROR; } /** @@ -66,8 +68,9 @@ contract CErc20 is CToken, CErc20Interface { * @param redeemAmount The amount of underlying to redeem * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ - function redeemUnderlying(uint redeemAmount) external returns (uint) { - return redeemUnderlyingInternal(redeemAmount); + function redeemUnderlying(uint redeemAmount) override external returns (uint) { + redeemUnderlyingInternal(redeemAmount); + return NO_ERROR; } /** @@ -75,29 +78,30 @@ contract CErc20 is CToken, CErc20Interface { * @param borrowAmount The amount of the underlying asset to borrow * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ - function borrow(uint borrowAmount) external returns (uint) { - return borrowInternal(borrowAmount); + function borrow(uint borrowAmount) override external returns (uint) { + borrowInternal(borrowAmount); + return NO_ERROR; } /** * @notice Sender repays their own borrow - * @param repayAmount The amount to repay + * @param repayAmount The amount to repay, or -1 for the full outstanding amount * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ - function repayBorrow(uint repayAmount) external returns (uint) { - (uint err,) = repayBorrowInternal(repayAmount); - return err; + function repayBorrow(uint repayAmount) override external returns (uint) { + repayBorrowInternal(repayAmount); + return NO_ERROR; } /** * @notice Sender repays a borrow belonging to borrower * @param borrower the account with the debt being payed off - * @param repayAmount The amount to repay + * @param repayAmount The amount to repay, or -1 for the full outstanding amount * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ - function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint) { - (uint err,) = repayBorrowBehalfInternal(borrower, repayAmount); - return err; + function repayBorrowBehalf(address borrower, uint repayAmount) override external returns (uint) { + repayBorrowBehalfInternal(borrower, repayAmount); + return NO_ERROR; } /** @@ -108,19 +112,20 @@ contract CErc20 is CToken, CErc20Interface { * @param cTokenCollateral The market in which to seize collateral from the borrower * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ - function liquidateBorrow(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) external returns (uint) { - (uint err,) = liquidateBorrowInternal(borrower, repayAmount, cTokenCollateral); - return err; + function liquidateBorrow(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) override external returns (uint) { + liquidateBorrowInternal(borrower, repayAmount, cTokenCollateral); + return NO_ERROR; } /** * @notice A public function to sweep accidental ERC-20 transfers to this contract. Tokens are sent to admin (timelock) * @param token The address of the ERC-20 token to sweep */ - function sweepToken(EIP20NonStandardInterface token) external { - require(address(token) != underlying, "CErc20::sweepToken: can not sweep underlying token"); - uint256 balance = token.balanceOf(address(this)); - token.transfer(admin, balance); + function sweepToken(EIP20NonStandardInterface token) override external { + require(msg.sender == admin, "CErc20::sweepToken: only admin can sweep tokens"); + require(address(token) != underlying, "CErc20::sweepToken: can not sweep underlying token"); + uint256 balance = token.balanceOf(address(this)); + token.transfer(admin, balance); } /** @@ -128,7 +133,7 @@ contract CErc20 is CToken, CErc20Interface { * @param addAmount The amount fo underlying token to add as reserves * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ - function _addReserves(uint addAmount) external returns (uint) { + function _addReserves(uint addAmount) override external returns (uint) { return _addReservesInternal(addAmount); } @@ -139,7 +144,7 @@ contract CErc20 is CToken, CErc20Interface { * @dev This excludes the value of the current message, if any * @return The quantity of underlying tokens owned by this contract */ - function getCashPrior() internal view returns (uint) { + function getCashPrior() virtual override internal view returns (uint) { EIP20Interface token = EIP20Interface(underlying); return token.balanceOf(address(this)); } @@ -153,9 +158,11 @@ contract CErc20 is CToken, CErc20Interface { * Note: This wrapper safely handles non-standard ERC-20 tokens that do not return a value. * See here: https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca */ - function doTransferIn(address from, uint amount) internal returns (uint) { - EIP20NonStandardInterface token = EIP20NonStandardInterface(underlying); - uint balanceBefore = EIP20Interface(underlying).balanceOf(address(this)); + function doTransferIn(address from, uint amount) virtual override internal returns (uint) { + // Read from storage once + address underlying_ = underlying; + EIP20NonStandardInterface token = EIP20NonStandardInterface(underlying_); + uint balanceBefore = EIP20Interface(underlying_).balanceOf(address(this)); token.transferFrom(from, address(this), amount); bool success; @@ -166,7 +173,7 @@ contract CErc20 is CToken, CErc20Interface { } case 32 { // This is a compliant ERC-20 returndatacopy(0, 0, 32) - success := mload(0) // Set `success = returndata` of external call + success := mload(0) // Set `success = returndata` of override external call } default { // This is an excessively non-compliant ERC-20, revert. revert(0, 0) @@ -175,8 +182,7 @@ contract CErc20 is CToken, CErc20Interface { require(success, "TOKEN_TRANSFER_IN_FAILED"); // Calculate the amount that was *actually* transferred - uint balanceAfter = EIP20Interface(underlying).balanceOf(address(this)); - require(balanceAfter >= balanceBefore, "TOKEN_TRANSFER_IN_OVERFLOW"); + uint balanceAfter = EIP20Interface(underlying_).balanceOf(address(this)); return balanceAfter - balanceBefore; // underflow already checked above, just subtract } @@ -189,7 +195,7 @@ contract CErc20 is CToken, CErc20Interface { * Note: This wrapper safely handles non-standard ERC-20 tokens that do not return a value. * See here: https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca */ - function doTransferOut(address payable to, uint amount) internal { + function doTransferOut(address payable to, uint amount) virtual override internal { EIP20NonStandardInterface token = EIP20NonStandardInterface(underlying); token.transfer(to, amount); @@ -201,7 +207,7 @@ contract CErc20 is CToken, CErc20Interface { } case 32 { // This is a compliant ERC-20 returndatacopy(0, 0, 32) - success := mload(0) // Set `success = returndata` of external call + success := mload(0) // Set `success = returndata` of override external call } default { // This is an excessively non-compliant ERC-20, revert. revert(0, 0) diff --git a/contracts/CErc20Delegate.sol b/contracts/CErc20Delegate.sol index ad19ab448..2b09af7fa 100644 --- a/contracts/CErc20Delegate.sol +++ b/contracts/CErc20Delegate.sol @@ -1,4 +1,5 @@ -pragma solidity ^0.5.16; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; import "./CErc20.sol"; @@ -11,13 +12,13 @@ contract CErc20Delegate is CErc20, CDelegateInterface { /** * @notice Construct an empty delegate */ - constructor() public {} + constructor() {} /** * @notice Called by the delegator on a delegate to initialize it for duty * @param data The encoded bytes data for any initialization */ - function _becomeImplementation(bytes memory data) public { + function _becomeImplementation(bytes memory data) virtual override public { // Shh -- currently unused data; @@ -32,7 +33,7 @@ contract CErc20Delegate is CErc20, CDelegateInterface { /** * @notice Called by the delegator on a delegate to forfeit its responsibility */ - function _resignImplementation() public { + function _resignImplementation() virtual override public { // Shh -- we don't ever want this hook to be marked pure if (false) { implementation = address(0); diff --git a/contracts/CErc20Delegator.sol b/contracts/CErc20Delegator.sol index 0e09a7054..ecc0d883e 100644 --- a/contracts/CErc20Delegator.sol +++ b/contracts/CErc20Delegator.sol @@ -1,4 +1,5 @@ -pragma solidity ^0.5.16; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; import "./CTokenInterfaces.sol"; @@ -30,9 +31,9 @@ contract CErc20Delegator is CTokenInterface, CErc20Interface, CDelegatorInterfac uint8 decimals_, address payable admin_, address implementation_, - bytes memory becomeImplementationData) public { + bytes memory becomeImplementationData) { // Creator of the contract is admin during initialization - admin = msg.sender; + admin = payable(msg.sender); // First delegate gets to initialize the delegator (i.e. storage contract) delegateTo(implementation_, abi.encodeWithSignature("initialize(address,address,address,uint256,string,string,uint8)", @@ -57,7 +58,7 @@ contract CErc20Delegator is CTokenInterface, CErc20Interface, CDelegatorInterfac * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation */ - function _setImplementation(address implementation_, bool allowResign, bytes memory becomeImplementationData) public { + function _setImplementation(address implementation_, bool allowResign, bytes memory becomeImplementationData)override public { require(msg.sender == admin, "CErc20Delegator::_setImplementation: Caller must be admin"); if (allowResign) { @@ -78,7 +79,7 @@ contract CErc20Delegator is CTokenInterface, CErc20Interface, CDelegatorInterfac * @param mintAmount The amount of the underlying asset to supply * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ - function mint(uint mintAmount) external returns (uint) { + function mint(uint mintAmount) override external returns (uint) { bytes memory data = delegateToImplementation(abi.encodeWithSignature("mint(uint256)", mintAmount)); return abi.decode(data, (uint)); } @@ -89,7 +90,7 @@ contract CErc20Delegator is CTokenInterface, CErc20Interface, CDelegatorInterfac * @param redeemTokens The number of cTokens to redeem into underlying * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ - function redeem(uint redeemTokens) external returns (uint) { + function redeem(uint redeemTokens) override external returns (uint) { bytes memory data = delegateToImplementation(abi.encodeWithSignature("redeem(uint256)", redeemTokens)); return abi.decode(data, (uint)); } @@ -100,7 +101,7 @@ contract CErc20Delegator is CTokenInterface, CErc20Interface, CDelegatorInterfac * @param redeemAmount The amount of underlying to redeem * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ - function redeemUnderlying(uint redeemAmount) external returns (uint) { + function redeemUnderlying(uint redeemAmount) override external returns (uint) { bytes memory data = delegateToImplementation(abi.encodeWithSignature("redeemUnderlying(uint256)", redeemAmount)); return abi.decode(data, (uint)); } @@ -110,17 +111,17 @@ contract CErc20Delegator is CTokenInterface, CErc20Interface, CDelegatorInterfac * @param borrowAmount The amount of the underlying asset to borrow * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ - function borrow(uint borrowAmount) external returns (uint) { + function borrow(uint borrowAmount) override external returns (uint) { bytes memory data = delegateToImplementation(abi.encodeWithSignature("borrow(uint256)", borrowAmount)); return abi.decode(data, (uint)); } /** * @notice Sender repays their own borrow - * @param repayAmount The amount to repay + * @param repayAmount The amount to repay, or -1 for the full outstanding amount * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ - function repayBorrow(uint repayAmount) external returns (uint) { + function repayBorrow(uint repayAmount) override external returns (uint) { bytes memory data = delegateToImplementation(abi.encodeWithSignature("repayBorrow(uint256)", repayAmount)); return abi.decode(data, (uint)); } @@ -128,10 +129,10 @@ contract CErc20Delegator is CTokenInterface, CErc20Interface, CDelegatorInterfac /** * @notice Sender repays a borrow belonging to borrower * @param borrower the account with the debt being payed off - * @param repayAmount The amount to repay + * @param repayAmount The amount to repay, or -1 for the full outstanding amount * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ - function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint) { + function repayBorrowBehalf(address borrower, uint repayAmount) override external returns (uint) { bytes memory data = delegateToImplementation(abi.encodeWithSignature("repayBorrowBehalf(address,uint256)", borrower, repayAmount)); return abi.decode(data, (uint)); } @@ -144,7 +145,7 @@ contract CErc20Delegator is CTokenInterface, CErc20Interface, CDelegatorInterfac * @param repayAmount The amount of the underlying borrowed asset to repay * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ - function liquidateBorrow(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) external returns (uint) { + function liquidateBorrow(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) override external returns (uint) { bytes memory data = delegateToImplementation(abi.encodeWithSignature("liquidateBorrow(address,uint256,address)", borrower, repayAmount, cTokenCollateral)); return abi.decode(data, (uint)); } @@ -155,7 +156,7 @@ contract CErc20Delegator is CTokenInterface, CErc20Interface, CDelegatorInterfac * @param amount The number of tokens to transfer * @return Whether or not the transfer succeeded */ - function transfer(address dst, uint amount) external returns (bool) { + function transfer(address dst, uint amount) override external returns (bool) { bytes memory data = delegateToImplementation(abi.encodeWithSignature("transfer(address,uint256)", dst, amount)); return abi.decode(data, (bool)); } @@ -167,7 +168,7 @@ contract CErc20Delegator is CTokenInterface, CErc20Interface, CDelegatorInterfac * @param amount The number of tokens to transfer * @return Whether or not the transfer succeeded */ - function transferFrom(address src, address dst, uint256 amount) external returns (bool) { + function transferFrom(address src, address dst, uint256 amount) override external returns (bool) { bytes memory data = delegateToImplementation(abi.encodeWithSignature("transferFrom(address,address,uint256)", src, dst, amount)); return abi.decode(data, (bool)); } @@ -180,7 +181,7 @@ contract CErc20Delegator is CTokenInterface, CErc20Interface, CDelegatorInterfac * @param amount The number of tokens that are approved (-1 means infinite) * @return Whether or not the approval succeeded */ - function approve(address spender, uint256 amount) external returns (bool) { + function approve(address spender, uint256 amount) override external returns (bool) { bytes memory data = delegateToImplementation(abi.encodeWithSignature("approve(address,uint256)", spender, amount)); return abi.decode(data, (bool)); } @@ -191,7 +192,7 @@ contract CErc20Delegator is CTokenInterface, CErc20Interface, CDelegatorInterfac * @param spender The address of the account which may transfer tokens * @return The number of tokens allowed to be spent (-1 means infinite) */ - function allowance(address owner, address spender) external view returns (uint) { + function allowance(address owner, address spender) override external view returns (uint) { bytes memory data = delegateToViewImplementation(abi.encodeWithSignature("allowance(address,address)", owner, spender)); return abi.decode(data, (uint)); } @@ -201,7 +202,7 @@ contract CErc20Delegator is CTokenInterface, CErc20Interface, CDelegatorInterfac * @param owner The address of the account to query * @return The number of tokens owned by `owner` */ - function balanceOf(address owner) external view returns (uint) { + function balanceOf(address owner) override external view returns (uint) { bytes memory data = delegateToViewImplementation(abi.encodeWithSignature("balanceOf(address)", owner)); return abi.decode(data, (uint)); } @@ -212,7 +213,7 @@ contract CErc20Delegator is CTokenInterface, CErc20Interface, CDelegatorInterfac * @param owner The address of the account to query * @return The amount of underlying owned by `owner` */ - function balanceOfUnderlying(address owner) external returns (uint) { + function balanceOfUnderlying(address owner) override external returns (uint) { bytes memory data = delegateToImplementation(abi.encodeWithSignature("balanceOfUnderlying(address)", owner)); return abi.decode(data, (uint)); } @@ -223,7 +224,7 @@ contract CErc20Delegator is CTokenInterface, CErc20Interface, CDelegatorInterfac * @param account Address of the account to snapshot * @return (possible error, token balance, borrow balance, exchange rate mantissa) */ - function getAccountSnapshot(address account) external view returns (uint, uint, uint, uint) { + function getAccountSnapshot(address account) override external view returns (uint, uint, uint, uint) { bytes memory data = delegateToViewImplementation(abi.encodeWithSignature("getAccountSnapshot(address)", account)); return abi.decode(data, (uint, uint, uint, uint)); } @@ -232,7 +233,7 @@ contract CErc20Delegator is CTokenInterface, CErc20Interface, CDelegatorInterfac * @notice Returns the current per-block borrow interest rate for this cToken * @return The borrow interest rate per block, scaled by 1e18 */ - function borrowRatePerBlock() external view returns (uint) { + function borrowRatePerBlock() override external view returns (uint) { bytes memory data = delegateToViewImplementation(abi.encodeWithSignature("borrowRatePerBlock()")); return abi.decode(data, (uint)); } @@ -241,7 +242,7 @@ contract CErc20Delegator is CTokenInterface, CErc20Interface, CDelegatorInterfac * @notice Returns the current per-block supply interest rate for this cToken * @return The supply interest rate per block, scaled by 1e18 */ - function supplyRatePerBlock() external view returns (uint) { + function supplyRatePerBlock() override external view returns (uint) { bytes memory data = delegateToViewImplementation(abi.encodeWithSignature("supplyRatePerBlock()")); return abi.decode(data, (uint)); } @@ -250,7 +251,7 @@ contract CErc20Delegator is CTokenInterface, CErc20Interface, CDelegatorInterfac * @notice Returns the current total borrows plus accrued interest * @return The total borrows with interest */ - function totalBorrowsCurrent() external returns (uint) { + function totalBorrowsCurrent() override external returns (uint) { bytes memory data = delegateToImplementation(abi.encodeWithSignature("totalBorrowsCurrent()")); return abi.decode(data, (uint)); } @@ -260,7 +261,7 @@ contract CErc20Delegator is CTokenInterface, CErc20Interface, CDelegatorInterfac * @param account The address whose balance should be calculated after updating borrowIndex * @return The calculated balance */ - function borrowBalanceCurrent(address account) external returns (uint) { + function borrowBalanceCurrent(address account) override external returns (uint) { bytes memory data = delegateToImplementation(abi.encodeWithSignature("borrowBalanceCurrent(address)", account)); return abi.decode(data, (uint)); } @@ -270,16 +271,16 @@ contract CErc20Delegator is CTokenInterface, CErc20Interface, CDelegatorInterfac * @param account The address whose balance should be calculated * @return The calculated balance */ - function borrowBalanceStored(address account) public view returns (uint) { + function borrowBalanceStored(address account) override public view returns (uint) { bytes memory data = delegateToViewImplementation(abi.encodeWithSignature("borrowBalanceStored(address)", account)); return abi.decode(data, (uint)); } - /** + /** * @notice Accrue interest then return the up-to-date exchange rate * @return Calculated exchange rate scaled by 1e18 */ - function exchangeRateCurrent() public returns (uint) { + function exchangeRateCurrent() override public returns (uint) { bytes memory data = delegateToImplementation(abi.encodeWithSignature("exchangeRateCurrent()")); return abi.decode(data, (uint)); } @@ -289,7 +290,7 @@ contract CErc20Delegator is CTokenInterface, CErc20Interface, CDelegatorInterfac * @dev This function does not accrue interest before calculating the exchange rate * @return Calculated exchange rate scaled by 1e18 */ - function exchangeRateStored() public view returns (uint) { + function exchangeRateStored() override public view returns (uint) { bytes memory data = delegateToViewImplementation(abi.encodeWithSignature("exchangeRateStored()")); return abi.decode(data, (uint)); } @@ -298,7 +299,7 @@ contract CErc20Delegator is CTokenInterface, CErc20Interface, CDelegatorInterfac * @notice Get cash balance of this cToken in the underlying asset * @return The quantity of underlying asset owned by this contract */ - function getCash() external view returns (uint) { + function getCash() override external view returns (uint) { bytes memory data = delegateToViewImplementation(abi.encodeWithSignature("getCash()")); return abi.decode(data, (uint)); } @@ -308,7 +309,7 @@ contract CErc20Delegator is CTokenInterface, CErc20Interface, CDelegatorInterfac * @dev This calculates interest accrued from the last checkpointed block * up to the current block and writes new checkpoint to storage. */ - function accrueInterest() public returns (uint) { + function accrueInterest() override public returns (uint) { bytes memory data = delegateToImplementation(abi.encodeWithSignature("accrueInterest()")); return abi.decode(data, (uint)); } @@ -322,7 +323,7 @@ contract CErc20Delegator is CTokenInterface, CErc20Interface, CDelegatorInterfac * @param seizeTokens The number of cTokens to seize * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ - function seize(address liquidator, address borrower, uint seizeTokens) external returns (uint) { + function seize(address liquidator, address borrower, uint seizeTokens) override external returns (uint) { bytes memory data = delegateToImplementation(abi.encodeWithSignature("seize(address,address,uint256)", liquidator, borrower, seizeTokens)); return abi.decode(data, (uint)); } @@ -331,7 +332,7 @@ contract CErc20Delegator is CTokenInterface, CErc20Interface, CDelegatorInterfac * @notice A public function to sweep accidental ERC-20 transfers to this contract. Tokens are sent to admin (timelock) * @param token The address of the ERC-20 token to sweep */ - function sweepToken(EIP20NonStandardInterface token) external { + function sweepToken(EIP20NonStandardInterface token) override external { delegateToImplementation(abi.encodeWithSignature("sweepToken(address)", token)); } @@ -344,7 +345,7 @@ contract CErc20Delegator is CTokenInterface, CErc20Interface, CDelegatorInterfac * @param newPendingAdmin New pending admin. * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ - function _setPendingAdmin(address payable newPendingAdmin) external returns (uint) { + function _setPendingAdmin(address payable newPendingAdmin) override external returns (uint) { bytes memory data = delegateToImplementation(abi.encodeWithSignature("_setPendingAdmin(address)", newPendingAdmin)); return abi.decode(data, (uint)); } @@ -354,7 +355,7 @@ contract CErc20Delegator is CTokenInterface, CErc20Interface, CDelegatorInterfac * @dev Admin function to set a new comptroller * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ - function _setComptroller(ComptrollerInterface newComptroller) public returns (uint) { + function _setComptroller(ComptrollerInterface newComptroller) override public returns (uint) { bytes memory data = delegateToImplementation(abi.encodeWithSignature("_setComptroller(address)", newComptroller)); return abi.decode(data, (uint)); } @@ -364,7 +365,7 @@ contract CErc20Delegator is CTokenInterface, CErc20Interface, CDelegatorInterfac * @dev Admin function to accrue interest and set a new reserve factor * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ - function _setReserveFactor(uint newReserveFactorMantissa) external returns (uint) { + function _setReserveFactor(uint newReserveFactorMantissa) override external returns (uint) { bytes memory data = delegateToImplementation(abi.encodeWithSignature("_setReserveFactor(uint256)", newReserveFactorMantissa)); return abi.decode(data, (uint)); } @@ -374,7 +375,7 @@ contract CErc20Delegator is CTokenInterface, CErc20Interface, CDelegatorInterfac * @dev Admin function for pending admin to accept role and update admin * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ - function _acceptAdmin() external returns (uint) { + function _acceptAdmin() override external returns (uint) { bytes memory data = delegateToImplementation(abi.encodeWithSignature("_acceptAdmin()")); return abi.decode(data, (uint)); } @@ -384,7 +385,7 @@ contract CErc20Delegator is CTokenInterface, CErc20Interface, CDelegatorInterfac * @param addAmount Amount of reserves to add * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ - function _addReserves(uint addAmount) external returns (uint) { + function _addReserves(uint addAmount) override external returns (uint) { bytes memory data = delegateToImplementation(abi.encodeWithSignature("_addReserves(uint256)", addAmount)); return abi.decode(data, (uint)); } @@ -394,7 +395,7 @@ contract CErc20Delegator is CTokenInterface, CErc20Interface, CDelegatorInterfac * @param reduceAmount Amount of reduction to reserves * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ - function _reduceReserves(uint reduceAmount) external returns (uint) { + function _reduceReserves(uint reduceAmount) override external returns (uint) { bytes memory data = delegateToImplementation(abi.encodeWithSignature("_reduceReserves(uint256)", reduceAmount)); return abi.decode(data, (uint)); } @@ -405,7 +406,7 @@ contract CErc20Delegator is CTokenInterface, CErc20Interface, CDelegatorInterfac * @param newInterestRateModel the new interest rate model to use * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ - function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint) { + function _setInterestRateModel(InterestRateModel newInterestRateModel) override public returns (uint) { bytes memory data = delegateToImplementation(abi.encodeWithSignature("_setInterestRateModel(address)", newInterestRateModel)); return abi.decode(data, (uint)); } @@ -421,7 +422,7 @@ contract CErc20Delegator is CTokenInterface, CErc20Interface, CDelegatorInterfac (bool success, bytes memory returnData) = callee.delegatecall(data); assembly { if eq(success, 0) { - revert(add(returnData, 0x20), returndatasize) + revert(add(returnData, 0x20), returndatasize()) } } return returnData; @@ -448,7 +449,7 @@ contract CErc20Delegator is CTokenInterface, CErc20Interface, CDelegatorInterfac (bool success, bytes memory returnData) = address(this).staticcall(abi.encodeWithSignature("delegateToImplementation(bytes)", data)); assembly { if eq(success, 0) { - revert(add(returnData, 0x20), returndatasize) + revert(add(returnData, 0x20), returndatasize()) } } return abi.decode(returnData, (bytes)); @@ -458,7 +459,7 @@ contract CErc20Delegator is CTokenInterface, CErc20Interface, CDelegatorInterfac * @notice Delegates execution to an implementation contract * @dev It returns to the external caller whatever the implementation returns or forwards reverts */ - function () external payable { + fallback() external payable { require(msg.value == 0,"CErc20Delegator:fallback: cannot send value to fallback"); // delegate all other functions to current implementation @@ -466,11 +467,11 @@ contract CErc20Delegator is CTokenInterface, CErc20Interface, CDelegatorInterfac assembly { let free_mem_ptr := mload(0x40) - returndatacopy(free_mem_ptr, 0, returndatasize) + returndatacopy(free_mem_ptr, 0, returndatasize()) switch success - case 0 { revert(free_mem_ptr, returndatasize) } - default { return(free_mem_ptr, returndatasize) } + case 0 { revert(free_mem_ptr, returndatasize()) } + default { return(free_mem_ptr, returndatasize()) } } } } diff --git a/contracts/CErc20Immutable.sol b/contracts/CErc20Immutable.sol index 164f1bcc7..0782db629 100644 --- a/contracts/CErc20Immutable.sol +++ b/contracts/CErc20Immutable.sol @@ -1,4 +1,5 @@ -pragma solidity ^0.5.16; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; import "./CErc20.sol"; @@ -26,9 +27,9 @@ contract CErc20Immutable is CErc20 { string memory name_, string memory symbol_, uint8 decimals_, - address payable admin_) public { + address payable admin_) { // Creator of the contract is admin during initialization - admin = msg.sender; + admin = payable(msg.sender); // Initialize the market initialize(underlying_, comptroller_, interestRateModel_, initialExchangeRateMantissa_, name_, symbol_, decimals_); diff --git a/contracts/CEther.sol b/contracts/CEther.sol index 6df990a35..183eb2935 100644 --- a/contracts/CEther.sol +++ b/contracts/CEther.sol @@ -1,4 +1,5 @@ -pragma solidity ^0.5.16; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; import "./CToken.sol"; @@ -24,9 +25,9 @@ contract CEther is CToken { string memory name_, string memory symbol_, uint8 decimals_, - address payable admin_) public { + address payable admin_) { // Creator of the contract is admin during initialization - admin = msg.sender; + admin = payable(msg.sender); initialize(comptroller_, interestRateModel_, initialExchangeRateMantissa_, name_, symbol_, decimals_); @@ -42,8 +43,7 @@ contract CEther is CToken { * @dev Reverts upon any failure */ function mint() external payable { - (uint err,) = mintInternal(msg.value); - requireNoError(err, "mint failed"); + mintInternal(msg.value); } /** @@ -53,7 +53,8 @@ contract CEther is CToken { * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function redeem(uint redeemTokens) external returns (uint) { - return redeemInternal(redeemTokens); + redeemInternal(redeemTokens); + return NO_ERROR; } /** @@ -63,7 +64,8 @@ contract CEther is CToken { * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function redeemUnderlying(uint redeemAmount) external returns (uint) { - return redeemUnderlyingInternal(redeemAmount); + redeemUnderlyingInternal(redeemAmount); + return NO_ERROR; } /** @@ -72,7 +74,8 @@ contract CEther is CToken { * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function borrow(uint borrowAmount) external returns (uint) { - return borrowInternal(borrowAmount); + borrowInternal(borrowAmount); + return NO_ERROR; } /** @@ -80,8 +83,7 @@ contract CEther is CToken { * @dev Reverts upon any failure */ function repayBorrow() external payable { - (uint err,) = repayBorrowInternal(msg.value); - requireNoError(err, "repayBorrow failed"); + repayBorrowInternal(msg.value); } /** @@ -90,8 +92,7 @@ contract CEther is CToken { * @param borrower the account with the debt being payed off */ function repayBorrowBehalf(address borrower) external payable { - (uint err,) = repayBorrowBehalfInternal(borrower, msg.value); - requireNoError(err, "repayBorrowBehalf failed"); + repayBorrowBehalfInternal(borrower, msg.value); } /** @@ -102,8 +103,7 @@ contract CEther is CToken { * @param cTokenCollateral The market in which to seize collateral from the borrower */ function liquidateBorrow(address borrower, CToken cTokenCollateral) external payable { - (uint err,) = liquidateBorrowInternal(borrower, msg.value, cTokenCollateral); - requireNoError(err, "liquidateBorrow failed"); + liquidateBorrowInternal(borrower, msg.value, cTokenCollateral); } /** @@ -117,9 +117,8 @@ contract CEther is CToken { /** * @notice Send Ether to CEther to mint */ - function () external payable { - (uint err,) = mintInternal(msg.value); - requireNoError(err, "mint failed"); + receive() external payable { + mintInternal(msg.value); } /*** Safe Token ***/ @@ -129,10 +128,8 @@ contract CEther is CToken { * @dev This excludes the value of the current message, if any * @return The quantity of Ether owned by this contract */ - function getCashPrior() internal view returns (uint) { - (MathError err, uint startingBalance) = subUInt(address(this).balance, msg.value); - require(err == MathError.NO_ERROR); - return startingBalance; + function getCashPrior() override internal view returns (uint) { + return address(this).balance - msg.value; } /** @@ -141,36 +138,15 @@ contract CEther is CToken { * @param amount Amount of Ether being sent * @return The actual amount of Ether transferred */ - function doTransferIn(address from, uint amount) internal returns (uint) { + function doTransferIn(address from, uint amount) override internal returns (uint) { // Sanity checks require(msg.sender == from, "sender mismatch"); require(msg.value == amount, "value mismatch"); return amount; } - function doTransferOut(address payable to, uint amount) internal { + function doTransferOut(address payable to, uint amount) virtual override internal { /* Send the Ether, with minimal gas and revert on failure */ to.transfer(amount); } - - function requireNoError(uint errCode, string memory message) internal pure { - if (errCode == uint(Error.NO_ERROR)) { - return; - } - - bytes memory fullMessage = new bytes(bytes(message).length + 5); - uint i; - - for (i = 0; i < bytes(message).length; i++) { - fullMessage[i] = bytes(message)[i]; - } - - fullMessage[i+0] = byte(uint8(32)); - fullMessage[i+1] = byte(uint8(40)); - fullMessage[i+2] = byte(uint8(48 + ( errCode / 10 ))); - fullMessage[i+3] = byte(uint8(48 + ( errCode % 10 ))); - fullMessage[i+4] = byte(uint8(41)); - - require(errCode == uint(Error.NO_ERROR), string(fullMessage)); - } } diff --git a/contracts/CToken.sol b/contracts/CToken.sol index 3f1eecda5..b8c878c79 100644 --- a/contracts/CToken.sol +++ b/contracts/CToken.sol @@ -1,18 +1,19 @@ -pragma solidity ^0.5.16; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; import "./ComptrollerInterface.sol"; import "./CTokenInterfaces.sol"; import "./ErrorReporter.sol"; -import "./Exponential.sol"; import "./EIP20Interface.sol"; import "./InterestRateModel.sol"; +import "./ExponentialNoError.sol"; /** * @title Compound's CToken Contract * @notice Abstract base for CTokens * @author Compound */ -contract CToken is CTokenInterface, Exponential, TokenErrorReporter { +abstract contract CToken is CTokenInterface, ExponentialNoError, TokenErrorReporter { /** * @notice Initialize the money market * @param comptroller_ The address of the Comptroller @@ -37,7 +38,7 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { // Set the comptroller uint err = _setComptroller(comptroller_); - require(err == uint(Error.NO_ERROR), "setting comptroller failed"); + require(err == NO_ERROR, "setting comptroller failed"); // Initialize block number and borrow index (block number mocks depend on comptroller being set) accrualBlockNumber = getBlockNumber(); @@ -45,7 +46,7 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { // Set the interest rate model (depends on block number / borrow index) err = _setInterestRateModelFresh(interestRateModel_); - require(err == uint(Error.NO_ERROR), "setting interest rate model failed"); + require(err == NO_ERROR, "setting interest rate model failed"); name = name_; symbol = symbol_; @@ -62,48 +63,32 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { * @param src The address of the source account * @param dst The address of the destination account * @param tokens The number of tokens to transfer - * @return Whether or not the transfer succeeded + * @return 0 if the transfer succeeded, else revert */ function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) { /* Fail if transfer not allowed */ uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens); if (allowed != 0) { - return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed); + revert TransferComptrollerRejection(allowed); } /* Do not allow self-transfers */ if (src == dst) { - return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED); + revert TransferNotAllowed(); } /* Get the allowance, infinite for the account owner */ uint startingAllowance = 0; if (spender == src) { - startingAllowance = uint(-1); + startingAllowance = type(uint).max; } else { startingAllowance = transferAllowances[src][spender]; } /* Do the calculations, checking for {under,over}flow */ - MathError mathErr; - uint allowanceNew; - uint srcTokensNew; - uint dstTokensNew; - - (mathErr, allowanceNew) = subUInt(startingAllowance, tokens); - if (mathErr != MathError.NO_ERROR) { - return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ALLOWED); - } - - (mathErr, srcTokensNew) = subUInt(accountTokens[src], tokens); - if (mathErr != MathError.NO_ERROR) { - return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ENOUGH); - } - - (mathErr, dstTokensNew) = addUInt(accountTokens[dst], tokens); - if (mathErr != MathError.NO_ERROR) { - return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_TOO_MUCH); - } + uint allowanceNew = startingAllowance - tokens; + uint srcTokensNew = accountTokens[src] - tokens; + uint dstTokensNew = accountTokens[dst] + tokens; ///////////////////////// // EFFECTS & INTERACTIONS @@ -113,7 +98,7 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { accountTokens[dst] = dstTokensNew; /* Eat some of the allowance (if necessary) */ - if (startingAllowance != uint(-1)) { + if (startingAllowance != type(uint).max) { transferAllowances[src][spender] = allowanceNew; } @@ -123,7 +108,7 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { // unused function // comptroller.transferVerify(address(this), src, dst, tokens); - return uint(Error.NO_ERROR); + return NO_ERROR; } /** @@ -132,8 +117,8 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { * @param amount The number of tokens to transfer * @return Whether or not the transfer succeeded */ - function transfer(address dst, uint256 amount) external nonReentrant returns (bool) { - return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR); + function transfer(address dst, uint256 amount) override external nonReentrant returns (bool) { + return transferTokens(msg.sender, msg.sender, dst, amount) == NO_ERROR; } /** @@ -143,8 +128,8 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { * @param amount The number of tokens to transfer * @return Whether or not the transfer succeeded */ - function transferFrom(address src, address dst, uint256 amount) external nonReentrant returns (bool) { - return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR); + function transferFrom(address src, address dst, uint256 amount) override external nonReentrant returns (bool) { + return transferTokens(msg.sender, src, dst, amount) == NO_ERROR; } /** @@ -152,10 +137,10 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { * @dev This will overwrite the approval amount for `spender` * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve) * @param spender The address of the account which may transfer tokens - * @param amount The number of tokens that are approved (-1 means infinite) + * @param amount The number of tokens that are approved (uint256.max means infinite) * @return Whether or not the approval succeeded */ - function approve(address spender, uint256 amount) external returns (bool) { + function approve(address spender, uint256 amount) override external returns (bool) { address src = msg.sender; transferAllowances[src][spender] = amount; emit Approval(src, spender, amount); @@ -168,7 +153,7 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { * @param spender The address of the account which may transfer tokens * @return The number of tokens allowed to be spent (-1 means infinite) */ - function allowance(address owner, address spender) external view returns (uint256) { + function allowance(address owner, address spender) override external view returns (uint256) { return transferAllowances[owner][spender]; } @@ -177,7 +162,7 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { * @param owner The address of the account to query * @return The number of tokens owned by `owner` */ - function balanceOf(address owner) external view returns (uint256) { + function balanceOf(address owner) override external view returns (uint256) { return accountTokens[owner]; } @@ -187,11 +172,9 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { * @param owner The address of the account to query * @return The amount of underlying owned by `owner` */ - function balanceOfUnderlying(address owner) external returns (uint) { + function balanceOfUnderlying(address owner) override external returns (uint) { Exp memory exchangeRate = Exp({mantissa: exchangeRateCurrent()}); - (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]); - require(mErr == MathError.NO_ERROR, "balance could not be calculated"); - return balance; + return mul_ScalarTruncate(exchangeRate, accountTokens[owner]); } /** @@ -200,31 +183,20 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { * @param account Address of the account to snapshot * @return (possible error, token balance, borrow balance, exchange rate mantissa) */ - function getAccountSnapshot(address account) external view returns (uint, uint, uint, uint) { - uint cTokenBalance = accountTokens[account]; - uint borrowBalance; - uint exchangeRateMantissa; - - MathError mErr; - - (mErr, borrowBalance) = borrowBalanceStoredInternal(account); - if (mErr != MathError.NO_ERROR) { - return (uint(Error.MATH_ERROR), 0, 0, 0); - } - - (mErr, exchangeRateMantissa) = exchangeRateStoredInternal(); - if (mErr != MathError.NO_ERROR) { - return (uint(Error.MATH_ERROR), 0, 0, 0); - } - - return (uint(Error.NO_ERROR), cTokenBalance, borrowBalance, exchangeRateMantissa); + function getAccountSnapshot(address account) override external view returns (uint, uint, uint, uint) { + return ( + NO_ERROR, + accountTokens[account], + borrowBalanceStoredInternal(account), + exchangeRateStoredInternal() + ); } /** * @dev Function to simply retrieve block number * This exists mainly for inheriting test contracts to stub this result. */ - function getBlockNumber() internal view returns (uint) { + function getBlockNumber() virtual internal view returns (uint) { return block.number; } @@ -232,7 +204,7 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { * @notice Returns the current per-block borrow interest rate for this cToken * @return The borrow interest rate per block, scaled by 1e18 */ - function borrowRatePerBlock() external view returns (uint) { + function borrowRatePerBlock() override external view returns (uint) { return interestRateModel.getBorrowRate(getCashPrior(), totalBorrows, totalReserves); } @@ -240,7 +212,7 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { * @notice Returns the current per-block supply interest rate for this cToken * @return The supply interest rate per block, scaled by 1e18 */ - function supplyRatePerBlock() external view returns (uint) { + function supplyRatePerBlock() override external view returns (uint) { return interestRateModel.getSupplyRate(getCashPrior(), totalBorrows, totalReserves, reserveFactorMantissa); } @@ -248,8 +220,8 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { * @notice Returns the current total borrows plus accrued interest * @return The total borrows with interest */ - function totalBorrowsCurrent() external nonReentrant returns (uint) { - require(accrueInterest() == uint(Error.NO_ERROR), "accrue interest failed"); + function totalBorrowsCurrent() override external nonReentrant returns (uint) { + accrueInterest(); return totalBorrows; } @@ -258,8 +230,8 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { * @param account The address whose balance should be calculated after updating borrowIndex * @return The calculated balance */ - function borrowBalanceCurrent(address account) external nonReentrant returns (uint) { - require(accrueInterest() == uint(Error.NO_ERROR), "accrue interest failed"); + function borrowBalanceCurrent(address account) override external nonReentrant returns (uint) { + accrueInterest(); return borrowBalanceStored(account); } @@ -268,10 +240,8 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { * @param account The address whose balance should be calculated * @return The calculated balance */ - function borrowBalanceStored(address account) public view returns (uint) { - (MathError err, uint result) = borrowBalanceStoredInternal(account); - require(err == MathError.NO_ERROR, "borrowBalanceStored: borrowBalanceStoredInternal failed"); - return result; + function borrowBalanceStored(address account) override public view returns (uint) { + return borrowBalanceStoredInternal(account); } /** @@ -279,12 +249,7 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { * @param account The address whose balance should be calculated * @return (error code, the calculated balance or 0 if error code is non-zero) */ - function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) { - /* Note: we do not assert that the market is up to date */ - MathError mathErr; - uint principalTimesIndex; - uint result; - + function borrowBalanceStoredInternal(address account) internal view returns (uint) { /* Get borrowBalance and borrowIndex */ BorrowSnapshot storage borrowSnapshot = accountBorrows[account]; @@ -292,31 +257,22 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { * Rather than failing the calculation with a division by 0, we immediately return 0 in this case. */ if (borrowSnapshot.principal == 0) { - return (MathError.NO_ERROR, 0); + return 0; } /* Calculate new borrow balance using the interest index: * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex */ - (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex); - if (mathErr != MathError.NO_ERROR) { - return (mathErr, 0); - } - - (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex); - if (mathErr != MathError.NO_ERROR) { - return (mathErr, 0); - } - - return (MathError.NO_ERROR, result); + uint principalTimesIndex = borrowSnapshot.principal * borrowIndex; + return principalTimesIndex / borrowSnapshot.interestIndex; } /** * @notice Accrue interest then return the up-to-date exchange rate * @return Calculated exchange rate scaled by 1e18 */ - function exchangeRateCurrent() public nonReentrant returns (uint) { - require(accrueInterest() == uint(Error.NO_ERROR), "accrue interest failed"); + function exchangeRateCurrent() override public nonReentrant returns (uint) { + accrueInterest(); return exchangeRateStored(); } @@ -325,46 +281,33 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { * @dev This function does not accrue interest before calculating the exchange rate * @return Calculated exchange rate scaled by 1e18 */ - function exchangeRateStored() public view returns (uint) { - (MathError err, uint result) = exchangeRateStoredInternal(); - require(err == MathError.NO_ERROR, "exchangeRateStored: exchangeRateStoredInternal failed"); - return result; + function exchangeRateStored() override public view returns (uint) { + return exchangeRateStoredInternal(); } /** * @notice Calculates the exchange rate from the underlying to the CToken * @dev This function does not accrue interest before calculating the exchange rate - * @return (error code, calculated exchange rate scaled by 1e18) + * @return calculated exchange rate scaled by 1e18 */ - function exchangeRateStoredInternal() internal view returns (MathError, uint) { + function exchangeRateStoredInternal() virtual internal view returns (uint) { uint _totalSupply = totalSupply; if (_totalSupply == 0) { /* * If there are no tokens minted: * exchangeRate = initialExchangeRate */ - return (MathError.NO_ERROR, initialExchangeRateMantissa); + return initialExchangeRateMantissa; } else { /* * Otherwise: * exchangeRate = (totalCash + totalBorrows - totalReserves) / totalSupply */ uint totalCash = getCashPrior(); - uint cashPlusBorrowsMinusReserves; - Exp memory exchangeRate; - MathError mathErr; + uint cashPlusBorrowsMinusReserves = totalCash + totalBorrows - totalReserves; + uint exchangeRate = cashPlusBorrowsMinusReserves * expScale / _totalSupply; - (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves); - if (mathErr != MathError.NO_ERROR) { - return (mathErr, 0); - } - - (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply); - if (mathErr != MathError.NO_ERROR) { - return (mathErr, 0); - } - - return (MathError.NO_ERROR, exchangeRate.mantissa); + return exchangeRate; } } @@ -372,7 +315,7 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { * @notice Get cash balance of this cToken in the underlying asset * @return The quantity of underlying asset owned by this contract */ - function getCash() external view returns (uint) { + function getCash() override external view returns (uint) { return getCashPrior(); } @@ -381,14 +324,14 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { * @dev This calculates interest accrued from the last checkpointed block * up to the current block and writes new checkpoint to storage. */ - function accrueInterest() public returns (uint) { + function accrueInterest() virtual override public returns (uint) { /* Remember the initial block number */ uint currentBlockNumber = getBlockNumber(); uint accrualBlockNumberPrior = accrualBlockNumber; /* Short-circuit accumulating 0 interest */ if (accrualBlockNumberPrior == currentBlockNumber) { - return uint(Error.NO_ERROR); + return NO_ERROR; } /* Read the previous values out of storage */ @@ -402,8 +345,7 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { require(borrowRateMantissa <= borrowRateMaxMantissa, "borrow rate is absurdly high"); /* Calculate the number of blocks elapsed since the last accrual */ - (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior); - require(mathErr == MathError.NO_ERROR, "could not calculate block delta"); + uint blockDelta = currentBlockNumber - accrualBlockNumberPrior; /* * Calculate the interest accumulated into borrows and reserves and the new index: @@ -414,36 +356,11 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex */ - Exp memory simpleInterestFactor; - uint interestAccumulated; - uint totalBorrowsNew; - uint totalReservesNew; - uint borrowIndexNew; - - (mathErr, simpleInterestFactor) = mulScalar(Exp({mantissa: borrowRateMantissa}), blockDelta); - if (mathErr != MathError.NO_ERROR) { - return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED, uint(mathErr)); - } - - (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior); - if (mathErr != MathError.NO_ERROR) { - return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED, uint(mathErr)); - } - - (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior); - if (mathErr != MathError.NO_ERROR) { - return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED, uint(mathErr)); - } - - (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(Exp({mantissa: reserveFactorMantissa}), interestAccumulated, reservesPrior); - if (mathErr != MathError.NO_ERROR) { - return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED, uint(mathErr)); - } - - (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior); - if (mathErr != MathError.NO_ERROR) { - return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED, uint(mathErr)); - } + Exp memory simpleInterestFactor = mul_(Exp({mantissa: borrowRateMantissa}), blockDelta); + uint interestAccumulated = mul_ScalarTruncate(simpleInterestFactor, borrowsPrior); + uint totalBorrowsNew = interestAccumulated + borrowsPrior; + uint totalReservesNew = mul_ScalarTruncateAddUInt(Exp({mantissa: reserveFactorMantissa}), interestAccumulated, reservesPrior); + uint borrowIndexNew = mul_ScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior); ///////////////////////// // EFFECTS & INTERACTIONS @@ -458,33 +375,18 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { /* We emit an AccrueInterest event */ emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew); - return uint(Error.NO_ERROR); + return NO_ERROR; } /** * @notice Sender supplies assets into the market and receives cTokens in exchange * @dev Accrues interest whether or not the operation succeeds, unless reverted * @param mintAmount The amount of the underlying asset to supply - * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount. */ - function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) { - uint error = accrueInterest(); - if (error != uint(Error.NO_ERROR)) { - // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed - return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0); - } + function mintInternal(uint mintAmount) internal nonReentrant { + accrueInterest(); // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to - return mintFresh(msg.sender, mintAmount); - } - - struct MintLocalVars { - Error err; - MathError mathErr; - uint exchangeRateMantissa; - uint mintTokens; - uint totalSupplyNew; - uint accountTokensNew; - uint actualMintAmount; + mintFresh(msg.sender, mintAmount); } /** @@ -492,26 +394,20 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { * @dev Assumes interest has already been accrued up to the current block * @param minter The address of the account which is supplying the assets * @param mintAmount The amount of the underlying asset to supply - * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount. */ - function mintFresh(address minter, uint mintAmount) internal returns (uint, uint) { + function mintFresh(address minter, uint mintAmount) internal { /* Fail if mint not allowed */ uint allowed = comptroller.mintAllowed(address(this), minter, mintAmount); if (allowed != 0) { - return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0); + revert MintComptrollerRejection(allowed); } /* Verify market's block number equals current block number */ if (accrualBlockNumber != getBlockNumber()) { - return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0); + revert MintFreshnessCheck(); } - MintLocalVars memory vars; - - (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal(); - if (vars.mathErr != MathError.NO_ERROR) { - return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0); - } + Exp memory exchangeRate = Exp({mantissa: exchangeRateStoredInternal()}); ///////////////////////// // EFFECTS & INTERACTIONS @@ -525,82 +421,53 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { * in case of a fee. On success, the cToken holds an additional `actualMintAmount` * of cash. */ - vars.actualMintAmount = doTransferIn(minter, mintAmount); + uint actualMintAmount = doTransferIn(minter, mintAmount); /* * We get the current exchange rate and calculate the number of cTokens to be minted: * mintTokens = actualMintAmount / exchangeRate */ - (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(vars.actualMintAmount, Exp({mantissa: vars.exchangeRateMantissa})); - require(vars.mathErr == MathError.NO_ERROR, "MINT_EXCHANGE_CALCULATION_FAILED"); + uint mintTokens = div_(actualMintAmount, exchangeRate); /* * We calculate the new total supply of cTokens and minter token balance, checking for overflow: * totalSupplyNew = totalSupply + mintTokens * accountTokensNew = accountTokens[minter] + mintTokens + * And write them into storage */ - (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens); - require(vars.mathErr == MathError.NO_ERROR, "MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED"); - - (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens); - require(vars.mathErr == MathError.NO_ERROR, "MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED"); - - /* We write previously calculated values into storage */ - totalSupply = vars.totalSupplyNew; - accountTokens[minter] = vars.accountTokensNew; + totalSupply = totalSupply + mintTokens; + accountTokens[minter] = accountTokens[minter] + mintTokens; /* We emit a Mint event, and a Transfer event */ - emit Mint(minter, vars.actualMintAmount, vars.mintTokens); - emit Transfer(address(this), minter, vars.mintTokens); + emit Mint(minter, actualMintAmount, mintTokens); + emit Transfer(address(this), minter, mintTokens); /* We call the defense hook */ // unused function - // comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens); - - return (uint(Error.NO_ERROR), vars.actualMintAmount); + // comptroller.mintVerify(address(this), minter, actualMintAmount, mintTokens); } /** * @notice Sender redeems cTokens in exchange for the underlying asset * @dev Accrues interest whether or not the operation succeeds, unless reverted * @param redeemTokens The number of cTokens to redeem into underlying - * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ - function redeemInternal(uint redeemTokens) internal nonReentrant returns (uint) { - uint error = accrueInterest(); - if (error != uint(Error.NO_ERROR)) { - // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed - return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED); - } + function redeemInternal(uint redeemTokens) internal nonReentrant { + accrueInterest(); // redeemFresh emits redeem-specific logs on errors, so we don't need to - return redeemFresh(msg.sender, redeemTokens, 0); + redeemFresh(payable(msg.sender), redeemTokens, 0); } /** * @notice Sender redeems cTokens in exchange for a specified amount of underlying asset * @dev Accrues interest whether or not the operation succeeds, unless reverted * @param redeemAmount The amount of underlying to receive from redeeming cTokens - * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ - function redeemUnderlyingInternal(uint redeemAmount) internal nonReentrant returns (uint) { - uint error = accrueInterest(); - if (error != uint(Error.NO_ERROR)) { - // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed - return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED); - } + function redeemUnderlyingInternal(uint redeemAmount) internal nonReentrant { + accrueInterest(); // redeemFresh emits redeem-specific logs on errors, so we don't need to - return redeemFresh(msg.sender, 0, redeemAmount); - } - - struct RedeemLocalVars { - Error err; - MathError mathErr; - uint exchangeRateMantissa; - uint redeemTokens; - uint redeemAmount; - uint totalSupplyNew; - uint accountTokensNew; + redeemFresh(payable(msg.sender), 0, redeemAmount); } /** @@ -609,19 +476,15 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { * @param redeemer The address of the account which is redeeming the tokens * @param redeemTokensIn The number of cTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero) * @param redeemAmountIn The number of underlying tokens to receive from redeeming cTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero) - * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ - function redeemFresh(address payable redeemer, uint redeemTokensIn, uint redeemAmountIn) internal returns (uint) { + function redeemFresh(address payable redeemer, uint redeemTokensIn, uint redeemAmountIn) internal { require(redeemTokensIn == 0 || redeemAmountIn == 0, "one of redeemTokensIn or redeemAmountIn must be zero"); - RedeemLocalVars memory vars; - /* exchangeRate = invoke Exchange Rate Stored() */ - (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal(); - if (vars.mathErr != MathError.NO_ERROR) { - return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)); - } + Exp memory exchangeRate = Exp({mantissa: exchangeRateStoredInternal() }); + uint redeemTokens; + uint redeemAmount; /* If redeemTokensIn > 0: */ if (redeemTokensIn > 0) { /* @@ -629,154 +492,114 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { * redeemTokens = redeemTokensIn * redeemAmount = redeemTokensIn x exchangeRateCurrent */ - vars.redeemTokens = redeemTokensIn; - - (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(Exp({mantissa: vars.exchangeRateMantissa}), redeemTokensIn); - if (vars.mathErr != MathError.NO_ERROR) { - return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED, uint(vars.mathErr)); - } + redeemTokens = redeemTokensIn; + redeemAmount = mul_ScalarTruncate(exchangeRate, redeemTokensIn); } else { /* * We get the current exchange rate and calculate the amount to be redeemed: * redeemTokens = redeemAmountIn / exchangeRate * redeemAmount = redeemAmountIn */ - - (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(redeemAmountIn, Exp({mantissa: vars.exchangeRateMantissa})); - if (vars.mathErr != MathError.NO_ERROR) { - return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED, uint(vars.mathErr)); - } - - vars.redeemAmount = redeemAmountIn; + redeemTokens = div_(redeemAmountIn, exchangeRate); + redeemAmount = redeemAmountIn; } /* Fail if redeem not allowed */ - uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens); + uint allowed = comptroller.redeemAllowed(address(this), redeemer, redeemTokens); if (allowed != 0) { - return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REDEEM_COMPTROLLER_REJECTION, allowed); + revert RedeemComptrollerRejection(allowed); } /* Verify market's block number equals current block number */ if (accrualBlockNumber != getBlockNumber()) { - return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDEEM_FRESHNESS_CHECK); - } - - /* - * We calculate the new total supply and redeemer balance, checking for underflow: - * totalSupplyNew = totalSupply - redeemTokens - * accountTokensNew = accountTokens[redeemer] - redeemTokens - */ - (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens); - if (vars.mathErr != MathError.NO_ERROR) { - return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED, uint(vars.mathErr)); - } - - (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens); - if (vars.mathErr != MathError.NO_ERROR) { - return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED, uint(vars.mathErr)); + revert RedeemFreshnessCheck(); } /* Fail gracefully if protocol has insufficient cash */ - if (getCashPrior() < vars.redeemAmount) { - return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDEEM_TRANSFER_OUT_NOT_POSSIBLE); + if (getCashPrior() < redeemAmount) { + revert RedeemTransferOutNotPossible(); } ///////////////////////// // EFFECTS & INTERACTIONS // (No safe failures beyond this point) + + /* + * We write the previously calculated values into storage. + * Note: Avoid token reentrancy attacks by writing reduced supply before external transfer. + */ + totalSupply = totalSupply - redeemTokens; + accountTokens[redeemer] = accountTokens[redeemer] - redeemTokens; + /* * We invoke doTransferOut for the redeemer and the redeemAmount. * Note: The cToken must handle variations between ERC-20 and ETH underlying. * On success, the cToken has redeemAmount less of cash. * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred. */ - doTransferOut(redeemer, vars.redeemAmount); - - /* We write previously calculated values into storage */ - totalSupply = vars.totalSupplyNew; - accountTokens[redeemer] = vars.accountTokensNew; + doTransferOut(redeemer, redeemAmount); /* We emit a Transfer event, and a Redeem event */ - emit Transfer(redeemer, address(this), vars.redeemTokens); - emit Redeem(redeemer, vars.redeemAmount, vars.redeemTokens); + emit Transfer(redeemer, address(this), redeemTokens); + emit Redeem(redeemer, redeemAmount, redeemTokens); /* We call the defense hook */ - comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens); - - return uint(Error.NO_ERROR); + comptroller.redeemVerify(address(this), redeemer, redeemAmount, redeemTokens); } /** * @notice Sender borrows assets from the protocol to their own address * @param borrowAmount The amount of the underlying asset to borrow - * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ - function borrowInternal(uint borrowAmount) internal nonReentrant returns (uint) { - uint error = accrueInterest(); - if (error != uint(Error.NO_ERROR)) { - // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed - return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED); - } + function borrowInternal(uint borrowAmount) internal nonReentrant { + accrueInterest(); // borrowFresh emits borrow-specific logs on errors, so we don't need to - return borrowFresh(msg.sender, borrowAmount); - } - - struct BorrowLocalVars { - MathError mathErr; - uint accountBorrows; - uint accountBorrowsNew; - uint totalBorrowsNew; + borrowFresh(payable(msg.sender), borrowAmount); } /** * @notice Users borrow assets from the protocol to their own address * @param borrowAmount The amount of the underlying asset to borrow - * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ - function borrowFresh(address payable borrower, uint borrowAmount) internal returns (uint) { + function borrowFresh(address payable borrower, uint borrowAmount) internal { /* Fail if borrow not allowed */ uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount); if (allowed != 0) { - return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.BORROW_COMPTROLLER_REJECTION, allowed); + revert BorrowComptrollerRejection(allowed); } /* Verify market's block number equals current block number */ if (accrualBlockNumber != getBlockNumber()) { - return fail(Error.MARKET_NOT_FRESH, FailureInfo.BORROW_FRESHNESS_CHECK); + revert BorrowFreshnessCheck(); } /* Fail gracefully if protocol has insufficient underlying cash */ if (getCashPrior() < borrowAmount) { - return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.BORROW_CASH_NOT_AVAILABLE); + revert BorrowCashNotAvailable(); } - BorrowLocalVars memory vars; - /* * We calculate the new borrower and total borrow balances, failing on overflow: - * accountBorrowsNew = accountBorrows + borrowAmount + * accountBorrowNew = accountBorrow + borrowAmount * totalBorrowsNew = totalBorrows + borrowAmount */ - (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower); - if (vars.mathErr != MathError.NO_ERROR) { - return failOpaque(Error.MATH_ERROR, FailureInfo.BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED, uint(vars.mathErr)); - } - - (vars.mathErr, vars.accountBorrowsNew) = addUInt(vars.accountBorrows, borrowAmount); - if (vars.mathErr != MathError.NO_ERROR) { - return failOpaque(Error.MATH_ERROR, FailureInfo.BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED, uint(vars.mathErr)); - } - - (vars.mathErr, vars.totalBorrowsNew) = addUInt(totalBorrows, borrowAmount); - if (vars.mathErr != MathError.NO_ERROR) { - return failOpaque(Error.MATH_ERROR, FailureInfo.BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED, uint(vars.mathErr)); - } + uint accountBorrowsPrev = borrowBalanceStoredInternal(borrower); + uint accountBorrowsNew = accountBorrowsPrev + borrowAmount; + uint totalBorrowsNew = totalBorrows + borrowAmount; ///////////////////////// // EFFECTS & INTERACTIONS // (No safe failures beyond this point) + /* + * We write the previously calculated values into storage. + * Note: Avoid token reentrancy attacks by writing increased borrow before external transfer. + `*/ + accountBorrows[borrower].principal = accountBorrowsNew; + accountBorrows[borrower].interestIndex = borrowIndex; + totalBorrows = totalBorrowsNew; + /* * We invoke doTransferOut for the borrower and the borrowAmount. * Note: The cToken must handle variations between ERC-20 and ETH underlying. @@ -785,99 +608,55 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { */ doTransferOut(borrower, borrowAmount); - /* We write the previously calculated values into storage */ - accountBorrows[borrower].principal = vars.accountBorrowsNew; - accountBorrows[borrower].interestIndex = borrowIndex; - totalBorrows = vars.totalBorrowsNew; - /* We emit a Borrow event */ - emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew); - - /* We call the defense hook */ - // unused function - // comptroller.borrowVerify(address(this), borrower, borrowAmount); - - return uint(Error.NO_ERROR); + emit Borrow(borrower, borrowAmount, accountBorrowsNew, totalBorrowsNew); } /** * @notice Sender repays their own borrow - * @param repayAmount The amount to repay - * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount. + * @param repayAmount The amount to repay, or -1 for the full outstanding amount */ - function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) { - uint error = accrueInterest(); - if (error != uint(Error.NO_ERROR)) { - // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed - return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0); - } + function repayBorrowInternal(uint repayAmount) internal nonReentrant { + accrueInterest(); // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to - return repayBorrowFresh(msg.sender, msg.sender, repayAmount); + repayBorrowFresh(msg.sender, msg.sender, repayAmount); } /** * @notice Sender repays a borrow belonging to borrower * @param borrower the account with the debt being payed off - * @param repayAmount The amount to repay - * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount. + * @param repayAmount The amount to repay, or -1 for the full outstanding amount */ - function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) { - uint error = accrueInterest(); - if (error != uint(Error.NO_ERROR)) { - // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed - return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0); - } + function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant { + accrueInterest(); // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to - return repayBorrowFresh(msg.sender, borrower, repayAmount); - } - - struct RepayBorrowLocalVars { - Error err; - MathError mathErr; - uint repayAmount; - uint borrowerIndex; - uint accountBorrows; - uint accountBorrowsNew; - uint totalBorrowsNew; - uint actualRepayAmount; + repayBorrowFresh(msg.sender, borrower, repayAmount); } /** * @notice Borrows are repaid by another user (possibly the borrower). * @param payer the account paying off the borrow * @param borrower the account with the debt being payed off - * @param repayAmount the amount of undelrying tokens being returned - * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount. + * @param repayAmount the amount of underlying tokens being returned, or -1 for the full outstanding amount + * @return (uint) the actual repayment amount. */ - function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) { + function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint) { /* Fail if repayBorrow not allowed */ uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount); if (allowed != 0) { - return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed), 0); + revert RepayBorrowComptrollerRejection(allowed); } /* Verify market's block number equals current block number */ if (accrualBlockNumber != getBlockNumber()) { - return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0); + revert RepayBorrowFreshnessCheck(); } - RepayBorrowLocalVars memory vars; - - /* We remember the original borrowerIndex for verification purposes */ - vars.borrowerIndex = accountBorrows[borrower].interestIndex; - /* We fetch the amount the borrower owes, with accumulated interest */ - (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower); - if (vars.mathErr != MathError.NO_ERROR) { - return (failOpaque(Error.MATH_ERROR, FailureInfo.REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED, uint(vars.mathErr)), 0); - } + uint accountBorrowsPrev = borrowBalanceStoredInternal(borrower); /* If repayAmount == -1, repayAmount = accountBorrows */ - if (repayAmount == uint(-1)) { - vars.repayAmount = vars.accountBorrows; - } else { - vars.repayAmount = repayAmount; - } + uint repayAmountFinal = repayAmount == type(uint).max ? accountBorrowsPrev : repayAmount; ///////////////////////// // EFFECTS & INTERACTIONS @@ -890,32 +669,25 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred. * it returns the amount actually transferred, in case of a fee. */ - vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount); + uint actualRepayAmount = doTransferIn(payer, repayAmountFinal); /* * We calculate the new borrower and total borrow balances, failing on underflow: * accountBorrowsNew = accountBorrows - actualRepayAmount * totalBorrowsNew = totalBorrows - actualRepayAmount */ - (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount); - require(vars.mathErr == MathError.NO_ERROR, "REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED"); - - (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount); - require(vars.mathErr == MathError.NO_ERROR, "REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED"); + uint accountBorrowsNew = accountBorrowsPrev - actualRepayAmount; + uint totalBorrowsNew = totalBorrows - actualRepayAmount; /* We write the previously calculated values into storage */ - accountBorrows[borrower].principal = vars.accountBorrowsNew; + accountBorrows[borrower].principal = accountBorrowsNew; accountBorrows[borrower].interestIndex = borrowIndex; - totalBorrows = vars.totalBorrowsNew; + totalBorrows = totalBorrowsNew; /* We emit a RepayBorrow event */ - emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew); + emit RepayBorrow(payer, borrower, actualRepayAmount, accountBorrowsNew, totalBorrowsNew); - /* We call the defense hook */ - // unused function - // comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex); - - return (uint(Error.NO_ERROR), vars.actualRepayAmount); + return actualRepayAmount; } /** @@ -924,23 +696,18 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { * @param borrower The borrower of this cToken to be liquidated * @param cTokenCollateral The market in which to seize collateral from the borrower * @param repayAmount The amount of the underlying borrowed asset to repay - * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount. */ - function liquidateBorrowInternal(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) internal nonReentrant returns (uint, uint) { - uint error = accrueInterest(); - if (error != uint(Error.NO_ERROR)) { - // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed - return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED), 0); - } + function liquidateBorrowInternal(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) internal nonReentrant { + accrueInterest(); - error = cTokenCollateral.accrueInterest(); - if (error != uint(Error.NO_ERROR)) { + uint error = cTokenCollateral.accrueInterest(); + if (error != NO_ERROR) { // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed - return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0); + revert LiquidateAccrueCollateralInterestFailed(error); } // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to - return liquidateBorrowFresh(msg.sender, borrower, repayAmount, cTokenCollateral); + liquidateBorrowFresh(msg.sender, borrower, repayAmount, cTokenCollateral); } /** @@ -950,46 +717,41 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { * @param liquidator The address repaying the borrow and seizing collateral * @param cTokenCollateral The market in which to seize collateral from the borrower * @param repayAmount The amount of the underlying borrowed asset to repay - * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount. */ - function liquidateBorrowFresh(address liquidator, address borrower, uint repayAmount, CTokenInterface cTokenCollateral) internal returns (uint, uint) { + function liquidateBorrowFresh(address liquidator, address borrower, uint repayAmount, CTokenInterface cTokenCollateral) internal { /* Fail if liquidate not allowed */ uint allowed = comptroller.liquidateBorrowAllowed(address(this), address(cTokenCollateral), liquidator, borrower, repayAmount); if (allowed != 0) { - return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0); + revert LiquidateComptrollerRejection(allowed); } /* Verify market's block number equals current block number */ if (accrualBlockNumber != getBlockNumber()) { - return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0); + revert LiquidateFreshnessCheck(); } /* Verify cTokenCollateral market's block number equals current block number */ if (cTokenCollateral.accrualBlockNumber() != getBlockNumber()) { - return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0); + revert LiquidateCollateralFreshnessCheck(); } /* Fail if borrower = liquidator */ if (borrower == liquidator) { - return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0); + revert LiquidateLiquidatorIsBorrower(); } /* Fail if repayAmount = 0 */ if (repayAmount == 0) { - return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0); + revert LiquidateCloseAmountIsZero(); } /* Fail if repayAmount = -1 */ - if (repayAmount == uint(-1)) { - return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0); + if (repayAmount == type(uint).max) { + revert LiquidateCloseAmountIsUintMax(); } - /* Fail if repayBorrow fails */ - (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount); - if (repayBorrowError != uint(Error.NO_ERROR)) { - return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0); - } + uint actualRepayAmount = repayBorrowFresh(liquidator, borrower, repayAmount); ///////////////////////// // EFFECTS & INTERACTIONS @@ -997,30 +759,20 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { /* We calculate the number of collateral tokens that will be seized */ (uint amountSeizeError, uint seizeTokens) = comptroller.liquidateCalculateSeizeTokens(address(this), address(cTokenCollateral), actualRepayAmount); - require(amountSeizeError == uint(Error.NO_ERROR), "LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED"); + require(amountSeizeError == NO_ERROR, "LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED"); /* Revert if borrower collateral token balance < seizeTokens */ require(cTokenCollateral.balanceOf(borrower) >= seizeTokens, "LIQUIDATE_SEIZE_TOO_MUCH"); // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call - uint seizeError; if (address(cTokenCollateral) == address(this)) { - seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens); + seizeInternal(address(this), liquidator, borrower, seizeTokens); } else { - seizeError = cTokenCollateral.seize(liquidator, borrower, seizeTokens); + require(cTokenCollateral.seize(liquidator, borrower, seizeTokens) == NO_ERROR, "token seizure failed"); } - /* Revert if seize tokens fails (since we cannot be sure of side effects) */ - require(seizeError == uint(Error.NO_ERROR), "token seizure failed"); - /* We emit a LiquidateBorrow event */ emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(cTokenCollateral), seizeTokens); - - /* We call the defense hook */ - // unused function - // comptroller.liquidateBorrowVerify(address(this), address(cTokenCollateral), liquidator, borrower, actualRepayAmount, seizeTokens); - - return (uint(Error.NO_ERROR), actualRepayAmount); } /** @@ -1032,20 +784,10 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { * @param seizeTokens The number of cTokens to seize * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ - function seize(address liquidator, address borrower, uint seizeTokens) external nonReentrant returns (uint) { - return seizeInternal(msg.sender, liquidator, borrower, seizeTokens); - } + function seize(address liquidator, address borrower, uint seizeTokens) override external nonReentrant returns (uint) { + seizeInternal(msg.sender, liquidator, borrower, seizeTokens); - struct SeizeInternalLocalVars { - MathError mathErr; - uint borrowerTokensNew; - uint liquidatorTokensNew; - uint liquidatorSeizeTokens; - uint protocolSeizeTokens; - uint protocolSeizeAmount; - uint exchangeRateMantissa; - uint totalReservesNew; - uint totalSupplyNew; + return NO_ERROR; } /** @@ -1056,68 +798,45 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { * @param liquidator The account receiving seized collateral * @param borrower The account having collateral seized * @param seizeTokens The number of cTokens to seize - * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ - function seizeInternal(address seizerToken, address liquidator, address borrower, uint seizeTokens) internal returns (uint) { + function seizeInternal(address seizerToken, address liquidator, address borrower, uint seizeTokens) internal { /* Fail if seize not allowed */ uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens); if (allowed != 0) { - return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed); + revert LiquidateSeizeComptrollerRejection(allowed); } /* Fail if borrower = liquidator */ if (borrower == liquidator) { - return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER); + revert LiquidateSeizeLiquidatorIsBorrower(); } - SeizeInternalLocalVars memory vars; - /* * We calculate the new borrower and liquidator token balances, failing on underflow/overflow: * borrowerTokensNew = accountTokens[borrower] - seizeTokens * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens */ - (vars.mathErr, vars.borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens); - if (vars.mathErr != MathError.NO_ERROR) { - return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(vars.mathErr)); - } + uint protocolSeizeTokens = mul_(seizeTokens, Exp({mantissa: protocolSeizeShareMantissa})); + uint liquidatorSeizeTokens = seizeTokens - protocolSeizeTokens; + Exp memory exchangeRate = Exp({mantissa: exchangeRateStoredInternal()}); + uint protocolSeizeAmount = mul_ScalarTruncate(exchangeRate, protocolSeizeTokens); + uint totalReservesNew = totalReserves + protocolSeizeAmount; - vars.protocolSeizeTokens = mul_(seizeTokens, Exp({mantissa: protocolSeizeShareMantissa})); - vars.liquidatorSeizeTokens = sub_(seizeTokens, vars.protocolSeizeTokens); - - (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal(); - require(vars.mathErr == MathError.NO_ERROR, "exchange rate math error"); - - vars.protocolSeizeAmount = mul_ScalarTruncate(Exp({mantissa: vars.exchangeRateMantissa}), vars.protocolSeizeTokens); - - vars.totalReservesNew = add_(totalReserves, vars.protocolSeizeAmount); - vars.totalSupplyNew = sub_(totalSupply, vars.protocolSeizeTokens); - - (vars.mathErr, vars.liquidatorTokensNew) = addUInt(accountTokens[liquidator], vars.liquidatorSeizeTokens); - if (vars.mathErr != MathError.NO_ERROR) { - return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(vars.mathErr)); - } ///////////////////////// // EFFECTS & INTERACTIONS // (No safe failures beyond this point) - /* We write the previously calculated values into storage */ - totalReserves = vars.totalReservesNew; - totalSupply = vars.totalSupplyNew; - accountTokens[borrower] = vars.borrowerTokensNew; - accountTokens[liquidator] = vars.liquidatorTokensNew; + /* We write the calculated values into storage */ + totalReserves = totalReservesNew; + totalSupply = totalSupply - protocolSeizeTokens; + accountTokens[borrower] = accountTokens[borrower] - seizeTokens; + accountTokens[liquidator] = accountTokens[liquidator] + liquidatorSeizeTokens; /* Emit a Transfer event */ - emit Transfer(borrower, liquidator, vars.liquidatorSeizeTokens); - emit Transfer(borrower, address(this), vars.protocolSeizeTokens); - emit ReservesAdded(address(this), vars.protocolSeizeAmount, vars.totalReservesNew); - - /* We call the defense hook */ - // unused function - // comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens); - - return uint(Error.NO_ERROR); + emit Transfer(borrower, liquidator, liquidatorSeizeTokens); + emit Transfer(borrower, address(this), protocolSeizeTokens); + emit ReservesAdded(address(this), protocolSeizeAmount, totalReservesNew); } @@ -1129,10 +848,10 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { * @param newPendingAdmin New pending admin. * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ - function _setPendingAdmin(address payable newPendingAdmin) external returns (uint) { + function _setPendingAdmin(address payable newPendingAdmin) override external returns (uint) { // Check caller = admin if (msg.sender != admin) { - return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK); + revert SetPendingAdminOwnerCheck(); } // Save current value, if any, for inclusion in log @@ -1144,7 +863,7 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin) emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin); - return uint(Error.NO_ERROR); + return NO_ERROR; } /** @@ -1152,10 +871,10 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { * @dev Admin function for pending admin to accept role and update admin * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ - function _acceptAdmin() external returns (uint) { + function _acceptAdmin() override external returns (uint) { // Check caller is pendingAdmin and pendingAdmin ≠ address(0) if (msg.sender != pendingAdmin || msg.sender == address(0)) { - return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK); + revert AcceptAdminPendingAdminCheck(); } // Save current values for inclusion in log @@ -1166,12 +885,12 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { admin = pendingAdmin; // Clear the pending value - pendingAdmin = address(0); + pendingAdmin = payable(address(0)); emit NewAdmin(oldAdmin, admin); emit NewPendingAdmin(oldPendingAdmin, pendingAdmin); - return uint(Error.NO_ERROR); + return NO_ERROR; } /** @@ -1179,10 +898,10 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { * @dev Admin function to set a new comptroller * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ - function _setComptroller(ComptrollerInterface newComptroller) public returns (uint) { + function _setComptroller(ComptrollerInterface newComptroller) override public returns (uint) { // Check caller is admin if (msg.sender != admin) { - return fail(Error.UNAUTHORIZED, FailureInfo.SET_COMPTROLLER_OWNER_CHECK); + revert SetComptrollerOwnerCheck(); } ComptrollerInterface oldComptroller = comptroller; @@ -1195,7 +914,7 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { // Emit NewComptroller(oldComptroller, newComptroller) emit NewComptroller(oldComptroller, newComptroller); - return uint(Error.NO_ERROR); + return NO_ERROR; } /** @@ -1203,12 +922,8 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { * @dev Admin function to accrue interest and set a new reserve factor * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ - function _setReserveFactor(uint newReserveFactorMantissa) external nonReentrant returns (uint) { - uint error = accrueInterest(); - if (error != uint(Error.NO_ERROR)) { - // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed. - return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED); - } + function _setReserveFactor(uint newReserveFactorMantissa) override external nonReentrant returns (uint) { + accrueInterest(); // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to. return _setReserveFactorFresh(newReserveFactorMantissa); } @@ -1221,17 +936,17 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) { // Check caller is admin if (msg.sender != admin) { - return fail(Error.UNAUTHORIZED, FailureInfo.SET_RESERVE_FACTOR_ADMIN_CHECK); + revert SetReserveFactorAdminCheck(); } // Verify market's block number equals current block number if (accrualBlockNumber != getBlockNumber()) { - return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK); + revert SetReserveFactorFreshCheck(); } // Check newReserveFactor ≤ maxReserveFactor if (newReserveFactorMantissa > reserveFactorMaxMantissa) { - return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK); + revert SetReserveFactorBoundsCheck(); } uint oldReserveFactorMantissa = reserveFactorMantissa; @@ -1239,7 +954,7 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa); - return uint(Error.NO_ERROR); + return NO_ERROR; } /** @@ -1248,15 +963,11 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) { - uint error = accrueInterest(); - if (error != uint(Error.NO_ERROR)) { - // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed. - return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED); - } + accrueInterest(); // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to. - (error, ) = _addReservesFresh(addAmount); - return error; + _addReservesFresh(addAmount); + return NO_ERROR; } /** @@ -1272,7 +983,7 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { // We fail gracefully unless market's block number equals current block number if (accrualBlockNumber != getBlockNumber()) { - return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount); + revert AddReservesFactorFreshCheck(actualAddAmount); } ///////////////////////// @@ -1291,9 +1002,6 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { totalReservesNew = totalReserves + actualAddAmount; - /* Revert on overflow */ - require(totalReservesNew >= totalReserves, "add reserves unexpected overflow"); - // Store reserves[n+1] = reserves[n] + actualAddAmount totalReserves = totalReservesNew; @@ -1301,7 +1009,7 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew); /* Return (NO_ERROR, actualAddAmount) */ - return (uint(Error.NO_ERROR), actualAddAmount); + return (NO_ERROR, actualAddAmount); } @@ -1310,12 +1018,8 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { * @param reduceAmount Amount of reduction to reserves * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ - function _reduceReserves(uint reduceAmount) external nonReentrant returns (uint) { - uint error = accrueInterest(); - if (error != uint(Error.NO_ERROR)) { - // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed. - return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED); - } + function _reduceReserves(uint reduceAmount) override external nonReentrant returns (uint) { + accrueInterest(); // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to. return _reduceReservesFresh(reduceAmount); } @@ -1332,22 +1036,22 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { // Check caller is admin if (msg.sender != admin) { - return fail(Error.UNAUTHORIZED, FailureInfo.REDUCE_RESERVES_ADMIN_CHECK); + revert ReduceReservesAdminCheck(); } // We fail gracefully unless market's block number equals current block number if (accrualBlockNumber != getBlockNumber()) { - return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK); + revert ReduceReservesFreshCheck(); } // Fail gracefully if protocol has insufficient underlying cash if (getCashPrior() < reduceAmount) { - return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE); + revert ReduceReservesCashNotAvailable(); } // Check reduceAmount ≤ reserves[n] (totalReserves) if (reduceAmount > totalReserves) { - return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION); + revert ReduceReservesCashValidation(); } ///////////////////////// @@ -1355,8 +1059,6 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { // (No safe failures beyond this point) totalReservesNew = totalReserves - reduceAmount; - // We checked reduceAmount <= totalReserves above, so this should never revert. - require(totalReservesNew <= totalReserves, "reduce reserves unexpected underflow"); // Store reserves[n+1] = reserves[n] - reduceAmount totalReserves = totalReservesNew; @@ -1366,7 +1068,7 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { emit ReservesReduced(admin, reduceAmount, totalReservesNew); - return uint(Error.NO_ERROR); + return NO_ERROR; } /** @@ -1375,12 +1077,8 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { * @param newInterestRateModel the new interest rate model to use * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ - function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint) { - uint error = accrueInterest(); - if (error != uint(Error.NO_ERROR)) { - // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed - return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED); - } + function _setInterestRateModel(InterestRateModel newInterestRateModel) override public returns (uint) { + accrueInterest(); // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to. return _setInterestRateModelFresh(newInterestRateModel); } @@ -1398,12 +1096,12 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { // Check caller is admin if (msg.sender != admin) { - return fail(Error.UNAUTHORIZED, FailureInfo.SET_INTEREST_RATE_MODEL_OWNER_CHECK); + revert SetInterestRateModelOwnerCheck(); } // We fail gracefully unless market's block number equals current block number if (accrualBlockNumber != getBlockNumber()) { - return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK); + revert SetInterestRateModelFreshCheck(); } // Track the market's current interest rate model @@ -1418,7 +1116,7 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel) emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel); - return uint(Error.NO_ERROR); + return NO_ERROR; } /*** Safe Token ***/ @@ -1428,20 +1126,20 @@ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { * @dev This excludes the value of the current message, if any * @return The quantity of underlying owned by this contract */ - function getCashPrior() internal view returns (uint); + function getCashPrior() virtual internal view returns (uint); /** * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee. * This may revert due to insufficient balance or insufficient allowance. */ - function doTransferIn(address from, uint amount) internal returns (uint); + function doTransferIn(address from, uint amount) virtual internal returns (uint); /** - * @dev Performs a transfer out, ideally returning an explanatory error code upon failure tather than reverting. + * @dev Performs a transfer out, ideally returning an explanatory error code upon failure rather than reverting. * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract. * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions. */ - function doTransferOut(address payable to, uint amount) internal; + function doTransferOut(address payable to, uint amount) virtual internal; /*** Reentrancy Guard ***/ diff --git a/contracts/CTokenInterfaces.sol b/contracts/CTokenInterfaces.sol index 7dd80621c..ba8d69a00 100644 --- a/contracts/CTokenInterfaces.sol +++ b/contracts/CTokenInterfaces.sol @@ -1,8 +1,10 @@ -pragma solidity ^0.5.16; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; import "./ComptrollerInterface.sol"; import "./InterestRateModel.sol"; import "./EIP20NonStandardInterface.sol"; +import "./ErrorReporter.sol"; contract CTokenStorage { /** @@ -25,15 +27,10 @@ contract CTokenStorage { */ uint8 public decimals; - /** - * @notice Maximum borrow rate that can ever be applied (.0005% / block) - */ - + // Maximum borrow rate that can ever be applied (.0005% / block) uint internal constant borrowRateMaxMantissa = 0.0005e16; - /** - * @notice Maximum fraction of interest that can be set aside for reserves - */ + // Maximum fraction of interest that can be set aside for reserves uint internal constant reserveFactorMaxMantissa = 1e18; /** @@ -56,9 +53,7 @@ contract CTokenStorage { */ InterestRateModel public interestRateModel; - /** - * @notice Initial exchange rate used when minting the first CTokens (used when totalSupply = 0) - */ + // Initial exchange rate used when minting the first CTokens (used when totalSupply = 0) uint internal initialExchangeRateMantissa; /** @@ -91,14 +86,10 @@ contract CTokenStorage { */ uint public totalSupply; - /** - * @notice Official record of token balances for each account - */ + // Official record of token balances for each account mapping (address => uint) internal accountTokens; - /** - * @notice Approved token transfer amounts on behalf of others - */ + // Approved token transfer amounts on behalf of others mapping (address => mapping (address => uint)) internal transferAllowances; /** @@ -111,19 +102,16 @@ contract CTokenStorage { uint interestIndex; } - /** - * @notice Mapping of account addresses to outstanding borrow balances - */ + // Mapping of account addresses to outstanding borrow balances mapping(address => BorrowSnapshot) internal accountBorrows; /** * @notice Share of seized collateral that is added to reserves */ uint public constant protocolSeizeShareMantissa = 2.8e16; //2.8% - } -contract CTokenInterface is CTokenStorage { +abstract contract CTokenInterface is CTokenStorage { /** * @notice Indicator that this is a CToken contract (for inspection) */ @@ -210,41 +198,36 @@ contract CTokenInterface is CTokenStorage { */ event Approval(address indexed owner, address indexed spender, uint amount); - /** - * @notice Failure event - */ - event Failure(uint error, uint info, uint detail); - /*** User Interface ***/ - function transfer(address dst, uint amount) external returns (bool); - function transferFrom(address src, address dst, uint amount) external returns (bool); - function approve(address spender, uint amount) external returns (bool); - function allowance(address owner, address spender) external view returns (uint); - function balanceOf(address owner) external view returns (uint); - function balanceOfUnderlying(address owner) external returns (uint); - function getAccountSnapshot(address account) external view returns (uint, uint, uint, uint); - function borrowRatePerBlock() external view returns (uint); - function supplyRatePerBlock() external view returns (uint); - function totalBorrowsCurrent() external returns (uint); - function borrowBalanceCurrent(address account) external returns (uint); - function borrowBalanceStored(address account) public view returns (uint); - function exchangeRateCurrent() public returns (uint); - function exchangeRateStored() public view returns (uint); - function getCash() external view returns (uint); - function accrueInterest() public returns (uint); - function seize(address liquidator, address borrower, uint seizeTokens) external returns (uint); + function transfer(address dst, uint amount) virtual external returns (bool); + function transferFrom(address src, address dst, uint amount) virtual external returns (bool); + function approve(address spender, uint amount) virtual external returns (bool); + function allowance(address owner, address spender) virtual external view returns (uint); + function balanceOf(address owner) virtual external view returns (uint); + function balanceOfUnderlying(address owner) virtual external returns (uint); + function getAccountSnapshot(address account) virtual external view returns (uint, uint, uint, uint); + function borrowRatePerBlock() virtual external view returns (uint); + function supplyRatePerBlock() virtual external view returns (uint); + function totalBorrowsCurrent() virtual external returns (uint); + function borrowBalanceCurrent(address account) virtual external returns (uint); + function borrowBalanceStored(address account) virtual external view returns (uint); + function exchangeRateCurrent() virtual external returns (uint); + function exchangeRateStored() virtual external view returns (uint); + function getCash() virtual external view returns (uint); + function accrueInterest() virtual external returns (uint); + function seize(address liquidator, address borrower, uint seizeTokens) virtual external returns (uint); /*** Admin Functions ***/ - function _setPendingAdmin(address payable newPendingAdmin) external returns (uint); - function _acceptAdmin() external returns (uint); - function _setComptroller(ComptrollerInterface newComptroller) public returns (uint); - function _setReserveFactor(uint newReserveFactorMantissa) external returns (uint); - function _reduceReserves(uint reduceAmount) external returns (uint); - function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint); + function _setPendingAdmin(address payable newPendingAdmin) virtual external returns (uint); + function _acceptAdmin() virtual external returns (uint); + function _setComptroller(ComptrollerInterface newComptroller) virtual external returns (uint); + function _setReserveFactor(uint newReserveFactorMantissa) virtual external returns (uint); + function _reduceReserves(uint reduceAmount) virtual external returns (uint); + function _setInterestRateModel(InterestRateModel newInterestRateModel) virtual external returns (uint); } contract CErc20Storage { @@ -254,23 +237,23 @@ contract CErc20Storage { address public underlying; } -contract CErc20Interface is CErc20Storage { +abstract contract CErc20Interface is CErc20Storage { /*** User Interface ***/ - function mint(uint mintAmount) external returns (uint); - function redeem(uint redeemTokens) external returns (uint); - function redeemUnderlying(uint redeemAmount) external returns (uint); - function borrow(uint borrowAmount) external returns (uint); - function repayBorrow(uint repayAmount) external returns (uint); - function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint); - function liquidateBorrow(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) external returns (uint); - function sweepToken(EIP20NonStandardInterface token) external; + function mint(uint mintAmount) virtual external returns (uint); + function redeem(uint redeemTokens) virtual external returns (uint); + function redeemUnderlying(uint redeemAmount) virtual external returns (uint); + function borrow(uint borrowAmount) virtual external returns (uint); + function repayBorrow(uint repayAmount) virtual external returns (uint); + function repayBorrowBehalf(address borrower, uint repayAmount) virtual external returns (uint); + function liquidateBorrow(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) virtual external returns (uint); + function sweepToken(EIP20NonStandardInterface token) virtual external; /*** Admin Functions ***/ - function _addReserves(uint addAmount) external returns (uint); + function _addReserves(uint addAmount) virtual external returns (uint); } contract CDelegationStorage { @@ -280,7 +263,7 @@ contract CDelegationStorage { address public implementation; } -contract CDelegatorInterface is CDelegationStorage { +abstract contract CDelegatorInterface is CDelegationStorage { /** * @notice Emitted when implementation is changed */ @@ -292,19 +275,19 @@ contract CDelegatorInterface is CDelegationStorage { * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation */ - function _setImplementation(address implementation_, bool allowResign, bytes memory becomeImplementationData) public; + function _setImplementation(address implementation_, bool allowResign, bytes memory becomeImplementationData) virtual external; } -contract CDelegateInterface is CDelegationStorage { +abstract contract CDelegateInterface is CDelegationStorage { /** * @notice Called by the delegator on a delegate to initialize it for duty * @dev Should revert if any issues arise which make it unfit for delegation * @param data The encoded bytes data for any initialization */ - function _becomeImplementation(bytes memory data) public; + function _becomeImplementation(bytes memory data) virtual external; /** * @notice Called by the delegator on a delegate to forfeit its responsibility */ - function _resignImplementation() public; + function _resignImplementation() virtual external; } diff --git a/contracts/CarefulMath.sol b/contracts/CarefulMath.sol deleted file mode 100644 index 4f5be2ebe..000000000 --- a/contracts/CarefulMath.sol +++ /dev/null @@ -1,85 +0,0 @@ -pragma solidity ^0.5.16; - -/** - * @title Careful Math - * @author Compound - * @notice Derived from OpenZeppelin's SafeMath library - * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol - */ -contract CarefulMath { - - /** - * @dev Possible error codes that we can return - */ - enum MathError { - NO_ERROR, - DIVISION_BY_ZERO, - INTEGER_OVERFLOW, - INTEGER_UNDERFLOW - } - - /** - * @dev Multiplies two numbers, returns an error on overflow. - */ - function mulUInt(uint a, uint b) internal pure returns (MathError, uint) { - if (a == 0) { - return (MathError.NO_ERROR, 0); - } - - uint c = a * b; - - if (c / a != b) { - return (MathError.INTEGER_OVERFLOW, 0); - } else { - return (MathError.NO_ERROR, c); - } - } - - /** - * @dev Integer division of two numbers, truncating the quotient. - */ - function divUInt(uint a, uint b) internal pure returns (MathError, uint) { - if (b == 0) { - return (MathError.DIVISION_BY_ZERO, 0); - } - - return (MathError.NO_ERROR, a / b); - } - - /** - * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend). - */ - function subUInt(uint a, uint b) internal pure returns (MathError, uint) { - if (b <= a) { - return (MathError.NO_ERROR, a - b); - } else { - return (MathError.INTEGER_UNDERFLOW, 0); - } - } - - /** - * @dev Adds two numbers, returns an error on overflow. - */ - function addUInt(uint a, uint b) internal pure returns (MathError, uint) { - uint c = a + b; - - if (c >= a) { - return (MathError.NO_ERROR, c); - } else { - return (MathError.INTEGER_OVERFLOW, 0); - } - } - - /** - * @dev add a and b and then subtract c - */ - function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) { - (MathError err0, uint sum) = addUInt(a, b); - - if (err0 != MathError.NO_ERROR) { - return (err0, 0); - } - - return subUInt(sum, c); - } -} \ No newline at end of file diff --git a/contracts/Comptroller.sol b/contracts/Comptroller.sol index 4399c3f61..1d94cc756 100644 --- a/contracts/Comptroller.sol +++ b/contracts/Comptroller.sol @@ -1,4 +1,5 @@ -pragma solidity ^0.5.16; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; import "./CToken.sol"; import "./ErrorReporter.sol"; @@ -85,7 +86,7 @@ contract Comptroller is ComptrollerV7Storage, ComptrollerInterface, ComptrollerE // No collateralFactorMantissa may exceed this value uint internal constant collateralFactorMaxMantissa = 0.9e18; // 0.9 - constructor() public { + constructor() { admin = msg.sender; } @@ -117,7 +118,7 @@ contract Comptroller is ComptrollerV7Storage, ComptrollerInterface, ComptrollerE * @param cTokens The list of addresses of the cToken markets to be enabled * @return Success indicator for whether each corresponding market was entered */ - function enterMarkets(address[] memory cTokens) public returns (uint[] memory) { + function enterMarkets(address[] memory cTokens) override public returns (uint[] memory) { uint len = cTokens.length; uint[] memory results = new uint[](len); @@ -169,7 +170,7 @@ contract Comptroller is ComptrollerV7Storage, ComptrollerInterface, ComptrollerE * @param cTokenAddress The address of the asset to be removed * @return Whether or not the account successfully exited the market */ - function exitMarket(address cTokenAddress) external returns (uint) { + function exitMarket(address cTokenAddress) override external returns (uint) { CToken cToken = CToken(cTokenAddress); /* Get sender tokensHeld and amountOwed underlying from the cToken */ (uint oErr, uint tokensHeld, uint amountOwed, ) = cToken.getAccountSnapshot(msg.sender); @@ -214,7 +215,7 @@ contract Comptroller is ComptrollerV7Storage, ComptrollerInterface, ComptrollerE // copy last item in list to location of item to be removed, reduce length by 1 CToken[] storage storedList = accountAssets[msg.sender]; storedList[assetIndex] = storedList[storedList.length - 1]; - storedList.length--; + storedList.pop(); emit MarketExited(cToken, msg.sender); @@ -230,7 +231,7 @@ contract Comptroller is ComptrollerV7Storage, ComptrollerInterface, ComptrollerE * @param mintAmount The amount of underlying being supplied to the market in exchange for tokens * @return 0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol) */ - function mintAllowed(address cToken, address minter, uint mintAmount) external returns (uint) { + function mintAllowed(address cToken, address minter, uint mintAmount) override external returns (uint) { // Pausing is a very serious situation - we revert to sound the alarms require(!mintGuardianPaused[cToken], "mint is paused"); @@ -256,7 +257,7 @@ contract Comptroller is ComptrollerV7Storage, ComptrollerInterface, ComptrollerE * @param actualMintAmount The amount of the underlying asset being minted * @param mintTokens The number of tokens being minted */ - function mintVerify(address cToken, address minter, uint actualMintAmount, uint mintTokens) external { + function mintVerify(address cToken, address minter, uint actualMintAmount, uint mintTokens) override external { // Shh - currently unused cToken; minter; @@ -276,7 +277,7 @@ contract Comptroller is ComptrollerV7Storage, ComptrollerInterface, ComptrollerE * @param redeemTokens The number of cTokens to exchange for the underlying asset in the market * @return 0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol) */ - function redeemAllowed(address cToken, address redeemer, uint redeemTokens) external returns (uint) { + function redeemAllowed(address cToken, address redeemer, uint redeemTokens) override external returns (uint) { uint allowed = redeemAllowedInternal(cToken, redeemer, redeemTokens); if (allowed != uint(Error.NO_ERROR)) { return allowed; @@ -318,7 +319,7 @@ contract Comptroller is ComptrollerV7Storage, ComptrollerInterface, ComptrollerE * @param redeemAmount The amount of the underlying asset being redeemed * @param redeemTokens The number of tokens being redeemed */ - function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) external { + function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) override external { // Shh - currently unused cToken; redeemer; @@ -336,7 +337,7 @@ contract Comptroller is ComptrollerV7Storage, ComptrollerInterface, ComptrollerE * @param borrowAmount The amount of underlying the account would borrow * @return 0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol) */ - function borrowAllowed(address cToken, address borrower, uint borrowAmount) external returns (uint) { + function borrowAllowed(address cToken, address borrower, uint borrowAmount) override external returns (uint) { // Pausing is a very serious situation - we revert to sound the alarms require(!borrowGuardianPaused[cToken], "borrow is paused"); @@ -393,7 +394,7 @@ contract Comptroller is ComptrollerV7Storage, ComptrollerInterface, ComptrollerE * @param borrower The address borrowing the underlying * @param borrowAmount The amount of the underlying asset requested to borrow */ - function borrowVerify(address cToken, address borrower, uint borrowAmount) external { + function borrowVerify(address cToken, address borrower, uint borrowAmount) override external { // Shh - currently unused cToken; borrower; @@ -417,7 +418,7 @@ contract Comptroller is ComptrollerV7Storage, ComptrollerInterface, ComptrollerE address cToken, address payer, address borrower, - uint repayAmount) external returns (uint) { + uint repayAmount) override external returns (uint) { // Shh - currently unused payer; borrower; @@ -447,7 +448,7 @@ contract Comptroller is ComptrollerV7Storage, ComptrollerInterface, ComptrollerE address payer, address borrower, uint actualRepayAmount, - uint borrowerIndex) external { + uint borrowerIndex) override external { // Shh - currently unused cToken; payer; @@ -474,7 +475,7 @@ contract Comptroller is ComptrollerV7Storage, ComptrollerInterface, ComptrollerE address cTokenCollateral, address liquidator, address borrower, - uint repayAmount) external returns (uint) { + uint repayAmount) override external returns (uint) { // Shh - currently unused liquidator; @@ -521,7 +522,7 @@ contract Comptroller is ComptrollerV7Storage, ComptrollerInterface, ComptrollerE address liquidator, address borrower, uint actualRepayAmount, - uint seizeTokens) external { + uint seizeTokens) override external { // Shh - currently unused cTokenBorrowed; cTokenCollateral; @@ -549,7 +550,7 @@ contract Comptroller is ComptrollerV7Storage, ComptrollerInterface, ComptrollerE address cTokenBorrowed, address liquidator, address borrower, - uint seizeTokens) external returns (uint) { + uint seizeTokens) override external returns (uint) { // Pausing is a very serious situation - we revert to sound the alarms require(!seizeGuardianPaused, "seize is paused"); @@ -585,7 +586,7 @@ contract Comptroller is ComptrollerV7Storage, ComptrollerInterface, ComptrollerE address cTokenBorrowed, address liquidator, address borrower, - uint seizeTokens) external { + uint seizeTokens) override external { // Shh - currently unused cTokenCollateral; cTokenBorrowed; @@ -607,7 +608,7 @@ contract Comptroller is ComptrollerV7Storage, ComptrollerInterface, ComptrollerE * @param transferTokens The number of cTokens to transfer * @return 0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol) */ - function transferAllowed(address cToken, address src, address dst, uint transferTokens) external returns (uint) { + function transferAllowed(address cToken, address src, address dst, uint transferTokens) override external returns (uint) { // Pausing is a very serious situation - we revert to sound the alarms require(!transferGuardianPaused, "transfer is paused"); @@ -633,7 +634,7 @@ contract Comptroller is ComptrollerV7Storage, ComptrollerInterface, ComptrollerE * @param dst The account which receives the tokens * @param transferTokens The number of cTokens to transfer */ - function transferVerify(address cToken, address src, address dst, uint transferTokens) external { + function transferVerify(address cToken, address src, address dst, uint transferTokens) override external { // Shh - currently unused cToken; src; @@ -673,7 +674,7 @@ contract Comptroller is ComptrollerV7Storage, ComptrollerInterface, ComptrollerE * account shortfall below collateral requirements) */ function getAccountLiquidity(address account) public view returns (uint, uint, uint) { - (Error err, uint liquidity, uint shortfall) = getHypotheticalAccountLiquidityInternal(account, CToken(0), 0, 0); + (Error err, uint liquidity, uint shortfall) = getHypotheticalAccountLiquidityInternal(account, CToken(address(0)), 0, 0); return (uint(err), liquidity, shortfall); } @@ -685,7 +686,7 @@ contract Comptroller is ComptrollerV7Storage, ComptrollerInterface, ComptrollerE * account shortfall below collateral requirements) */ function getAccountLiquidityInternal(address account) internal view returns (Error, uint, uint) { - return getHypotheticalAccountLiquidityInternal(account, CToken(0), 0, 0); + return getHypotheticalAccountLiquidityInternal(account, CToken(address(0)), 0, 0); } /** @@ -785,7 +786,7 @@ contract Comptroller is ComptrollerV7Storage, ComptrollerInterface, ComptrollerE * @param actualRepayAmount The amount of cTokenBorrowed underlying to convert into cTokenCollateral tokens * @return (errorCode, number of cTokenCollateral tokens to be seized in a liquidation) */ - function liquidateCalculateSeizeTokens(address cTokenBorrowed, address cTokenCollateral, uint actualRepayAmount) external view returns (uint, uint) { + function liquidateCalculateSeizeTokens(address cTokenBorrowed, address cTokenCollateral, uint actualRepayAmount) override external view returns (uint, uint) { /* Read oracle prices for borrowed and collateral markets */ uint priceBorrowedMantissa = oracle.getUnderlyingPrice(CToken(cTokenBorrowed)); uint priceCollateralMantissa = oracle.getUnderlyingPrice(CToken(cTokenCollateral)); @@ -940,7 +941,10 @@ contract Comptroller is ComptrollerV7Storage, ComptrollerInterface, ComptrollerE cToken.isCToken(); // Sanity check to make sure its really a CToken // Note that isComped is not in active use anymore - markets[address(cToken)] = Market({isListed: true, isComped: false, collateralFactorMantissa: 0}); + Market storage newMarket = markets[address(cToken)]; + newMarket.isListed = true; + newMarket.isComped = false; + newMarket.collateralFactorMantissa = 0; _addMarketInternal(address(cToken)); _initializeMarket(address(cToken)); @@ -990,7 +994,7 @@ contract Comptroller is ComptrollerV7Storage, ComptrollerInterface, ComptrollerE * @param newBorrowCaps The new borrow cap values in underlying to be set. A value of 0 corresponds to unlimited borrowing. */ function _setMarketBorrowCaps(CToken[] calldata cTokens, uint[] calldata newBorrowCaps) external { - require(msg.sender == admin || msg.sender == borrowCapGuardian, "only admin or borrow cap guardian can set borrow caps"); + require(msg.sender == admin || msg.sender == borrowCapGuardian, "only admin or borrow cap guardian can set borrow caps"); uint numMarkets = cTokens.length; uint numBorrowCaps = newBorrowCaps.length; @@ -1120,7 +1124,7 @@ contract Comptroller is ComptrollerV7Storage, ComptrollerInterface, ComptrollerE amountToSubtract = currentAccrual; } - + if (amountToSubtract > 0) { // Subtract the bad accrual amount from what they have accrued. // Users will keep whatever they have correctly accrued. @@ -1285,7 +1289,7 @@ contract Comptroller is ComptrollerV7Storage, ComptrollerInterface, ComptrollerE Double memory deltaIndex = Double({mantissa: sub_(borrowIndex, borrowerIndex)}); uint borrowerAmount = div_(CToken(cToken).borrowBalanceStored(borrower), marketBorrowIndex); - + // Calculate COMP accrued: cTokenAmount * accruedPerBorrowedUnit uint borrowerDelta = mul_(borrowerAmount, deltaIndex); @@ -1447,13 +1451,13 @@ contract Comptroller is ComptrollerV7Storage, ComptrollerInterface, ComptrollerE */ function isDeprecated(CToken cToken) public view returns (bool) { return - markets[address(cToken)].collateralFactorMantissa == 0 && - borrowGuardianPaused[address(cToken)] == true && + markets[address(cToken)].collateralFactorMantissa == 0 && + borrowGuardianPaused[address(cToken)] == true && cToken.reserveFactorMantissa() == 1e18 ; } - function getBlockNumber() public view returns (uint) { + function getBlockNumber() virtual public view returns (uint) { return block.number; } @@ -1461,7 +1465,7 @@ contract Comptroller is ComptrollerV7Storage, ComptrollerInterface, ComptrollerE * @notice Return the address of the COMP token * @return The address of COMP */ - function getCompAddress() public view returns (address) { + function getCompAddress() virtual public view returns (address) { return 0xc00e94Cb662C3520282E6f5717214004A7f26888; } } diff --git a/contracts/ComptrollerG1.sol b/contracts/ComptrollerG1.sol deleted file mode 100644 index 9e243f660..000000000 --- a/contracts/ComptrollerG1.sol +++ /dev/null @@ -1,993 +0,0 @@ -pragma solidity ^0.5.16; - -import "./CToken.sol"; -import "./ErrorReporter.sol"; -import "./Exponential.sol"; -import "./PriceOracle.sol"; -import "./ComptrollerInterface.sol"; -import "./ComptrollerStorage.sol"; -import "./Unitroller.sol"; - -/** - * @title Compound's Comptroller Contract - * @author Compound - * @dev This was the first version of the Comptroller brains. - * We keep it so our tests can continue to do the real-life behavior of upgrading from this logic forward. - */ -contract ComptrollerG1 is ComptrollerV1Storage, ComptrollerInterface, ComptrollerErrorReporter, Exponential { - struct Market { - /** - * @notice Whether or not this market is listed - */ - bool isListed; - - /** - * @notice Multiplier representing the most one can borrow against their collateral in this market. - * For instance, 0.9 to allow borrowing 90% of collateral value. - * Must be between 0 and 1, and stored as a mantissa. - */ - uint collateralFactorMantissa; - - /** - * @notice Per-market mapping of "accounts in this asset" - */ - mapping(address => bool) accountMembership; - } - - /** - * @notice Official mapping of cTokens -> Market metadata - * @dev Used e.g. to determine if a market is supported - */ - mapping(address => Market) public markets; - - /** - * @notice Emitted when an admin supports a market - */ - event MarketListed(CToken cToken); - - /** - * @notice Emitted when an account enters a market - */ - event MarketEntered(CToken cToken, address account); - - /** - * @notice Emitted when an account exits a market - */ - event MarketExited(CToken cToken, address account); - - /** - * @notice Emitted when close factor is changed by admin - */ - event NewCloseFactor(uint oldCloseFactorMantissa, uint newCloseFactorMantissa); - - /** - * @notice Emitted when a collateral factor is changed by admin - */ - event NewCollateralFactor(CToken cToken, uint oldCollateralFactorMantissa, uint newCollateralFactorMantissa); - - /** - * @notice Emitted when liquidation incentive is changed by admin - */ - event NewLiquidationIncentive(uint oldLiquidationIncentiveMantissa, uint newLiquidationIncentiveMantissa); - - /** - * @notice Emitted when maxAssets is changed by admin - */ - event NewMaxAssets(uint oldMaxAssets, uint newMaxAssets); - - /** - * @notice Emitted when price oracle is changed - */ - event NewPriceOracle(PriceOracle oldPriceOracle, PriceOracle newPriceOracle); - - // closeFactorMantissa must be strictly greater than this value - uint constant closeFactorMinMantissa = 5e16; // 0.05 - - // closeFactorMantissa must not exceed this value - uint constant closeFactorMaxMantissa = 9e17; // 0.9 - - // No collateralFactorMantissa may exceed this value - uint constant collateralFactorMaxMantissa = 9e17; // 0.9 - - // liquidationIncentiveMantissa must be no less than this value - uint constant liquidationIncentiveMinMantissa = mantissaOne; - - // liquidationIncentiveMantissa must be no greater than this value - uint constant liquidationIncentiveMaxMantissa = 15e17; // 1.5 - - constructor() public { - admin = msg.sender; - } - - /*** Assets You Are In ***/ - - /** - * @notice Returns the assets an account has entered - * @param account The address of the account to pull assets for - * @return A dynamic list with the assets the account has entered - */ - function getAssetsIn(address account) external view returns (CToken[] memory) { - CToken[] memory assetsIn = accountAssets[account]; - - return assetsIn; - } - - /** - * @notice Returns whether the given account is entered in the given asset - * @param account The address of the account to check - * @param cToken The cToken to check - * @return True if the account is in the asset, otherwise false. - */ - function checkMembership(address account, CToken cToken) external view returns (bool) { - return markets[address(cToken)].accountMembership[account]; - } - - /** - * @notice Add assets to be included in account liquidity calculation - * @param cTokens The list of addresses of the cToken markets to be enabled - * @return Success indicator for whether each corresponding market was entered - */ - function enterMarkets(address[] memory cTokens) public returns (uint[] memory) { - uint len = cTokens.length; - - uint[] memory results = new uint[](len); - for (uint i = 0; i < len; i++) { - CToken cToken = CToken(cTokens[i]); - Market storage marketToJoin = markets[address(cToken)]; - - if (!marketToJoin.isListed) { - // if market is not listed, cannot join move along - results[i] = uint(Error.MARKET_NOT_LISTED); - continue; - } - - if (marketToJoin.accountMembership[msg.sender] == true) { - // if already joined, move along - results[i] = uint(Error.NO_ERROR); - continue; - } - - if (accountAssets[msg.sender].length >= maxAssets) { - // if no space, cannot join, move along - results[i] = uint(Error.TOO_MANY_ASSETS); - continue; - } - - // survived the gauntlet, add to list - // NOTE: we store these somewhat redundantly as a significant optimization - // this avoids having to iterate through the list for the most common use cases - // that is, only when we need to perform liquidity checks - // and not whenever we want to check if an account is in a particular market - marketToJoin.accountMembership[msg.sender] = true; - accountAssets[msg.sender].push(cToken); - - emit MarketEntered(cToken, msg.sender); - - results[i] = uint(Error.NO_ERROR); - } - - return results; - } - - /** - * @notice Removes asset from sender's account liquidity calculation - * @dev Sender must not have an outstanding borrow balance in the asset, - * or be providing neccessary collateral for an outstanding borrow. - * @param cTokenAddress The address of the asset to be removed - * @return Whether or not the account successfully exited the market - */ - function exitMarket(address cTokenAddress) external returns (uint) { - CToken cToken = CToken(cTokenAddress); - /* Get sender tokensHeld and amountOwed underlying from the cToken */ - (uint oErr, uint tokensHeld, uint amountOwed, ) = cToken.getAccountSnapshot(msg.sender); - require(oErr == 0, "exitMarket: getAccountSnapshot failed"); // semi-opaque error code - - /* Fail if the sender has a borrow balance */ - if (amountOwed != 0) { - return fail(Error.NONZERO_BORROW_BALANCE, FailureInfo.EXIT_MARKET_BALANCE_OWED); - } - - /* Fail if the sender is not permitted to redeem all of their tokens */ - uint allowed = redeemAllowedInternal(cTokenAddress, msg.sender, tokensHeld); - if (allowed != 0) { - return failOpaque(Error.REJECTION, FailureInfo.EXIT_MARKET_REJECTION, allowed); - } - - Market storage marketToExit = markets[address(cToken)]; - - /* Return true if the sender is not already ‘in’ the market */ - if (!marketToExit.accountMembership[msg.sender]) { - return uint(Error.NO_ERROR); - } - - /* Set cToken account membership to false */ - delete marketToExit.accountMembership[msg.sender]; - - /* Delete cToken from the account’s list of assets */ - // load into memory for faster iteration - CToken[] memory userAssetList = accountAssets[msg.sender]; - uint len = userAssetList.length; - uint assetIndex = len; - for (uint i = 0; i < len; i++) { - if (userAssetList[i] == cToken) { - assetIndex = i; - break; - } - } - - // We *must* have found the asset in the list or our redundant data structure is broken - assert(assetIndex < len); - - // copy last item in list to location of item to be removed, reduce length by 1 - CToken[] storage storedList = accountAssets[msg.sender]; - storedList[assetIndex] = storedList[storedList.length - 1]; - storedList.length--; - - emit MarketExited(cToken, msg.sender); - - return uint(Error.NO_ERROR); - } - - /*** Policy Hooks ***/ - - /** - * @notice Checks if the account should be allowed to mint tokens in the given market - * @param cToken The market to verify the mint against - * @param minter The account which would get the minted tokens - * @param mintAmount The amount of underlying being supplied to the market in exchange for tokens - * @return 0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol) - */ - function mintAllowed(address cToken, address minter, uint mintAmount) external returns (uint) { - minter; // currently unused - mintAmount; // currently unused - - if (!markets[cToken].isListed) { - return uint(Error.MARKET_NOT_LISTED); - } - - // *may include Policy Hook-type checks - - return uint(Error.NO_ERROR); - } - - /** - * @notice Validates mint and reverts on rejection. May emit logs. - * @param cToken Asset being minted - * @param minter The address minting the tokens - * @param mintAmount The amount of the underlying asset being minted - * @param mintTokens The number of tokens being minted - */ - function mintVerify(address cToken, address minter, uint mintAmount, uint mintTokens) external { - cToken; // currently unused - minter; // currently unused - mintAmount; // currently unused - mintTokens; // currently unused - - if (false) { - maxAssets = maxAssets; // not pure - } - } - - /** - * @notice Checks if the account should be allowed to redeem tokens in the given market - * @param cToken The market to verify the redeem against - * @param redeemer The account which would redeem the tokens - * @param redeemTokens The number of cTokens to exchange for the underlying asset in the market - * @return 0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol) - */ - function redeemAllowed(address cToken, address redeemer, uint redeemTokens) external returns (uint) { - return redeemAllowedInternal(cToken, redeemer, redeemTokens); - } - - function redeemAllowedInternal(address cToken, address redeemer, uint redeemTokens) internal view returns (uint) { - if (!markets[cToken].isListed) { - return uint(Error.MARKET_NOT_LISTED); - } - - // *may include Policy Hook-type checks - - /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */ - if (!markets[cToken].accountMembership[redeemer]) { - return uint(Error.NO_ERROR); - } - - /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */ - (Error err, , uint shortfall) = getHypotheticalAccountLiquidityInternal(redeemer, CToken(cToken), redeemTokens, 0); - if (err != Error.NO_ERROR) { - return uint(err); - } - if (shortfall > 0) { - return uint(Error.INSUFFICIENT_LIQUIDITY); - } - - return uint(Error.NO_ERROR); - } - - /** - * @notice Validates redeem and reverts on rejection. May emit logs. - * @param cToken Asset being redeemed - * @param redeemer The address redeeming the tokens - * @param redeemAmount The amount of the underlying asset being redeemed - * @param redeemTokens The number of tokens being redeemed - */ - function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) external { - cToken; // currently unused - redeemer; // currently unused - redeemAmount; // currently unused - redeemTokens; // currently unused - - // Require tokens is zero or amount is also zero - if (redeemTokens == 0 && redeemAmount > 0) { - revert("redeemTokens zero"); - } - } - - /** - * @notice Checks if the account should be allowed to borrow the underlying asset of the given market - * @param cToken The market to verify the borrow against - * @param borrower The account which would borrow the asset - * @param borrowAmount The amount of underlying the account would borrow - * @return 0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol) - */ - function borrowAllowed(address cToken, address borrower, uint borrowAmount) external returns (uint) { - if (!markets[cToken].isListed) { - return uint(Error.MARKET_NOT_LISTED); - } - - // *may include Policy Hook-type checks - - if (!markets[cToken].accountMembership[borrower]) { - return uint(Error.MARKET_NOT_ENTERED); - } - - if (oracle.getUnderlyingPrice(CToken(cToken)) == 0) { - return uint(Error.PRICE_ERROR); - } - - (Error err, , uint shortfall) = getHypotheticalAccountLiquidityInternal(borrower, CToken(cToken), 0, borrowAmount); - if (err != Error.NO_ERROR) { - return uint(err); - } - if (shortfall > 0) { - return uint(Error.INSUFFICIENT_LIQUIDITY); - } - - return uint(Error.NO_ERROR); - } - - /** - * @notice Validates borrow and reverts on rejection. May emit logs. - * @param cToken Asset whose underlying is being borrowed - * @param borrower The address borrowing the underlying - * @param borrowAmount The amount of the underlying asset requested to borrow - */ - function borrowVerify(address cToken, address borrower, uint borrowAmount) external { - cToken; // currently unused - borrower; // currently unused - borrowAmount; // currently unused - - if (false) { - maxAssets = maxAssets; // not pure - } - } - - /** - * @notice Checks if the account should be allowed to repay a borrow in the given market - * @param cToken The market to verify the repay against - * @param payer The account which would repay the asset - * @param borrower The account which would borrowed the asset - * @param repayAmount The amount of the underlying asset the account would repay - * @return 0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol) - */ - function repayBorrowAllowed( - address cToken, - address payer, - address borrower, - uint repayAmount) external returns (uint) { - payer; // currently unused - borrower; // currently unused - repayAmount; // currently unused - - if (!markets[cToken].isListed) { - return uint(Error.MARKET_NOT_LISTED); - } - - // *may include Policy Hook-type checks - - return uint(Error.NO_ERROR); - } - - /** - * @notice Validates repayBorrow and reverts on rejection. May emit logs. - * @param cToken Asset being repaid - * @param payer The address repaying the borrow - * @param borrower The address of the borrower - * @param repayAmount The amount of underlying being repaid - */ - function repayBorrowVerify( - address cToken, - address payer, - address borrower, - uint repayAmount, - uint borrowerIndex) external { - cToken; // currently unused - payer; // currently unused - borrower; // currently unused - repayAmount; // currently unused - borrowerIndex; // currently unused - - if (false) { - maxAssets = maxAssets; // not pure - } - } - - /** - * @notice Checks if the liquidation should be allowed to occur - * @param cTokenBorrowed Asset which was borrowed by the borrower - * @param cTokenCollateral Asset which was used as collateral and will be seized - * @param liquidator The address repaying the borrow and seizing the collateral - * @param borrower The address of the borrower - * @param repayAmount The amount of underlying being repaid - */ - function liquidateBorrowAllowed( - address cTokenBorrowed, - address cTokenCollateral, - address liquidator, - address borrower, - uint repayAmount) external returns (uint) { - liquidator; // currently unused - borrower; // currently unused - repayAmount; // currently unused - - if (!markets[cTokenBorrowed].isListed || !markets[cTokenCollateral].isListed) { - return uint(Error.MARKET_NOT_LISTED); - } - - // *may include Policy Hook-type checks - - /* The borrower must have shortfall in order to be liquidatable */ - (Error err, , uint shortfall) = getAccountLiquidityInternal(borrower); - if (err != Error.NO_ERROR) { - return uint(err); - } - if (shortfall == 0) { - return uint(Error.INSUFFICIENT_SHORTFALL); - } - - /* The liquidator may not repay more than what is allowed by the closeFactor */ - uint borrowBalance = CToken(cTokenBorrowed).borrowBalanceStored(borrower); - (MathError mathErr, uint maxClose) = mulScalarTruncate(Exp({mantissa: closeFactorMantissa}), borrowBalance); - if (mathErr != MathError.NO_ERROR) { - return uint(Error.MATH_ERROR); - } - if (repayAmount > maxClose) { - return uint(Error.TOO_MUCH_REPAY); - } - - return uint(Error.NO_ERROR); - } - - /** - * @notice Validates liquidateBorrow and reverts on rejection. May emit logs. - * @param cTokenBorrowed Asset which was borrowed by the borrower - * @param cTokenCollateral Asset which was used as collateral and will be seized - * @param liquidator The address repaying the borrow and seizing the collateral - * @param borrower The address of the borrower - * @param repayAmount The amount of underlying being repaid - */ - function liquidateBorrowVerify( - address cTokenBorrowed, - address cTokenCollateral, - address liquidator, - address borrower, - uint repayAmount, - uint seizeTokens) external { - cTokenBorrowed; // currently unused - cTokenCollateral; // currently unused - liquidator; // currently unused - borrower; // currently unused - repayAmount; // currently unused - seizeTokens; // currently unused - - if (false) { - maxAssets = maxAssets; // not pure - } - } - - /** - * @notice Checks if the seizing of assets should be allowed to occur - * @param cTokenCollateral Asset which was used as collateral and will be seized - * @param cTokenBorrowed Asset which was borrowed by the borrower - * @param liquidator The address repaying the borrow and seizing the collateral - * @param borrower The address of the borrower - * @param seizeTokens The number of collateral tokens to seize - */ - function seizeAllowed( - address cTokenCollateral, - address cTokenBorrowed, - address liquidator, - address borrower, - uint seizeTokens) external returns (uint) { - liquidator; // currently unused - borrower; // currently unused - seizeTokens; // currently unused - - if (!markets[cTokenCollateral].isListed || !markets[cTokenBorrowed].isListed) { - return uint(Error.MARKET_NOT_LISTED); - } - - if (CToken(cTokenCollateral).comptroller() != CToken(cTokenBorrowed).comptroller()) { - return uint(Error.COMPTROLLER_MISMATCH); - } - - // *may include Policy Hook-type checks - - return uint(Error.NO_ERROR); - } - - /** - * @notice Validates seize and reverts on rejection. May emit logs. - * @param cTokenCollateral Asset which was used as collateral and will be seized - * @param cTokenBorrowed Asset which was borrowed by the borrower - * @param liquidator The address repaying the borrow and seizing the collateral - * @param borrower The address of the borrower - * @param seizeTokens The number of collateral tokens to seize - */ - function seizeVerify( - address cTokenCollateral, - address cTokenBorrowed, - address liquidator, - address borrower, - uint seizeTokens) external { - cTokenCollateral; // currently unused - cTokenBorrowed; // currently unused - liquidator; // currently unused - borrower; // currently unused - seizeTokens; // currently unused - - if (false) { - maxAssets = maxAssets; // not pure - } - } - - /** - * @notice Checks if the account should be allowed to transfer tokens in the given market - * @param cToken The market to verify the transfer against - * @param src The account which sources the tokens - * @param dst The account which receives the tokens - * @param transferTokens The number of cTokens to transfer - * @return 0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol) - */ - function transferAllowed(address cToken, address src, address dst, uint transferTokens) external returns (uint) { - cToken; // currently unused - src; // currently unused - dst; // currently unused - transferTokens; // currently unused - - // *may include Policy Hook-type checks - - // Currently the only consideration is whether or not - // the src is allowed to redeem this many tokens - return redeemAllowedInternal(cToken, src, transferTokens); - } - - /** - * @notice Validates transfer and reverts on rejection. May emit logs. - * @param cToken Asset being transferred - * @param src The account which sources the tokens - * @param dst The account which receives the tokens - * @param transferTokens The number of cTokens to transfer - */ - function transferVerify(address cToken, address src, address dst, uint transferTokens) external { - cToken; // currently unused - src; // currently unused - dst; // currently unused - transferTokens; // currently unused - - if (false) { - maxAssets = maxAssets; // not pure - } - } - - /*** Liquidity/Liquidation Calculations ***/ - - /** - * @dev Local vars for avoiding stack-depth limits in calculating account liquidity. - * Note that `cTokenBalance` is the number of cTokens the account owns in the market, - * whereas `borrowBalance` is the amount of underlying that the account has borrowed. - */ - struct AccountLiquidityLocalVars { - uint sumCollateral; - uint sumBorrowPlusEffects; - uint cTokenBalance; - uint borrowBalance; - uint exchangeRateMantissa; - uint oraclePriceMantissa; - Exp collateralFactor; - Exp exchangeRate; - Exp oraclePrice; - Exp tokensToEther; - } - - /** - * @notice Determine the current account liquidity wrt collateral requirements - * @return (possible error code (semi-opaque), - account liquidity in excess of collateral requirements, - * account shortfall below collateral requirements) - */ - function getAccountLiquidity(address account) public view returns (uint, uint, uint) { - (Error err, uint liquidity, uint shortfall) = getHypotheticalAccountLiquidityInternal(account, CToken(0), 0, 0); - - return (uint(err), liquidity, shortfall); - } - - /** - * @notice Determine the current account liquidity wrt collateral requirements - * @return (possible error code, - account liquidity in excess of collateral requirements, - * account shortfall below collateral requirements) - */ - function getAccountLiquidityInternal(address account) internal view returns (Error, uint, uint) { - return getHypotheticalAccountLiquidityInternal(account, CToken(0), 0, 0); - } - - /** - * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed - * @param cTokenModify The market to hypothetically redeem/borrow in - * @param account The account to determine liquidity for - * @param redeemTokens The number of tokens to hypothetically redeem - * @param borrowAmount The amount of underlying to hypothetically borrow - * @dev Note that we calculate the exchangeRateStored for each collateral cToken using stored data, - * without calculating accumulated interest. - * @return (possible error code, - hypothetical account liquidity in excess of collateral requirements, - * hypothetical account shortfall below collateral requirements) - */ - function getHypotheticalAccountLiquidityInternal( - address account, - CToken cTokenModify, - uint redeemTokens, - uint borrowAmount) internal view returns (Error, uint, uint) { - - AccountLiquidityLocalVars memory vars; // Holds all our calculation results - uint oErr; - MathError mErr; - - // For each asset the account is in - CToken[] memory assets = accountAssets[account]; - for (uint i = 0; i < assets.length; i++) { - CToken asset = assets[i]; - - // Read the balances and exchange rate from the cToken - (oErr, vars.cTokenBalance, vars.borrowBalance, vars.exchangeRateMantissa) = asset.getAccountSnapshot(account); - if (oErr != 0) { // semi-opaque error code, we assume NO_ERROR == 0 is invariant between upgrades - return (Error.SNAPSHOT_ERROR, 0, 0); - } - vars.collateralFactor = Exp({mantissa: markets[address(asset)].collateralFactorMantissa}); - vars.exchangeRate = Exp({mantissa: vars.exchangeRateMantissa}); - - // Get the normalized price of the asset - vars.oraclePriceMantissa = oracle.getUnderlyingPrice(asset); - if (vars.oraclePriceMantissa == 0) { - return (Error.PRICE_ERROR, 0, 0); - } - vars.oraclePrice = Exp({mantissa: vars.oraclePriceMantissa}); - - // Pre-compute a conversion factor from tokens -> ether (normalized price value) - (mErr, vars.tokensToEther) = mulExp3(vars.collateralFactor, vars.exchangeRate, vars.oraclePrice); - if (mErr != MathError.NO_ERROR) { - return (Error.MATH_ERROR, 0, 0); - } - - // sumCollateral += tokensToEther * cTokenBalance - (mErr, vars.sumCollateral) = mulScalarTruncateAddUInt(vars.tokensToEther, vars.cTokenBalance, vars.sumCollateral); - if (mErr != MathError.NO_ERROR) { - return (Error.MATH_ERROR, 0, 0); - } - - // sumBorrowPlusEffects += oraclePrice * borrowBalance - (mErr, vars.sumBorrowPlusEffects) = mulScalarTruncateAddUInt(vars.oraclePrice, vars.borrowBalance, vars.sumBorrowPlusEffects); - if (mErr != MathError.NO_ERROR) { - return (Error.MATH_ERROR, 0, 0); - } - - // Calculate effects of interacting with cTokenModify - if (asset == cTokenModify) { - // redeem effect - // sumBorrowPlusEffects += tokensToEther * redeemTokens - (mErr, vars.sumBorrowPlusEffects) = mulScalarTruncateAddUInt(vars.tokensToEther, redeemTokens, vars.sumBorrowPlusEffects); - if (mErr != MathError.NO_ERROR) { - return (Error.MATH_ERROR, 0, 0); - } - - // borrow effect - // sumBorrowPlusEffects += oraclePrice * borrowAmount - (mErr, vars.sumBorrowPlusEffects) = mulScalarTruncateAddUInt(vars.oraclePrice, borrowAmount, vars.sumBorrowPlusEffects); - if (mErr != MathError.NO_ERROR) { - return (Error.MATH_ERROR, 0, 0); - } - } - } - - // These are safe, as the underflow condition is checked first - if (vars.sumCollateral > vars.sumBorrowPlusEffects) { - return (Error.NO_ERROR, vars.sumCollateral - vars.sumBorrowPlusEffects, 0); - } else { - return (Error.NO_ERROR, 0, vars.sumBorrowPlusEffects - vars.sumCollateral); - } - } - - /** - * @notice Calculate number of tokens of collateral asset to seize given an underlying amount - * @dev Used in liquidation (called in cToken.liquidateBorrowFresh) - * @param cTokenBorrowed The address of the borrowed cToken - * @param cTokenCollateral The address of the collateral cToken - * @param repayAmount The amount of cTokenBorrowed underlying to convert into cTokenCollateral tokens - * @return (errorCode, number of cTokenCollateral tokens to be seized in a liquidation) - */ - function liquidateCalculateSeizeTokens(address cTokenBorrowed, address cTokenCollateral, uint repayAmount) external view returns (uint, uint) { - /* Read oracle prices for borrowed and collateral markets */ - uint priceBorrowedMantissa = oracle.getUnderlyingPrice(CToken(cTokenBorrowed)); - uint priceCollateralMantissa = oracle.getUnderlyingPrice(CToken(cTokenCollateral)); - if (priceBorrowedMantissa == 0 || priceCollateralMantissa == 0) { - return (uint(Error.PRICE_ERROR), 0); - } - - /* - * Get the exchange rate and calculate the number of collateral tokens to seize: - * seizeAmount = repayAmount * liquidationIncentive * priceBorrowed / priceCollateral - * seizeTokens = seizeAmount / exchangeRate - * = repayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate) - */ - uint exchangeRateMantissa = CToken(cTokenCollateral).exchangeRateStored(); // Note: reverts on error - uint seizeTokens; - Exp memory numerator; - Exp memory denominator; - Exp memory ratio; - MathError mathErr; - - (mathErr, numerator) = mulExp(liquidationIncentiveMantissa, priceBorrowedMantissa); - if (mathErr != MathError.NO_ERROR) { - return (uint(Error.MATH_ERROR), 0); - } - - (mathErr, denominator) = mulExp(priceCollateralMantissa, exchangeRateMantissa); - if (mathErr != MathError.NO_ERROR) { - return (uint(Error.MATH_ERROR), 0); - } - - (mathErr, ratio) = divExp(numerator, denominator); - if (mathErr != MathError.NO_ERROR) { - return (uint(Error.MATH_ERROR), 0); - } - - (mathErr, seizeTokens) = mulScalarTruncate(ratio, repayAmount); - if (mathErr != MathError.NO_ERROR) { - return (uint(Error.MATH_ERROR), 0); - } - - return (uint(Error.NO_ERROR), seizeTokens); - } - - /*** Admin Functions ***/ - - /** - * @notice Sets a new price oracle for the comptroller - * @dev Admin function to set a new price oracle - * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) - */ - function _setPriceOracle(PriceOracle newOracle) public returns (uint) { - // Check caller is admin OR currently initialzing as new unitroller implementation - if (!adminOrInitializing()) { - return fail(Error.UNAUTHORIZED, FailureInfo.SET_PRICE_ORACLE_OWNER_CHECK); - } - - // Track the old oracle for the comptroller - PriceOracle oldOracle = oracle; - - // Ensure invoke newOracle.isPriceOracle() returns true - // require(newOracle.isPriceOracle(), "oracle method isPriceOracle returned false"); - - // Set comptroller's oracle to newOracle - oracle = newOracle; - - // Emit NewPriceOracle(oldOracle, newOracle) - emit NewPriceOracle(oldOracle, newOracle); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Sets the closeFactor used when liquidating borrows - * @dev Admin function to set closeFactor - * @param newCloseFactorMantissa New close factor, scaled by 1e18 - * @return uint 0=success, otherwise a failure. (See ErrorReporter for details) - */ - function _setCloseFactor(uint newCloseFactorMantissa) external returns (uint256) { - // Check caller is admin OR currently initialzing as new unitroller implementation - if (!adminOrInitializing()) { - return fail(Error.UNAUTHORIZED, FailureInfo.SET_CLOSE_FACTOR_OWNER_CHECK); - } - - Exp memory newCloseFactorExp = Exp({mantissa: newCloseFactorMantissa}); - Exp memory lowLimit = Exp({mantissa: closeFactorMinMantissa}); - if (lessThanOrEqualExp(newCloseFactorExp, lowLimit)) { - return fail(Error.INVALID_CLOSE_FACTOR, FailureInfo.SET_CLOSE_FACTOR_VALIDATION); - } - - Exp memory highLimit = Exp({mantissa: closeFactorMaxMantissa}); - if (lessThanExp(highLimit, newCloseFactorExp)) { - return fail(Error.INVALID_CLOSE_FACTOR, FailureInfo.SET_CLOSE_FACTOR_VALIDATION); - } - - uint oldCloseFactorMantissa = closeFactorMantissa; - closeFactorMantissa = newCloseFactorMantissa; - emit NewCloseFactor(oldCloseFactorMantissa, closeFactorMantissa); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Sets the collateralFactor for a market - * @dev Admin function to set per-market collateralFactor - * @param cToken The market to set the factor on - * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18 - * @return uint 0=success, otherwise a failure. (See ErrorReporter for details) - */ - function _setCollateralFactor(CToken cToken, uint newCollateralFactorMantissa) external returns (uint256) { - // Check caller is admin - if (msg.sender != admin) { - return fail(Error.UNAUTHORIZED, FailureInfo.SET_COLLATERAL_FACTOR_OWNER_CHECK); - } - - // Verify market is listed - Market storage market = markets[address(cToken)]; - if (!market.isListed) { - return fail(Error.MARKET_NOT_LISTED, FailureInfo.SET_COLLATERAL_FACTOR_NO_EXISTS); - } - - Exp memory newCollateralFactorExp = Exp({mantissa: newCollateralFactorMantissa}); - - // Check collateral factor <= 0.9 - Exp memory highLimit = Exp({mantissa: collateralFactorMaxMantissa}); - if (lessThanExp(highLimit, newCollateralFactorExp)) { - return fail(Error.INVALID_COLLATERAL_FACTOR, FailureInfo.SET_COLLATERAL_FACTOR_VALIDATION); - } - - // If collateral factor != 0, fail if price == 0 - if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(cToken) == 0) { - return fail(Error.PRICE_ERROR, FailureInfo.SET_COLLATERAL_FACTOR_WITHOUT_PRICE); - } - - // Set market's collateral factor to new collateral factor, remember old value - uint oldCollateralFactorMantissa = market.collateralFactorMantissa; - market.collateralFactorMantissa = newCollateralFactorMantissa; - - // Emit event with asset, old collateral factor, and new collateral factor - emit NewCollateralFactor(cToken, oldCollateralFactorMantissa, newCollateralFactorMantissa); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Sets maxAssets which controls how many markets can be entered - * @dev Admin function to set maxAssets - * @param newMaxAssets New max assets - * @return uint 0=success, otherwise a failure. (See ErrorReporter for details) - */ - function _setMaxAssets(uint newMaxAssets) external returns (uint) { - // Check caller is admin OR currently initialzing as new unitroller implementation - if (!adminOrInitializing()) { - return fail(Error.UNAUTHORIZED, FailureInfo.SET_MAX_ASSETS_OWNER_CHECK); - } - - uint oldMaxAssets = maxAssets; - maxAssets = newMaxAssets; - emit NewMaxAssets(oldMaxAssets, newMaxAssets); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Sets liquidationIncentive - * @dev Admin function to set liquidationIncentive - * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18 - * @return uint 0=success, otherwise a failure. (See ErrorReporter for details) - */ - function _setLiquidationIncentive(uint newLiquidationIncentiveMantissa) external returns (uint) { - // Check caller is admin OR currently initialzing as new unitroller implementation - if (!adminOrInitializing()) { - return fail(Error.UNAUTHORIZED, FailureInfo.SET_LIQUIDATION_INCENTIVE_OWNER_CHECK); - } - - // Check de-scaled 1 <= newLiquidationDiscount <= 1.5 - Exp memory newLiquidationIncentive = Exp({mantissa: newLiquidationIncentiveMantissa}); - Exp memory minLiquidationIncentive = Exp({mantissa: liquidationIncentiveMinMantissa}); - if (lessThanExp(newLiquidationIncentive, minLiquidationIncentive)) { - return fail(Error.INVALID_LIQUIDATION_INCENTIVE, FailureInfo.SET_LIQUIDATION_INCENTIVE_VALIDATION); - } - - Exp memory maxLiquidationIncentive = Exp({mantissa: liquidationIncentiveMaxMantissa}); - if (lessThanExp(maxLiquidationIncentive, newLiquidationIncentive)) { - return fail(Error.INVALID_LIQUIDATION_INCENTIVE, FailureInfo.SET_LIQUIDATION_INCENTIVE_VALIDATION); - } - - // Save current value for use in log - uint oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa; - - // Set liquidation incentive to new incentive - liquidationIncentiveMantissa = newLiquidationIncentiveMantissa; - - // Emit event with old incentive, new incentive - emit NewLiquidationIncentive(oldLiquidationIncentiveMantissa, newLiquidationIncentiveMantissa); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Add the market to the markets mapping and set it as listed - * @dev Admin function to set isListed and add support for the market - * @param cToken The address of the market (token) to list - * @return uint 0=success, otherwise a failure. (See enum Error for details) - */ - function _supportMarket(CToken cToken) external returns (uint) { - if (msg.sender != admin) { - return fail(Error.UNAUTHORIZED, FailureInfo.SUPPORT_MARKET_OWNER_CHECK); - } - - if (markets[address(cToken)].isListed) { - return fail(Error.MARKET_ALREADY_LISTED, FailureInfo.SUPPORT_MARKET_EXISTS); - } - - cToken.isCToken(); // Sanity check to make sure its really a CToken - - markets[address(cToken)] = Market({isListed: true, collateralFactorMantissa: 0}); - emit MarketListed(cToken); - - return uint(Error.NO_ERROR); - } - - function _become(Unitroller unitroller, PriceOracle _oracle, uint _closeFactorMantissa, uint _maxAssets, bool reinitializing) public { - require(msg.sender == unitroller.admin(), "only unitroller admin can change brains"); - uint changeStatus = unitroller._acceptImplementation(); - - require(changeStatus == 0, "change not authorized"); - - if (!reinitializing) { - ComptrollerG1 freshBrainedComptroller = ComptrollerG1(address(unitroller)); - - // Ensure invoke _setPriceOracle() = 0 - uint err = freshBrainedComptroller._setPriceOracle(_oracle); - require (err == uint(Error.NO_ERROR), "set price oracle error"); - - // Ensure invoke _setCloseFactor() = 0 - err = freshBrainedComptroller._setCloseFactor(_closeFactorMantissa); - require (err == uint(Error.NO_ERROR), "set close factor error"); - - // Ensure invoke _setMaxAssets() = 0 - err = freshBrainedComptroller._setMaxAssets(_maxAssets); - require (err == uint(Error.NO_ERROR), "set max asssets error"); - - // Ensure invoke _setLiquidationIncentive(liquidationIncentiveMinMantissa) = 0 - err = freshBrainedComptroller._setLiquidationIncentive(liquidationIncentiveMinMantissa); - require (err == uint(Error.NO_ERROR), "set liquidation incentive error"); - } - } - - /** - * @dev Check that caller is admin or this contract is initializing itself as - * the new implementation. - * There should be no way to satisfy msg.sender == comptrollerImplementaiton - * without tx.origin also being admin, but both are included for extra safety - */ - function adminOrInitializing() internal view returns (bool) { - bool initializing = ( - msg.sender == comptrollerImplementation - && - //solium-disable-next-line security/no-tx-origin - tx.origin == admin - ); - bool isAdmin = msg.sender == admin; - return isAdmin || initializing; - } -} \ No newline at end of file diff --git a/contracts/ComptrollerG2.sol b/contracts/ComptrollerG2.sol deleted file mode 100644 index d7aa0cbc4..000000000 --- a/contracts/ComptrollerG2.sol +++ /dev/null @@ -1,1061 +0,0 @@ -pragma solidity ^0.5.16; - -import "./CToken.sol"; -import "./ErrorReporter.sol"; -import "./Exponential.sol"; -import "./PriceOracle.sol"; -import "./ComptrollerInterface.sol"; -import "./ComptrollerStorage.sol"; -import "./Unitroller.sol"; - -/** - * @title Compound's Comptroller Contract - * @author Compound - */ -contract ComptrollerG2 is ComptrollerV2Storage, ComptrollerInterface, ComptrollerErrorReporter, Exponential { - /** - * @notice Emitted when an admin supports a market - */ - event MarketListed(CToken cToken); - - /** - * @notice Emitted when an account enters a market - */ - event MarketEntered(CToken cToken, address account); - - /** - * @notice Emitted when an account exits a market - */ - event MarketExited(CToken cToken, address account); - - /** - * @notice Emitted when close factor is changed by admin - */ - event NewCloseFactor(uint oldCloseFactorMantissa, uint newCloseFactorMantissa); - - /** - * @notice Emitted when a collateral factor is changed by admin - */ - event NewCollateralFactor(CToken cToken, uint oldCollateralFactorMantissa, uint newCollateralFactorMantissa); - - /** - * @notice Emitted when liquidation incentive is changed by admin - */ - event NewLiquidationIncentive(uint oldLiquidationIncentiveMantissa, uint newLiquidationIncentiveMantissa); - - /** - * @notice Emitted when maxAssets is changed by admin - */ - event NewMaxAssets(uint oldMaxAssets, uint newMaxAssets); - - /** - * @notice Emitted when price oracle is changed - */ - event NewPriceOracle(PriceOracle oldPriceOracle, PriceOracle newPriceOracle); - - /** - * @notice Emitted when pause guardian is changed - */ - event NewPauseGuardian(address oldPauseGuardian, address newPauseGuardian); - - /** - * @notice Emitted when an action is paused globally - */ - event ActionPaused(string action, bool pauseState); - - /** - * @notice Emitted when an action is paused on a market - */ - event ActionPaused(CToken cToken, string action, bool pauseState); - - // closeFactorMantissa must be strictly greater than this value - uint internal constant closeFactorMinMantissa = 0.05e18; // 0.05 - - // closeFactorMantissa must not exceed this value - uint internal constant closeFactorMaxMantissa = 0.9e18; // 0.9 - - // No collateralFactorMantissa may exceed this value - uint internal constant collateralFactorMaxMantissa = 0.9e18; // 0.9 - - // liquidationIncentiveMantissa must be no less than this value - uint internal constant liquidationIncentiveMinMantissa = 1.0e18; // 1.0 - - // liquidationIncentiveMantissa must be no greater than this value - uint internal constant liquidationIncentiveMaxMantissa = 1.5e18; // 1.5 - - constructor() public { - admin = msg.sender; - } - - /*** Assets You Are In ***/ - - /** - * @notice Returns the assets an account has entered - * @param account The address of the account to pull assets for - * @return A dynamic list with the assets the account has entered - */ - function getAssetsIn(address account) external view returns (CToken[] memory) { - CToken[] memory assetsIn = accountAssets[account]; - - return assetsIn; - } - - /** - * @notice Returns whether the given account is entered in the given asset - * @param account The address of the account to check - * @param cToken The cToken to check - * @return True if the account is in the asset, otherwise false. - */ - function checkMembership(address account, CToken cToken) external view returns (bool) { - return markets[address(cToken)].accountMembership[account]; - } - - /** - * @notice Add assets to be included in account liquidity calculation - * @param cTokens The list of addresses of the cToken markets to be enabled - * @return Success indicator for whether each corresponding market was entered - */ - function enterMarkets(address[] memory cTokens) public returns (uint[] memory) { - uint len = cTokens.length; - - uint[] memory results = new uint[](len); - for (uint i = 0; i < len; i++) { - CToken cToken = CToken(cTokens[i]); - - results[i] = uint(addToMarketInternal(cToken, msg.sender)); - } - - return results; - } - - /** - * @notice Add the market to the borrower's "assets in" for liquidity calculations - * @param cToken The market to enter - * @param borrower The address of the account to modify - * @return Success indicator for whether the market was entered - */ - function addToMarketInternal(CToken cToken, address borrower) internal returns (Error) { - Market storage marketToJoin = markets[address(cToken)]; - - if (!marketToJoin.isListed) { - // market is not listed, cannot join - return Error.MARKET_NOT_LISTED; - } - - if (marketToJoin.accountMembership[borrower] == true) { - // already joined - return Error.NO_ERROR; - } - - if (accountAssets[borrower].length >= maxAssets) { - // no space, cannot join - return Error.TOO_MANY_ASSETS; - } - - // survived the gauntlet, add to list - // NOTE: we store these somewhat redundantly as a significant optimization - // this avoids having to iterate through the list for the most common use cases - // that is, only when we need to perform liquidity checks - // and not whenever we want to check if an account is in a particular market - marketToJoin.accountMembership[borrower] = true; - accountAssets[borrower].push(cToken); - - emit MarketEntered(cToken, borrower); - - return Error.NO_ERROR; - } - - /** - * @notice Removes asset from sender's account liquidity calculation - * @dev Sender must not have an outstanding borrow balance in the asset, - * or be providing neccessary collateral for an outstanding borrow. - * @param cTokenAddress The address of the asset to be removed - * @return Whether or not the account successfully exited the market - */ - function exitMarket(address cTokenAddress) external returns (uint) { - CToken cToken = CToken(cTokenAddress); - /* Get sender tokensHeld and amountOwed underlying from the cToken */ - (uint oErr, uint tokensHeld, uint amountOwed, ) = cToken.getAccountSnapshot(msg.sender); - require(oErr == 0, "exitMarket: getAccountSnapshot failed"); // semi-opaque error code - - /* Fail if the sender has a borrow balance */ - if (amountOwed != 0) { - return fail(Error.NONZERO_BORROW_BALANCE, FailureInfo.EXIT_MARKET_BALANCE_OWED); - } - - /* Fail if the sender is not permitted to redeem all of their tokens */ - uint allowed = redeemAllowedInternal(cTokenAddress, msg.sender, tokensHeld); - if (allowed != 0) { - return failOpaque(Error.REJECTION, FailureInfo.EXIT_MARKET_REJECTION, allowed); - } - - Market storage marketToExit = markets[address(cToken)]; - - /* Return true if the sender is not already ‘in’ the market */ - if (!marketToExit.accountMembership[msg.sender]) { - return uint(Error.NO_ERROR); - } - - /* Set cToken account membership to false */ - delete marketToExit.accountMembership[msg.sender]; - - /* Delete cToken from the account’s list of assets */ - // load into memory for faster iteration - CToken[] memory userAssetList = accountAssets[msg.sender]; - uint len = userAssetList.length; - uint assetIndex = len; - for (uint i = 0; i < len; i++) { - if (userAssetList[i] == cToken) { - assetIndex = i; - break; - } - } - - // We *must* have found the asset in the list or our redundant data structure is broken - assert(assetIndex < len); - - // copy last item in list to location of item to be removed, reduce length by 1 - CToken[] storage storedList = accountAssets[msg.sender]; - storedList[assetIndex] = storedList[storedList.length - 1]; - storedList.length--; - - emit MarketExited(cToken, msg.sender); - - return uint(Error.NO_ERROR); - } - - /*** Policy Hooks ***/ - - /** - * @notice Checks if the account should be allowed to mint tokens in the given market - * @param cToken The market to verify the mint against - * @param minter The account which would get the minted tokens - * @param mintAmount The amount of underlying being supplied to the market in exchange for tokens - * @return 0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol) - */ - function mintAllowed(address cToken, address minter, uint mintAmount) external returns (uint) { - // Pausing is a very serious situation - we revert to sound the alarms - require(!mintGuardianPaused[cToken], "mint is paused"); - - // Shh - currently unused - minter; - mintAmount; - - if (!markets[cToken].isListed) { - return uint(Error.MARKET_NOT_LISTED); - } - - // *may include Policy Hook-type checks - - return uint(Error.NO_ERROR); - } - - /** - * @notice Validates mint and reverts on rejection. May emit logs. - * @param cToken Asset being minted - * @param minter The address minting the tokens - * @param actualMintAmount The amount of the underlying asset being minted - * @param mintTokens The number of tokens being minted - */ - function mintVerify(address cToken, address minter, uint actualMintAmount, uint mintTokens) external { - // Shh - currently unused - cToken; - minter; - actualMintAmount; - mintTokens; - - // Shh - we don't ever want this hook to be marked pure - if (false) { - maxAssets = maxAssets; - } - } - - /** - * @notice Checks if the account should be allowed to redeem tokens in the given market - * @param cToken The market to verify the redeem against - * @param redeemer The account which would redeem the tokens - * @param redeemTokens The number of cTokens to exchange for the underlying asset in the market - * @return 0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol) - */ - function redeemAllowed(address cToken, address redeemer, uint redeemTokens) external returns (uint) { - return redeemAllowedInternal(cToken, redeemer, redeemTokens); - } - - function redeemAllowedInternal(address cToken, address redeemer, uint redeemTokens) internal view returns (uint) { - if (!markets[cToken].isListed) { - return uint(Error.MARKET_NOT_LISTED); - } - - // *may include Policy Hook-type checks - - /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */ - if (!markets[cToken].accountMembership[redeemer]) { - return uint(Error.NO_ERROR); - } - - /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */ - (Error err, , uint shortfall) = getHypotheticalAccountLiquidityInternal(redeemer, CToken(cToken), redeemTokens, 0); - if (err != Error.NO_ERROR) { - return uint(err); - } - if (shortfall > 0) { - return uint(Error.INSUFFICIENT_LIQUIDITY); - } - - return uint(Error.NO_ERROR); - } - - /** - * @notice Validates redeem and reverts on rejection. May emit logs. - * @param cToken Asset being redeemed - * @param redeemer The address redeeming the tokens - * @param redeemAmount The amount of the underlying asset being redeemed - * @param redeemTokens The number of tokens being redeemed - */ - function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) external { - // Shh - currently unused - cToken; - redeemer; - - // Require tokens is zero or amount is also zero - if (redeemTokens == 0 && redeemAmount > 0) { - revert("redeemTokens zero"); - } - } - - /** - * @notice Checks if the account should be allowed to borrow the underlying asset of the given market - * @param cToken The market to verify the borrow against - * @param borrower The account which would borrow the asset - * @param borrowAmount The amount of underlying the account would borrow - * @return 0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol) - */ - function borrowAllowed(address cToken, address borrower, uint borrowAmount) external returns (uint) { - // Pausing is a very serious situation - we revert to sound the alarms - require(!borrowGuardianPaused[cToken], "borrow is paused"); - - if (!markets[cToken].isListed) { - return uint(Error.MARKET_NOT_LISTED); - } - - // *may include Policy Hook-type checks - - if (!markets[cToken].accountMembership[borrower]) { - // only cTokens may call borrowAllowed if borrower not in market - require(msg.sender == cToken, "sender must be cToken"); - - // attempt to add borrower to the market - Error err = addToMarketInternal(CToken(msg.sender), borrower); - if (err != Error.NO_ERROR) { - return uint(err); - } - - // it should be impossible to break the important invariant - assert(markets[cToken].accountMembership[borrower]); - } - - if (oracle.getUnderlyingPrice(CToken(cToken)) == 0) { - return uint(Error.PRICE_ERROR); - } - - (Error err, , uint shortfall) = getHypotheticalAccountLiquidityInternal(borrower, CToken(cToken), 0, borrowAmount); - if (err != Error.NO_ERROR) { - return uint(err); - } - if (shortfall > 0) { - return uint(Error.INSUFFICIENT_LIQUIDITY); - } - - return uint(Error.NO_ERROR); - } - - /** - * @notice Validates borrow and reverts on rejection. May emit logs. - * @param cToken Asset whose underlying is being borrowed - * @param borrower The address borrowing the underlying - * @param borrowAmount The amount of the underlying asset requested to borrow - */ - function borrowVerify(address cToken, address borrower, uint borrowAmount) external { - // Shh - currently unused - cToken; - borrower; - borrowAmount; - - // Shh - we don't ever want this hook to be marked pure - if (false) { - maxAssets = maxAssets; - } - } - - /** - * @notice Checks if the account should be allowed to repay a borrow in the given market - * @param cToken The market to verify the repay against - * @param payer The account which would repay the asset - * @param borrower The account which would borrowed the asset - * @param repayAmount The amount of the underlying asset the account would repay - * @return 0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol) - */ - function repayBorrowAllowed( - address cToken, - address payer, - address borrower, - uint repayAmount) external returns (uint) { - // Shh - currently unused - payer; - borrower; - repayAmount; - - if (!markets[cToken].isListed) { - return uint(Error.MARKET_NOT_LISTED); - } - - // *may include Policy Hook-type checks - - return uint(Error.NO_ERROR); - } - - /** - * @notice Validates repayBorrow and reverts on rejection. May emit logs. - * @param cToken Asset being repaid - * @param payer The address repaying the borrow - * @param borrower The address of the borrower - * @param actualRepayAmount The amount of underlying being repaid - */ - function repayBorrowVerify( - address cToken, - address payer, - address borrower, - uint actualRepayAmount, - uint borrowerIndex) external { - // Shh - currently unused - cToken; - payer; - borrower; - actualRepayAmount; - borrowerIndex; - - // Shh - we don't ever want this hook to be marked pure - if (false) { - maxAssets = maxAssets; - } - } - - /** - * @notice Checks if the liquidation should be allowed to occur - * @param cTokenBorrowed Asset which was borrowed by the borrower - * @param cTokenCollateral Asset which was used as collateral and will be seized - * @param liquidator The address repaying the borrow and seizing the collateral - * @param borrower The address of the borrower - * @param repayAmount The amount of underlying being repaid - */ - function liquidateBorrowAllowed( - address cTokenBorrowed, - address cTokenCollateral, - address liquidator, - address borrower, - uint repayAmount) external returns (uint) { - // Shh - currently unused - liquidator; - - if (!markets[cTokenBorrowed].isListed || !markets[cTokenCollateral].isListed) { - return uint(Error.MARKET_NOT_LISTED); - } - - // *may include Policy Hook-type checks - - /* The borrower must have shortfall in order to be liquidatable */ - (Error err, , uint shortfall) = getAccountLiquidityInternal(borrower); - if (err != Error.NO_ERROR) { - return uint(err); - } - if (shortfall == 0) { - return uint(Error.INSUFFICIENT_SHORTFALL); - } - - /* The liquidator may not repay more than what is allowed by the closeFactor */ - uint borrowBalance = CToken(cTokenBorrowed).borrowBalanceStored(borrower); - (MathError mathErr, uint maxClose) = mulScalarTruncate(Exp({mantissa: closeFactorMantissa}), borrowBalance); - if (mathErr != MathError.NO_ERROR) { - return uint(Error.MATH_ERROR); - } - if (repayAmount > maxClose) { - return uint(Error.TOO_MUCH_REPAY); - } - - return uint(Error.NO_ERROR); - } - - /** - * @notice Validates liquidateBorrow and reverts on rejection. May emit logs. - * @param cTokenBorrowed Asset which was borrowed by the borrower - * @param cTokenCollateral Asset which was used as collateral and will be seized - * @param liquidator The address repaying the borrow and seizing the collateral - * @param borrower The address of the borrower - * @param actualRepayAmount The amount of underlying being repaid - */ - function liquidateBorrowVerify( - address cTokenBorrowed, - address cTokenCollateral, - address liquidator, - address borrower, - uint actualRepayAmount, - uint seizeTokens) external { - // Shh - currently unused - cTokenBorrowed; - cTokenCollateral; - liquidator; - borrower; - actualRepayAmount; - seizeTokens; - - // Shh - we don't ever want this hook to be marked pure - if (false) { - maxAssets = maxAssets; - } - } - - /** - * @notice Checks if the seizing of assets should be allowed to occur - * @param cTokenCollateral Asset which was used as collateral and will be seized - * @param cTokenBorrowed Asset which was borrowed by the borrower - * @param liquidator The address repaying the borrow and seizing the collateral - * @param borrower The address of the borrower - * @param seizeTokens The number of collateral tokens to seize - */ - function seizeAllowed( - address cTokenCollateral, - address cTokenBorrowed, - address liquidator, - address borrower, - uint seizeTokens) external returns (uint) { - // Pausing is a very serious situation - we revert to sound the alarms - require(!seizeGuardianPaused, "seize is paused"); - - // Shh - currently unused - liquidator; - borrower; - seizeTokens; - - if (!markets[cTokenCollateral].isListed || !markets[cTokenBorrowed].isListed) { - return uint(Error.MARKET_NOT_LISTED); - } - - if (CToken(cTokenCollateral).comptroller() != CToken(cTokenBorrowed).comptroller()) { - return uint(Error.COMPTROLLER_MISMATCH); - } - - // *may include Policy Hook-type checks - - return uint(Error.NO_ERROR); - } - - /** - * @notice Validates seize and reverts on rejection. May emit logs. - * @param cTokenCollateral Asset which was used as collateral and will be seized - * @param cTokenBorrowed Asset which was borrowed by the borrower - * @param liquidator The address repaying the borrow and seizing the collateral - * @param borrower The address of the borrower - * @param seizeTokens The number of collateral tokens to seize - */ - function seizeVerify( - address cTokenCollateral, - address cTokenBorrowed, - address liquidator, - address borrower, - uint seizeTokens) external { - // Shh - currently unused - cTokenCollateral; - cTokenBorrowed; - liquidator; - borrower; - seizeTokens; - - // Shh - we don't ever want this hook to be marked pure - if (false) { - maxAssets = maxAssets; - } - } - - /** - * @notice Checks if the account should be allowed to transfer tokens in the given market - * @param cToken The market to verify the transfer against - * @param src The account which sources the tokens - * @param dst The account which receives the tokens - * @param transferTokens The number of cTokens to transfer - * @return 0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol) - */ - function transferAllowed(address cToken, address src, address dst, uint transferTokens) external returns (uint) { - // Pausing is a very serious situation - we revert to sound the alarms - require(!transferGuardianPaused, "transfer is paused"); - - // Shh - currently unused - dst; - - // *may include Policy Hook-type checks - - // Currently the only consideration is whether or not - // the src is allowed to redeem this many tokens - return redeemAllowedInternal(cToken, src, transferTokens); - } - - /** - * @notice Validates transfer and reverts on rejection. May emit logs. - * @param cToken Asset being transferred - * @param src The account which sources the tokens - * @param dst The account which receives the tokens - * @param transferTokens The number of cTokens to transfer - */ - function transferVerify(address cToken, address src, address dst, uint transferTokens) external { - // Shh - currently unused - cToken; - src; - dst; - transferTokens; - - // Shh - we don't ever want this hook to be marked pure - if (false) { - maxAssets = maxAssets; - } - } - - /*** Liquidity/Liquidation Calculations ***/ - - /** - * @dev Local vars for avoiding stack-depth limits in calculating account liquidity. - * Note that `cTokenBalance` is the number of cTokens the account owns in the market, - * whereas `borrowBalance` is the amount of underlying that the account has borrowed. - */ - struct AccountLiquidityLocalVars { - uint sumCollateral; - uint sumBorrowPlusEffects; - uint cTokenBalance; - uint borrowBalance; - uint exchangeRateMantissa; - uint oraclePriceMantissa; - Exp collateralFactor; - Exp exchangeRate; - Exp oraclePrice; - Exp tokensToEther; - } - - /** - * @notice Determine the current account liquidity wrt collateral requirements - * @return (possible error code (semi-opaque), - account liquidity in excess of collateral requirements, - * account shortfall below collateral requirements) - */ - function getAccountLiquidity(address account) public view returns (uint, uint, uint) { - (Error err, uint liquidity, uint shortfall) = getHypotheticalAccountLiquidityInternal(account, CToken(0), 0, 0); - - return (uint(err), liquidity, shortfall); - } - - /** - * @notice Determine the current account liquidity wrt collateral requirements - * @return (possible error code, - account liquidity in excess of collateral requirements, - * account shortfall below collateral requirements) - */ - function getAccountLiquidityInternal(address account) internal view returns (Error, uint, uint) { - return getHypotheticalAccountLiquidityInternal(account, CToken(0), 0, 0); - } - - /** - * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed - * @param cTokenModify The market to hypothetically redeem/borrow in - * @param account The account to determine liquidity for - * @param redeemTokens The number of tokens to hypothetically redeem - * @param borrowAmount The amount of underlying to hypothetically borrow - * @return (possible error code (semi-opaque), - hypothetical account liquidity in excess of collateral requirements, - * hypothetical account shortfall below collateral requirements) - */ - function getHypotheticalAccountLiquidity( - address account, - address cTokenModify, - uint redeemTokens, - uint borrowAmount) public view returns (uint, uint, uint) { - (Error err, uint liquidity, uint shortfall) = getHypotheticalAccountLiquidityInternal(account, CToken(cTokenModify), redeemTokens, borrowAmount); - return (uint(err), liquidity, shortfall); - } - - /** - * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed - * @param cTokenModify The market to hypothetically redeem/borrow in - * @param account The account to determine liquidity for - * @param redeemTokens The number of tokens to hypothetically redeem - * @param borrowAmount The amount of underlying to hypothetically borrow - * @dev Note that we calculate the exchangeRateStored for each collateral cToken using stored data, - * without calculating accumulated interest. - * @return (possible error code, - hypothetical account liquidity in excess of collateral requirements, - * hypothetical account shortfall below collateral requirements) - */ - function getHypotheticalAccountLiquidityInternal( - address account, - CToken cTokenModify, - uint redeemTokens, - uint borrowAmount) internal view returns (Error, uint, uint) { - - AccountLiquidityLocalVars memory vars; // Holds all our calculation results - uint oErr; - MathError mErr; - - // For each asset the account is in - CToken[] memory assets = accountAssets[account]; - for (uint i = 0; i < assets.length; i++) { - CToken asset = assets[i]; - - // Read the balances and exchange rate from the cToken - (oErr, vars.cTokenBalance, vars.borrowBalance, vars.exchangeRateMantissa) = asset.getAccountSnapshot(account); - if (oErr != 0) { // semi-opaque error code, we assume NO_ERROR == 0 is invariant between upgrades - return (Error.SNAPSHOT_ERROR, 0, 0); - } - vars.collateralFactor = Exp({mantissa: markets[address(asset)].collateralFactorMantissa}); - vars.exchangeRate = Exp({mantissa: vars.exchangeRateMantissa}); - - // Get the normalized price of the asset - vars.oraclePriceMantissa = oracle.getUnderlyingPrice(asset); - if (vars.oraclePriceMantissa == 0) { - return (Error.PRICE_ERROR, 0, 0); - } - vars.oraclePrice = Exp({mantissa: vars.oraclePriceMantissa}); - - // Pre-compute a conversion factor from tokens -> ether (normalized price value) - (mErr, vars.tokensToEther) = mulExp3(vars.collateralFactor, vars.exchangeRate, vars.oraclePrice); - if (mErr != MathError.NO_ERROR) { - return (Error.MATH_ERROR, 0, 0); - } - - // sumCollateral += tokensToEther * cTokenBalance - (mErr, vars.sumCollateral) = mulScalarTruncateAddUInt(vars.tokensToEther, vars.cTokenBalance, vars.sumCollateral); - if (mErr != MathError.NO_ERROR) { - return (Error.MATH_ERROR, 0, 0); - } - - // sumBorrowPlusEffects += oraclePrice * borrowBalance - (mErr, vars.sumBorrowPlusEffects) = mulScalarTruncateAddUInt(vars.oraclePrice, vars.borrowBalance, vars.sumBorrowPlusEffects); - if (mErr != MathError.NO_ERROR) { - return (Error.MATH_ERROR, 0, 0); - } - - // Calculate effects of interacting with cTokenModify - if (asset == cTokenModify) { - // redeem effect - // sumBorrowPlusEffects += tokensToEther * redeemTokens - (mErr, vars.sumBorrowPlusEffects) = mulScalarTruncateAddUInt(vars.tokensToEther, redeemTokens, vars.sumBorrowPlusEffects); - if (mErr != MathError.NO_ERROR) { - return (Error.MATH_ERROR, 0, 0); - } - - // borrow effect - // sumBorrowPlusEffects += oraclePrice * borrowAmount - (mErr, vars.sumBorrowPlusEffects) = mulScalarTruncateAddUInt(vars.oraclePrice, borrowAmount, vars.sumBorrowPlusEffects); - if (mErr != MathError.NO_ERROR) { - return (Error.MATH_ERROR, 0, 0); - } - } - } - - // These are safe, as the underflow condition is checked first - if (vars.sumCollateral > vars.sumBorrowPlusEffects) { - return (Error.NO_ERROR, vars.sumCollateral - vars.sumBorrowPlusEffects, 0); - } else { - return (Error.NO_ERROR, 0, vars.sumBorrowPlusEffects - vars.sumCollateral); - } - } - - /** - * @notice Calculate number of tokens of collateral asset to seize given an underlying amount - * @dev Used in liquidation (called in cToken.liquidateBorrowFresh) - * @param cTokenBorrowed The address of the borrowed cToken - * @param cTokenCollateral The address of the collateral cToken - * @param actualRepayAmount The amount of cTokenBorrowed underlying to convert into cTokenCollateral tokens - * @return (errorCode, number of cTokenCollateral tokens to be seized in a liquidation) - */ - function liquidateCalculateSeizeTokens(address cTokenBorrowed, address cTokenCollateral, uint actualRepayAmount) external view returns (uint, uint) { - /* Read oracle prices for borrowed and collateral markets */ - uint priceBorrowedMantissa = oracle.getUnderlyingPrice(CToken(cTokenBorrowed)); - uint priceCollateralMantissa = oracle.getUnderlyingPrice(CToken(cTokenCollateral)); - if (priceBorrowedMantissa == 0 || priceCollateralMantissa == 0) { - return (uint(Error.PRICE_ERROR), 0); - } - - /* - * Get the exchange rate and calculate the number of collateral tokens to seize: - * seizeAmount = actualRepayAmount * liquidationIncentive * priceBorrowed / priceCollateral - * seizeTokens = seizeAmount / exchangeRate - * = actualRepayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate) - */ - uint exchangeRateMantissa = CToken(cTokenCollateral).exchangeRateStored(); // Note: reverts on error - uint seizeTokens; - Exp memory numerator; - Exp memory denominator; - Exp memory ratio; - MathError mathErr; - - (mathErr, numerator) = mulExp(liquidationIncentiveMantissa, priceBorrowedMantissa); - if (mathErr != MathError.NO_ERROR) { - return (uint(Error.MATH_ERROR), 0); - } - - (mathErr, denominator) = mulExp(priceCollateralMantissa, exchangeRateMantissa); - if (mathErr != MathError.NO_ERROR) { - return (uint(Error.MATH_ERROR), 0); - } - - (mathErr, ratio) = divExp(numerator, denominator); - if (mathErr != MathError.NO_ERROR) { - return (uint(Error.MATH_ERROR), 0); - } - - (mathErr, seizeTokens) = mulScalarTruncate(ratio, actualRepayAmount); - if (mathErr != MathError.NO_ERROR) { - return (uint(Error.MATH_ERROR), 0); - } - - return (uint(Error.NO_ERROR), seizeTokens); - } - - /*** Admin Functions ***/ - - /** - * @notice Sets a new price oracle for the comptroller - * @dev Admin function to set a new price oracle - * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) - */ - function _setPriceOracle(PriceOracle newOracle) public returns (uint) { - // Check caller is admin - if (msg.sender != admin) { - return fail(Error.UNAUTHORIZED, FailureInfo.SET_PRICE_ORACLE_OWNER_CHECK); - } - - // Track the old oracle for the comptroller - PriceOracle oldOracle = oracle; - - // Set comptroller's oracle to newOracle - oracle = newOracle; - - // Emit NewPriceOracle(oldOracle, newOracle) - emit NewPriceOracle(oldOracle, newOracle); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Sets the closeFactor used when liquidating borrows - * @dev Admin function to set closeFactor - * @param newCloseFactorMantissa New close factor, scaled by 1e18 - * @return uint 0=success, otherwise a failure. (See ErrorReporter for details) - */ - function _setCloseFactor(uint newCloseFactorMantissa) external returns (uint256) { - // Check caller is admin - if (msg.sender != admin) { - return fail(Error.UNAUTHORIZED, FailureInfo.SET_CLOSE_FACTOR_OWNER_CHECK); - } - - Exp memory newCloseFactorExp = Exp({mantissa: newCloseFactorMantissa}); - Exp memory lowLimit = Exp({mantissa: closeFactorMinMantissa}); - if (lessThanOrEqualExp(newCloseFactorExp, lowLimit)) { - return fail(Error.INVALID_CLOSE_FACTOR, FailureInfo.SET_CLOSE_FACTOR_VALIDATION); - } - - Exp memory highLimit = Exp({mantissa: closeFactorMaxMantissa}); - if (lessThanExp(highLimit, newCloseFactorExp)) { - return fail(Error.INVALID_CLOSE_FACTOR, FailureInfo.SET_CLOSE_FACTOR_VALIDATION); - } - - uint oldCloseFactorMantissa = closeFactorMantissa; - closeFactorMantissa = newCloseFactorMantissa; - emit NewCloseFactor(oldCloseFactorMantissa, closeFactorMantissa); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Sets the collateralFactor for a market - * @dev Admin function to set per-market collateralFactor - * @param cToken The market to set the factor on - * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18 - * @return uint 0=success, otherwise a failure. (See ErrorReporter for details) - */ - function _setCollateralFactor(CToken cToken, uint newCollateralFactorMantissa) external returns (uint256) { - // Check caller is admin - if (msg.sender != admin) { - return fail(Error.UNAUTHORIZED, FailureInfo.SET_COLLATERAL_FACTOR_OWNER_CHECK); - } - - // Verify market is listed - Market storage market = markets[address(cToken)]; - if (!market.isListed) { - return fail(Error.MARKET_NOT_LISTED, FailureInfo.SET_COLLATERAL_FACTOR_NO_EXISTS); - } - - Exp memory newCollateralFactorExp = Exp({mantissa: newCollateralFactorMantissa}); - - // Check collateral factor <= 0.9 - Exp memory highLimit = Exp({mantissa: collateralFactorMaxMantissa}); - if (lessThanExp(highLimit, newCollateralFactorExp)) { - return fail(Error.INVALID_COLLATERAL_FACTOR, FailureInfo.SET_COLLATERAL_FACTOR_VALIDATION); - } - - // If collateral factor != 0, fail if price == 0 - if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(cToken) == 0) { - return fail(Error.PRICE_ERROR, FailureInfo.SET_COLLATERAL_FACTOR_WITHOUT_PRICE); - } - - // Set market's collateral factor to new collateral factor, remember old value - uint oldCollateralFactorMantissa = market.collateralFactorMantissa; - market.collateralFactorMantissa = newCollateralFactorMantissa; - - // Emit event with asset, old collateral factor, and new collateral factor - emit NewCollateralFactor(cToken, oldCollateralFactorMantissa, newCollateralFactorMantissa); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Sets maxAssets which controls how many markets can be entered - * @dev Admin function to set maxAssets - * @param newMaxAssets New max assets - * @return uint 0=success, otherwise a failure. (See ErrorReporter for details) - */ - function _setMaxAssets(uint newMaxAssets) external returns (uint) { - // Check caller is admin - if (msg.sender != admin) { - return fail(Error.UNAUTHORIZED, FailureInfo.SET_MAX_ASSETS_OWNER_CHECK); - } - - uint oldMaxAssets = maxAssets; - maxAssets = newMaxAssets; - emit NewMaxAssets(oldMaxAssets, newMaxAssets); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Sets liquidationIncentive - * @dev Admin function to set liquidationIncentive - * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18 - * @return uint 0=success, otherwise a failure. (See ErrorReporter for details) - */ - function _setLiquidationIncentive(uint newLiquidationIncentiveMantissa) external returns (uint) { - // Check caller is admin - if (msg.sender != admin) { - return fail(Error.UNAUTHORIZED, FailureInfo.SET_LIQUIDATION_INCENTIVE_OWNER_CHECK); - } - - // Check de-scaled min <= newLiquidationIncentive <= max - Exp memory newLiquidationIncentive = Exp({mantissa: newLiquidationIncentiveMantissa}); - Exp memory minLiquidationIncentive = Exp({mantissa: liquidationIncentiveMinMantissa}); - if (lessThanExp(newLiquidationIncentive, minLiquidationIncentive)) { - return fail(Error.INVALID_LIQUIDATION_INCENTIVE, FailureInfo.SET_LIQUIDATION_INCENTIVE_VALIDATION); - } - - Exp memory maxLiquidationIncentive = Exp({mantissa: liquidationIncentiveMaxMantissa}); - if (lessThanExp(maxLiquidationIncentive, newLiquidationIncentive)) { - return fail(Error.INVALID_LIQUIDATION_INCENTIVE, FailureInfo.SET_LIQUIDATION_INCENTIVE_VALIDATION); - } - - // Save current value for use in log - uint oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa; - - // Set liquidation incentive to new incentive - liquidationIncentiveMantissa = newLiquidationIncentiveMantissa; - - // Emit event with old incentive, new incentive - emit NewLiquidationIncentive(oldLiquidationIncentiveMantissa, newLiquidationIncentiveMantissa); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Add the market to the markets mapping and set it as listed - * @dev Admin function to set isListed and add support for the market - * @param cToken The address of the market (token) to list - * @return uint 0=success, otherwise a failure. (See enum Error for details) - */ - function _supportMarket(CToken cToken) external returns (uint) { - if (msg.sender != admin) { - return fail(Error.UNAUTHORIZED, FailureInfo.SUPPORT_MARKET_OWNER_CHECK); - } - - if (markets[address(cToken)].isListed) { - return fail(Error.MARKET_ALREADY_LISTED, FailureInfo.SUPPORT_MARKET_EXISTS); - } - - cToken.isCToken(); // Sanity check to make sure its really a CToken - - markets[address(cToken)] = Market({isListed: true, isComped: false, collateralFactorMantissa: 0}); - emit MarketListed(cToken); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Admin function to change the Pause Guardian - * @param newPauseGuardian The address of the new Pause Guardian - * @return uint 0=success, otherwise a failure. (See enum Error for details) - */ - function _setPauseGuardian(address newPauseGuardian) public returns (uint) { - if (msg.sender != admin) { - return fail(Error.UNAUTHORIZED, FailureInfo.SET_PAUSE_GUARDIAN_OWNER_CHECK); - } - - // Save current value for inclusion in log - address oldPauseGuardian = pauseGuardian; - - // Store pauseGuardian with value newPauseGuardian - pauseGuardian = newPauseGuardian; - - // Emit NewPauseGuardian(OldPauseGuardian, NewPauseGuardian) - emit NewPauseGuardian(oldPauseGuardian, pauseGuardian); - - return uint(Error.NO_ERROR); - } - - function _setMintPaused(CToken cToken, bool state) public returns (bool) { - require(markets[address(cToken)].isListed, "cannot pause a market that is not listed"); - require(msg.sender == pauseGuardian || msg.sender == admin, "only pause guardian and admin can pause"); - require(msg.sender == admin || state == true, "only admin can unpause"); - - mintGuardianPaused[address(cToken)] = state; - emit ActionPaused(cToken, "Mint", state); - return state; - } - - function _setBorrowPaused(CToken cToken, bool state) public returns (bool) { - require(markets[address(cToken)].isListed, "cannot pause a market that is not listed"); - require(msg.sender == pauseGuardian || msg.sender == admin, "only pause guardian and admin can pause"); - require(msg.sender == admin || state == true, "only admin can unpause"); - - borrowGuardianPaused[address(cToken)] = state; - emit ActionPaused(cToken, "Borrow", state); - return state; - } - - function _setTransferPaused(bool state) public returns (bool) { - require(msg.sender == pauseGuardian || msg.sender == admin, "only pause guardian and admin can pause"); - require(msg.sender == admin || state == true, "only admin can unpause"); - - transferGuardianPaused = state; - emit ActionPaused("Transfer", state); - return state; - } - - function _setSeizePaused(bool state) public returns (bool) { - require(msg.sender == pauseGuardian || msg.sender == admin, "only pause guardian and admin can pause"); - require(msg.sender == admin || state == true, "only admin can unpause"); - - seizeGuardianPaused = state; - emit ActionPaused("Seize", state); - return state; - } - - function _become(Unitroller unitroller) public { - require(msg.sender == unitroller.admin(), "only unitroller admin can change brains"); - - uint changeStatus = unitroller._acceptImplementation(); - require(changeStatus == 0, "change not authorized"); - } -} diff --git a/contracts/ComptrollerG3.sol b/contracts/ComptrollerG3.sol deleted file mode 100644 index 2553ddc6f..000000000 --- a/contracts/ComptrollerG3.sol +++ /dev/null @@ -1,1394 +0,0 @@ -pragma solidity ^0.5.16; - -import "./CToken.sol"; -import "./ErrorReporter.sol"; -import "./Exponential.sol"; -import "./PriceOracle.sol"; -import "./ComptrollerInterface.sol"; -import "./ComptrollerStorage.sol"; -import "./Unitroller.sol"; -import "./Governance/Comp.sol"; - -/** - * @title Compound's Comptroller Contract - * @author Compound - */ -contract ComptrollerG3 is ComptrollerV3Storage, ComptrollerInterface, ComptrollerErrorReporter, Exponential { - /// @notice Emitted when an admin supports a market - event MarketListed(CToken cToken); - - /// @notice Emitted when an account enters a market - event MarketEntered(CToken cToken, address account); - - /// @notice Emitted when an account exits a market - event MarketExited(CToken cToken, address account); - - /// @notice Emitted when close factor is changed by admin - event NewCloseFactor(uint oldCloseFactorMantissa, uint newCloseFactorMantissa); - - /// @notice Emitted when a collateral factor is changed by admin - event NewCollateralFactor(CToken cToken, uint oldCollateralFactorMantissa, uint newCollateralFactorMantissa); - - /// @notice Emitted when liquidation incentive is changed by admin - event NewLiquidationIncentive(uint oldLiquidationIncentiveMantissa, uint newLiquidationIncentiveMantissa); - - /// @notice Emitted when maxAssets is changed by admin - event NewMaxAssets(uint oldMaxAssets, uint newMaxAssets); - - /// @notice Emitted when price oracle is changed - event NewPriceOracle(PriceOracle oldPriceOracle, PriceOracle newPriceOracle); - - /// @notice Emitted when pause guardian is changed - event NewPauseGuardian(address oldPauseGuardian, address newPauseGuardian); - - /// @notice Emitted when an action is paused globally - event ActionPaused(string action, bool pauseState); - - /// @notice Emitted when an action is paused on a market - event ActionPaused(CToken cToken, string action, bool pauseState); - - /// @notice Emitted when market comped status is changed - event MarketComped(CToken cToken, bool isComped); - - /// @notice Emitted when COMP rate is changed - event NewCompRate(uint oldCompRate, uint newCompRate); - - /// @notice Emitted when a new COMP speed is calculated for a market - event CompSpeedUpdated(CToken indexed cToken, uint newSpeed); - - /// @notice Emitted when COMP is distributed to a supplier - event DistributedSupplierComp(CToken indexed cToken, address indexed supplier, uint compDelta, uint compSupplyIndex); - - /// @notice Emitted when COMP is distributed to a borrower - event DistributedBorrowerComp(CToken indexed cToken, address indexed borrower, uint compDelta, uint compBorrowIndex); - - /// @notice The threshold above which the flywheel transfers COMP, in wei - uint public constant compClaimThreshold = 0.001e18; - - /// @notice The initial COMP index for a market - uint224 public constant compInitialIndex = 1e36; - - // closeFactorMantissa must be strictly greater than this value - uint internal constant closeFactorMinMantissa = 0.05e18; // 0.05 - - // closeFactorMantissa must not exceed this value - uint internal constant closeFactorMaxMantissa = 0.9e18; // 0.9 - - // No collateralFactorMantissa may exceed this value - uint internal constant collateralFactorMaxMantissa = 0.9e18; // 0.9 - - // liquidationIncentiveMantissa must be no less than this value - uint internal constant liquidationIncentiveMinMantissa = 1.0e18; // 1.0 - - // liquidationIncentiveMantissa must be no greater than this value - uint internal constant liquidationIncentiveMaxMantissa = 1.5e18; // 1.5 - - constructor() public { - admin = msg.sender; - } - - /*** Assets You Are In ***/ - - /** - * @notice Returns the assets an account has entered - * @param account The address of the account to pull assets for - * @return A dynamic list with the assets the account has entered - */ - function getAssetsIn(address account) external view returns (CToken[] memory) { - CToken[] memory assetsIn = accountAssets[account]; - - return assetsIn; - } - - /** - * @notice Returns whether the given account is entered in the given asset - * @param account The address of the account to check - * @param cToken The cToken to check - * @return True if the account is in the asset, otherwise false. - */ - function checkMembership(address account, CToken cToken) external view returns (bool) { - return markets[address(cToken)].accountMembership[account]; - } - - /** - * @notice Add assets to be included in account liquidity calculation - * @param cTokens The list of addresses of the cToken markets to be enabled - * @return Success indicator for whether each corresponding market was entered - */ - function enterMarkets(address[] memory cTokens) public returns (uint[] memory) { - uint len = cTokens.length; - - uint[] memory results = new uint[](len); - for (uint i = 0; i < len; i++) { - CToken cToken = CToken(cTokens[i]); - - results[i] = uint(addToMarketInternal(cToken, msg.sender)); - } - - return results; - } - - /** - * @notice Add the market to the borrower's "assets in" for liquidity calculations - * @param cToken The market to enter - * @param borrower The address of the account to modify - * @return Success indicator for whether the market was entered - */ - function addToMarketInternal(CToken cToken, address borrower) internal returns (Error) { - Market storage marketToJoin = markets[address(cToken)]; - - if (!marketToJoin.isListed) { - // market is not listed, cannot join - return Error.MARKET_NOT_LISTED; - } - - if (marketToJoin.accountMembership[borrower] == true) { - // already joined - return Error.NO_ERROR; - } - - if (accountAssets[borrower].length >= maxAssets) { - // no space, cannot join - return Error.TOO_MANY_ASSETS; - } - - // survived the gauntlet, add to list - // NOTE: we store these somewhat redundantly as a significant optimization - // this avoids having to iterate through the list for the most common use cases - // that is, only when we need to perform liquidity checks - // and not whenever we want to check if an account is in a particular market - marketToJoin.accountMembership[borrower] = true; - accountAssets[borrower].push(cToken); - - emit MarketEntered(cToken, borrower); - - return Error.NO_ERROR; - } - - /** - * @notice Removes asset from sender's account liquidity calculation - * @dev Sender must not have an outstanding borrow balance in the asset, - * or be providing neccessary collateral for an outstanding borrow. - * @param cTokenAddress The address of the asset to be removed - * @return Whether or not the account successfully exited the market - */ - function exitMarket(address cTokenAddress) external returns (uint) { - CToken cToken = CToken(cTokenAddress); - /* Get sender tokensHeld and amountOwed underlying from the cToken */ - (uint oErr, uint tokensHeld, uint amountOwed, ) = cToken.getAccountSnapshot(msg.sender); - require(oErr == 0, "exitMarket: getAccountSnapshot failed"); // semi-opaque error code - - /* Fail if the sender has a borrow balance */ - if (amountOwed != 0) { - return fail(Error.NONZERO_BORROW_BALANCE, FailureInfo.EXIT_MARKET_BALANCE_OWED); - } - - /* Fail if the sender is not permitted to redeem all of their tokens */ - uint allowed = redeemAllowedInternal(cTokenAddress, msg.sender, tokensHeld); - if (allowed != 0) { - return failOpaque(Error.REJECTION, FailureInfo.EXIT_MARKET_REJECTION, allowed); - } - - Market storage marketToExit = markets[address(cToken)]; - - /* Return true if the sender is not already ‘in’ the market */ - if (!marketToExit.accountMembership[msg.sender]) { - return uint(Error.NO_ERROR); - } - - /* Set cToken account membership to false */ - delete marketToExit.accountMembership[msg.sender]; - - /* Delete cToken from the account’s list of assets */ - // load into memory for faster iteration - CToken[] memory userAssetList = accountAssets[msg.sender]; - uint len = userAssetList.length; - uint assetIndex = len; - for (uint i = 0; i < len; i++) { - if (userAssetList[i] == cToken) { - assetIndex = i; - break; - } - } - - // We *must* have found the asset in the list or our redundant data structure is broken - assert(assetIndex < len); - - // copy last item in list to location of item to be removed, reduce length by 1 - CToken[] storage storedList = accountAssets[msg.sender]; - storedList[assetIndex] = storedList[storedList.length - 1]; - storedList.length--; - - emit MarketExited(cToken, msg.sender); - - return uint(Error.NO_ERROR); - } - - /*** Policy Hooks ***/ - - /** - * @notice Checks if the account should be allowed to mint tokens in the given market - * @param cToken The market to verify the mint against - * @param minter The account which would get the minted tokens - * @param mintAmount The amount of underlying being supplied to the market in exchange for tokens - * @return 0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol) - */ - function mintAllowed(address cToken, address minter, uint mintAmount) external returns (uint) { - // Pausing is a very serious situation - we revert to sound the alarms - require(!mintGuardianPaused[cToken], "mint is paused"); - - // Shh - currently unused - minter; - mintAmount; - - if (!markets[cToken].isListed) { - return uint(Error.MARKET_NOT_LISTED); - } - - // Keep the flywheel moving - updateCompSupplyIndex(cToken); - distributeSupplierComp(cToken, minter, false); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Validates mint and reverts on rejection. May emit logs. - * @param cToken Asset being minted - * @param minter The address minting the tokens - * @param actualMintAmount The amount of the underlying asset being minted - * @param mintTokens The number of tokens being minted - */ - function mintVerify(address cToken, address minter, uint actualMintAmount, uint mintTokens) external { - // Shh - currently unused - cToken; - minter; - actualMintAmount; - mintTokens; - - // Shh - we don't ever want this hook to be marked pure - if (false) { - maxAssets = maxAssets; - } - } - - /** - * @notice Checks if the account should be allowed to redeem tokens in the given market - * @param cToken The market to verify the redeem against - * @param redeemer The account which would redeem the tokens - * @param redeemTokens The number of cTokens to exchange for the underlying asset in the market - * @return 0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol) - */ - function redeemAllowed(address cToken, address redeemer, uint redeemTokens) external returns (uint) { - uint allowed = redeemAllowedInternal(cToken, redeemer, redeemTokens); - if (allowed != uint(Error.NO_ERROR)) { - return allowed; - } - - // Keep the flywheel moving - updateCompSupplyIndex(cToken); - distributeSupplierComp(cToken, redeemer, false); - - return uint(Error.NO_ERROR); - } - - function redeemAllowedInternal(address cToken, address redeemer, uint redeemTokens) internal view returns (uint) { - if (!markets[cToken].isListed) { - return uint(Error.MARKET_NOT_LISTED); - } - - /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */ - if (!markets[cToken].accountMembership[redeemer]) { - return uint(Error.NO_ERROR); - } - - /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */ - (Error err, , uint shortfall) = getHypotheticalAccountLiquidityInternal(redeemer, CToken(cToken), redeemTokens, 0); - if (err != Error.NO_ERROR) { - return uint(err); - } - if (shortfall > 0) { - return uint(Error.INSUFFICIENT_LIQUIDITY); - } - - return uint(Error.NO_ERROR); - } - - /** - * @notice Validates redeem and reverts on rejection. May emit logs. - * @param cToken Asset being redeemed - * @param redeemer The address redeeming the tokens - * @param redeemAmount The amount of the underlying asset being redeemed - * @param redeemTokens The number of tokens being redeemed - */ - function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) external { - // Shh - currently unused - cToken; - redeemer; - - // Require tokens is zero or amount is also zero - if (redeemTokens == 0 && redeemAmount > 0) { - revert("redeemTokens zero"); - } - } - - /** - * @notice Checks if the account should be allowed to borrow the underlying asset of the given market - * @param cToken The market to verify the borrow against - * @param borrower The account which would borrow the asset - * @param borrowAmount The amount of underlying the account would borrow - * @return 0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol) - */ - function borrowAllowed(address cToken, address borrower, uint borrowAmount) external returns (uint) { - // Pausing is a very serious situation - we revert to sound the alarms - require(!borrowGuardianPaused[cToken], "borrow is paused"); - - if (!markets[cToken].isListed) { - return uint(Error.MARKET_NOT_LISTED); - } - - if (!markets[cToken].accountMembership[borrower]) { - // only cTokens may call borrowAllowed if borrower not in market - require(msg.sender == cToken, "sender must be cToken"); - - // attempt to add borrower to the market - Error err = addToMarketInternal(CToken(msg.sender), borrower); - if (err != Error.NO_ERROR) { - return uint(err); - } - - // it should be impossible to break the important invariant - assert(markets[cToken].accountMembership[borrower]); - } - - if (oracle.getUnderlyingPrice(CToken(cToken)) == 0) { - return uint(Error.PRICE_ERROR); - } - - (Error err, , uint shortfall) = getHypotheticalAccountLiquidityInternal(borrower, CToken(cToken), 0, borrowAmount); - if (err != Error.NO_ERROR) { - return uint(err); - } - if (shortfall > 0) { - return uint(Error.INSUFFICIENT_LIQUIDITY); - } - - // Keep the flywheel moving - Exp memory borrowIndex = Exp({mantissa: CToken(cToken).borrowIndex()}); - updateCompBorrowIndex(cToken, borrowIndex); - distributeBorrowerComp(cToken, borrower, borrowIndex, false); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Validates borrow and reverts on rejection. May emit logs. - * @param cToken Asset whose underlying is being borrowed - * @param borrower The address borrowing the underlying - * @param borrowAmount The amount of the underlying asset requested to borrow - */ - function borrowVerify(address cToken, address borrower, uint borrowAmount) external { - // Shh - currently unused - cToken; - borrower; - borrowAmount; - - // Shh - we don't ever want this hook to be marked pure - if (false) { - maxAssets = maxAssets; - } - } - - /** - * @notice Checks if the account should be allowed to repay a borrow in the given market - * @param cToken The market to verify the repay against - * @param payer The account which would repay the asset - * @param borrower The account which would borrowed the asset - * @param repayAmount The amount of the underlying asset the account would repay - * @return 0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol) - */ - function repayBorrowAllowed( - address cToken, - address payer, - address borrower, - uint repayAmount) external returns (uint) { - // Shh - currently unused - payer; - borrower; - repayAmount; - - if (!markets[cToken].isListed) { - return uint(Error.MARKET_NOT_LISTED); - } - - // Keep the flywheel moving - Exp memory borrowIndex = Exp({mantissa: CToken(cToken).borrowIndex()}); - updateCompBorrowIndex(cToken, borrowIndex); - distributeBorrowerComp(cToken, borrower, borrowIndex, false); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Validates repayBorrow and reverts on rejection. May emit logs. - * @param cToken Asset being repaid - * @param payer The address repaying the borrow - * @param borrower The address of the borrower - * @param actualRepayAmount The amount of underlying being repaid - */ - function repayBorrowVerify( - address cToken, - address payer, - address borrower, - uint actualRepayAmount, - uint borrowerIndex) external { - // Shh - currently unused - cToken; - payer; - borrower; - actualRepayAmount; - borrowerIndex; - - // Shh - we don't ever want this hook to be marked pure - if (false) { - maxAssets = maxAssets; - } - } - - /** - * @notice Checks if the liquidation should be allowed to occur - * @param cTokenBorrowed Asset which was borrowed by the borrower - * @param cTokenCollateral Asset which was used as collateral and will be seized - * @param liquidator The address repaying the borrow and seizing the collateral - * @param borrower The address of the borrower - * @param repayAmount The amount of underlying being repaid - */ - function liquidateBorrowAllowed( - address cTokenBorrowed, - address cTokenCollateral, - address liquidator, - address borrower, - uint repayAmount) external returns (uint) { - // Shh - currently unused - liquidator; - - if (!markets[cTokenBorrowed].isListed || !markets[cTokenCollateral].isListed) { - return uint(Error.MARKET_NOT_LISTED); - } - - /* The borrower must have shortfall in order to be liquidatable */ - (Error err, , uint shortfall) = getAccountLiquidityInternal(borrower); - if (err != Error.NO_ERROR) { - return uint(err); - } - if (shortfall == 0) { - return uint(Error.INSUFFICIENT_SHORTFALL); - } - - /* The liquidator may not repay more than what is allowed by the closeFactor */ - uint borrowBalance = CToken(cTokenBorrowed).borrowBalanceStored(borrower); - (MathError mathErr, uint maxClose) = mulScalarTruncate(Exp({mantissa: closeFactorMantissa}), borrowBalance); - if (mathErr != MathError.NO_ERROR) { - return uint(Error.MATH_ERROR); - } - if (repayAmount > maxClose) { - return uint(Error.TOO_MUCH_REPAY); - } - - return uint(Error.NO_ERROR); - } - - /** - * @notice Validates liquidateBorrow and reverts on rejection. May emit logs. - * @param cTokenBorrowed Asset which was borrowed by the borrower - * @param cTokenCollateral Asset which was used as collateral and will be seized - * @param liquidator The address repaying the borrow and seizing the collateral - * @param borrower The address of the borrower - * @param actualRepayAmount The amount of underlying being repaid - */ - function liquidateBorrowVerify( - address cTokenBorrowed, - address cTokenCollateral, - address liquidator, - address borrower, - uint actualRepayAmount, - uint seizeTokens) external { - // Shh - currently unused - cTokenBorrowed; - cTokenCollateral; - liquidator; - borrower; - actualRepayAmount; - seizeTokens; - - // Shh - we don't ever want this hook to be marked pure - if (false) { - maxAssets = maxAssets; - } - } - - /** - * @notice Checks if the seizing of assets should be allowed to occur - * @param cTokenCollateral Asset which was used as collateral and will be seized - * @param cTokenBorrowed Asset which was borrowed by the borrower - * @param liquidator The address repaying the borrow and seizing the collateral - * @param borrower The address of the borrower - * @param seizeTokens The number of collateral tokens to seize - */ - function seizeAllowed( - address cTokenCollateral, - address cTokenBorrowed, - address liquidator, - address borrower, - uint seizeTokens) external returns (uint) { - // Pausing is a very serious situation - we revert to sound the alarms - require(!seizeGuardianPaused, "seize is paused"); - - // Shh - currently unused - seizeTokens; - - if (!markets[cTokenCollateral].isListed || !markets[cTokenBorrowed].isListed) { - return uint(Error.MARKET_NOT_LISTED); - } - - if (CToken(cTokenCollateral).comptroller() != CToken(cTokenBorrowed).comptroller()) { - return uint(Error.COMPTROLLER_MISMATCH); - } - - // Keep the flywheel moving - updateCompSupplyIndex(cTokenCollateral); - distributeSupplierComp(cTokenCollateral, borrower, false); - distributeSupplierComp(cTokenCollateral, liquidator, false); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Validates seize and reverts on rejection. May emit logs. - * @param cTokenCollateral Asset which was used as collateral and will be seized - * @param cTokenBorrowed Asset which was borrowed by the borrower - * @param liquidator The address repaying the borrow and seizing the collateral - * @param borrower The address of the borrower - * @param seizeTokens The number of collateral tokens to seize - */ - function seizeVerify( - address cTokenCollateral, - address cTokenBorrowed, - address liquidator, - address borrower, - uint seizeTokens) external { - // Shh - currently unused - cTokenCollateral; - cTokenBorrowed; - liquidator; - borrower; - seizeTokens; - - // Shh - we don't ever want this hook to be marked pure - if (false) { - maxAssets = maxAssets; - } - } - - /** - * @notice Checks if the account should be allowed to transfer tokens in the given market - * @param cToken The market to verify the transfer against - * @param src The account which sources the tokens - * @param dst The account which receives the tokens - * @param transferTokens The number of cTokens to transfer - * @return 0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol) - */ - function transferAllowed(address cToken, address src, address dst, uint transferTokens) external returns (uint) { - // Pausing is a very serious situation - we revert to sound the alarms - require(!transferGuardianPaused, "transfer is paused"); - - // Currently the only consideration is whether or not - // the src is allowed to redeem this many tokens - uint allowed = redeemAllowedInternal(cToken, src, transferTokens); - if (allowed != uint(Error.NO_ERROR)) { - return allowed; - } - - // Keep the flywheel moving - updateCompSupplyIndex(cToken); - distributeSupplierComp(cToken, src, false); - distributeSupplierComp(cToken, dst, false); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Validates transfer and reverts on rejection. May emit logs. - * @param cToken Asset being transferred - * @param src The account which sources the tokens - * @param dst The account which receives the tokens - * @param transferTokens The number of cTokens to transfer - */ - function transferVerify(address cToken, address src, address dst, uint transferTokens) external { - // Shh - currently unused - cToken; - src; - dst; - transferTokens; - - // Shh - we don't ever want this hook to be marked pure - if (false) { - maxAssets = maxAssets; - } - } - - /*** Liquidity/Liquidation Calculations ***/ - - /** - * @dev Local vars for avoiding stack-depth limits in calculating account liquidity. - * Note that `cTokenBalance` is the number of cTokens the account owns in the market, - * whereas `borrowBalance` is the amount of underlying that the account has borrowed. - */ - struct AccountLiquidityLocalVars { - uint sumCollateral; - uint sumBorrowPlusEffects; - uint cTokenBalance; - uint borrowBalance; - uint exchangeRateMantissa; - uint oraclePriceMantissa; - Exp collateralFactor; - Exp exchangeRate; - Exp oraclePrice; - Exp tokensToDenom; - } - - /** - * @notice Determine the current account liquidity wrt collateral requirements - * @return (possible error code (semi-opaque), - account liquidity in excess of collateral requirements, - * account shortfall below collateral requirements) - */ - function getAccountLiquidity(address account) public view returns (uint, uint, uint) { - (Error err, uint liquidity, uint shortfall) = getHypotheticalAccountLiquidityInternal(account, CToken(0), 0, 0); - - return (uint(err), liquidity, shortfall); - } - - /** - * @notice Determine the current account liquidity wrt collateral requirements - * @return (possible error code, - account liquidity in excess of collateral requirements, - * account shortfall below collateral requirements) - */ - function getAccountLiquidityInternal(address account) internal view returns (Error, uint, uint) { - return getHypotheticalAccountLiquidityInternal(account, CToken(0), 0, 0); - } - - /** - * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed - * @param cTokenModify The market to hypothetically redeem/borrow in - * @param account The account to determine liquidity for - * @param redeemTokens The number of tokens to hypothetically redeem - * @param borrowAmount The amount of underlying to hypothetically borrow - * @return (possible error code (semi-opaque), - hypothetical account liquidity in excess of collateral requirements, - * hypothetical account shortfall below collateral requirements) - */ - function getHypotheticalAccountLiquidity( - address account, - address cTokenModify, - uint redeemTokens, - uint borrowAmount) public view returns (uint, uint, uint) { - (Error err, uint liquidity, uint shortfall) = getHypotheticalAccountLiquidityInternal(account, CToken(cTokenModify), redeemTokens, borrowAmount); - return (uint(err), liquidity, shortfall); - } - - /** - * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed - * @param cTokenModify The market to hypothetically redeem/borrow in - * @param account The account to determine liquidity for - * @param redeemTokens The number of tokens to hypothetically redeem - * @param borrowAmount The amount of underlying to hypothetically borrow - * @dev Note that we calculate the exchangeRateStored for each collateral cToken using stored data, - * without calculating accumulated interest. - * @return (possible error code, - hypothetical account liquidity in excess of collateral requirements, - * hypothetical account shortfall below collateral requirements) - */ - function getHypotheticalAccountLiquidityInternal( - address account, - CToken cTokenModify, - uint redeemTokens, - uint borrowAmount) internal view returns (Error, uint, uint) { - - AccountLiquidityLocalVars memory vars; // Holds all our calculation results - uint oErr; - MathError mErr; - - // For each asset the account is in - CToken[] memory assets = accountAssets[account]; - for (uint i = 0; i < assets.length; i++) { - CToken asset = assets[i]; - - // Read the balances and exchange rate from the cToken - (oErr, vars.cTokenBalance, vars.borrowBalance, vars.exchangeRateMantissa) = asset.getAccountSnapshot(account); - if (oErr != 0) { // semi-opaque error code, we assume NO_ERROR == 0 is invariant between upgrades - return (Error.SNAPSHOT_ERROR, 0, 0); - } - vars.collateralFactor = Exp({mantissa: markets[address(asset)].collateralFactorMantissa}); - vars.exchangeRate = Exp({mantissa: vars.exchangeRateMantissa}); - - // Get the normalized price of the asset - vars.oraclePriceMantissa = oracle.getUnderlyingPrice(asset); - if (vars.oraclePriceMantissa == 0) { - return (Error.PRICE_ERROR, 0, 0); - } - vars.oraclePrice = Exp({mantissa: vars.oraclePriceMantissa}); - - // Pre-compute a conversion factor from tokens -> ether (normalized price value) - (mErr, vars.tokensToDenom) = mulExp3(vars.collateralFactor, vars.exchangeRate, vars.oraclePrice); - if (mErr != MathError.NO_ERROR) { - return (Error.MATH_ERROR, 0, 0); - } - - // sumCollateral += tokensToDenom * cTokenBalance - (mErr, vars.sumCollateral) = mulScalarTruncateAddUInt(vars.tokensToDenom, vars.cTokenBalance, vars.sumCollateral); - if (mErr != MathError.NO_ERROR) { - return (Error.MATH_ERROR, 0, 0); - } - - // sumBorrowPlusEffects += oraclePrice * borrowBalance - (mErr, vars.sumBorrowPlusEffects) = mulScalarTruncateAddUInt(vars.oraclePrice, vars.borrowBalance, vars.sumBorrowPlusEffects); - if (mErr != MathError.NO_ERROR) { - return (Error.MATH_ERROR, 0, 0); - } - - // Calculate effects of interacting with cTokenModify - if (asset == cTokenModify) { - // redeem effect - // sumBorrowPlusEffects += tokensToDenom * redeemTokens - (mErr, vars.sumBorrowPlusEffects) = mulScalarTruncateAddUInt(vars.tokensToDenom, redeemTokens, vars.sumBorrowPlusEffects); - if (mErr != MathError.NO_ERROR) { - return (Error.MATH_ERROR, 0, 0); - } - - // borrow effect - // sumBorrowPlusEffects += oraclePrice * borrowAmount - (mErr, vars.sumBorrowPlusEffects) = mulScalarTruncateAddUInt(vars.oraclePrice, borrowAmount, vars.sumBorrowPlusEffects); - if (mErr != MathError.NO_ERROR) { - return (Error.MATH_ERROR, 0, 0); - } - } - } - - // These are safe, as the underflow condition is checked first - if (vars.sumCollateral > vars.sumBorrowPlusEffects) { - return (Error.NO_ERROR, vars.sumCollateral - vars.sumBorrowPlusEffects, 0); - } else { - return (Error.NO_ERROR, 0, vars.sumBorrowPlusEffects - vars.sumCollateral); - } - } - - /** - * @notice Calculate number of tokens of collateral asset to seize given an underlying amount - * @dev Used in liquidation (called in cToken.liquidateBorrowFresh) - * @param cTokenBorrowed The address of the borrowed cToken - * @param cTokenCollateral The address of the collateral cToken - * @param actualRepayAmount The amount of cTokenBorrowed underlying to convert into cTokenCollateral tokens - * @return (errorCode, number of cTokenCollateral tokens to be seized in a liquidation) - */ - function liquidateCalculateSeizeTokens(address cTokenBorrowed, address cTokenCollateral, uint actualRepayAmount) external view returns (uint, uint) { - /* Read oracle prices for borrowed and collateral markets */ - uint priceBorrowedMantissa = oracle.getUnderlyingPrice(CToken(cTokenBorrowed)); - uint priceCollateralMantissa = oracle.getUnderlyingPrice(CToken(cTokenCollateral)); - if (priceBorrowedMantissa == 0 || priceCollateralMantissa == 0) { - return (uint(Error.PRICE_ERROR), 0); - } - - /* - * Get the exchange rate and calculate the number of collateral tokens to seize: - * seizeAmount = actualRepayAmount * liquidationIncentive * priceBorrowed / priceCollateral - * seizeTokens = seizeAmount / exchangeRate - * = actualRepayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate) - */ - uint exchangeRateMantissa = CToken(cTokenCollateral).exchangeRateStored(); // Note: reverts on error - uint seizeTokens; - Exp memory numerator; - Exp memory denominator; - Exp memory ratio; - MathError mathErr; - - (mathErr, numerator) = mulExp(liquidationIncentiveMantissa, priceBorrowedMantissa); - if (mathErr != MathError.NO_ERROR) { - return (uint(Error.MATH_ERROR), 0); - } - - (mathErr, denominator) = mulExp(priceCollateralMantissa, exchangeRateMantissa); - if (mathErr != MathError.NO_ERROR) { - return (uint(Error.MATH_ERROR), 0); - } - - (mathErr, ratio) = divExp(numerator, denominator); - if (mathErr != MathError.NO_ERROR) { - return (uint(Error.MATH_ERROR), 0); - } - - (mathErr, seizeTokens) = mulScalarTruncate(ratio, actualRepayAmount); - if (mathErr != MathError.NO_ERROR) { - return (uint(Error.MATH_ERROR), 0); - } - - return (uint(Error.NO_ERROR), seizeTokens); - } - - /*** Admin Functions ***/ - - /** - * @notice Sets a new price oracle for the comptroller - * @dev Admin function to set a new price oracle - * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) - */ - function _setPriceOracle(PriceOracle newOracle) public returns (uint) { - // Check caller is admin - if (msg.sender != admin) { - return fail(Error.UNAUTHORIZED, FailureInfo.SET_PRICE_ORACLE_OWNER_CHECK); - } - - // Track the old oracle for the comptroller - PriceOracle oldOracle = oracle; - - // Set comptroller's oracle to newOracle - oracle = newOracle; - - // Emit NewPriceOracle(oldOracle, newOracle) - emit NewPriceOracle(oldOracle, newOracle); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Sets the closeFactor used when liquidating borrows - * @dev Admin function to set closeFactor - * @param newCloseFactorMantissa New close factor, scaled by 1e18 - * @return uint 0=success, otherwise a failure. (See ErrorReporter for details) - */ - function _setCloseFactor(uint newCloseFactorMantissa) external returns (uint) { - // Check caller is admin - if (msg.sender != admin) { - return fail(Error.UNAUTHORIZED, FailureInfo.SET_CLOSE_FACTOR_OWNER_CHECK); - } - - Exp memory newCloseFactorExp = Exp({mantissa: newCloseFactorMantissa}); - Exp memory lowLimit = Exp({mantissa: closeFactorMinMantissa}); - if (lessThanOrEqualExp(newCloseFactorExp, lowLimit)) { - return fail(Error.INVALID_CLOSE_FACTOR, FailureInfo.SET_CLOSE_FACTOR_VALIDATION); - } - - Exp memory highLimit = Exp({mantissa: closeFactorMaxMantissa}); - if (lessThanExp(highLimit, newCloseFactorExp)) { - return fail(Error.INVALID_CLOSE_FACTOR, FailureInfo.SET_CLOSE_FACTOR_VALIDATION); - } - - uint oldCloseFactorMantissa = closeFactorMantissa; - closeFactorMantissa = newCloseFactorMantissa; - emit NewCloseFactor(oldCloseFactorMantissa, closeFactorMantissa); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Sets the collateralFactor for a market - * @dev Admin function to set per-market collateralFactor - * @param cToken The market to set the factor on - * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18 - * @return uint 0=success, otherwise a failure. (See ErrorReporter for details) - */ - function _setCollateralFactor(CToken cToken, uint newCollateralFactorMantissa) external returns (uint) { - // Check caller is admin - if (msg.sender != admin) { - return fail(Error.UNAUTHORIZED, FailureInfo.SET_COLLATERAL_FACTOR_OWNER_CHECK); - } - - // Verify market is listed - Market storage market = markets[address(cToken)]; - if (!market.isListed) { - return fail(Error.MARKET_NOT_LISTED, FailureInfo.SET_COLLATERAL_FACTOR_NO_EXISTS); - } - - Exp memory newCollateralFactorExp = Exp({mantissa: newCollateralFactorMantissa}); - - // Check collateral factor <= 0.9 - Exp memory highLimit = Exp({mantissa: collateralFactorMaxMantissa}); - if (lessThanExp(highLimit, newCollateralFactorExp)) { - return fail(Error.INVALID_COLLATERAL_FACTOR, FailureInfo.SET_COLLATERAL_FACTOR_VALIDATION); - } - - // If collateral factor != 0, fail if price == 0 - if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(cToken) == 0) { - return fail(Error.PRICE_ERROR, FailureInfo.SET_COLLATERAL_FACTOR_WITHOUT_PRICE); - } - - // Set market's collateral factor to new collateral factor, remember old value - uint oldCollateralFactorMantissa = market.collateralFactorMantissa; - market.collateralFactorMantissa = newCollateralFactorMantissa; - - // Emit event with asset, old collateral factor, and new collateral factor - emit NewCollateralFactor(cToken, oldCollateralFactorMantissa, newCollateralFactorMantissa); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Sets maxAssets which controls how many markets can be entered - * @dev Admin function to set maxAssets - * @param newMaxAssets New max assets - * @return uint 0=success, otherwise a failure. (See ErrorReporter for details) - */ - function _setMaxAssets(uint newMaxAssets) external returns (uint) { - // Check caller is admin - if (msg.sender != admin) { - return fail(Error.UNAUTHORIZED, FailureInfo.SET_MAX_ASSETS_OWNER_CHECK); - } - - uint oldMaxAssets = maxAssets; - maxAssets = newMaxAssets; - emit NewMaxAssets(oldMaxAssets, newMaxAssets); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Sets liquidationIncentive - * @dev Admin function to set liquidationIncentive - * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18 - * @return uint 0=success, otherwise a failure. (See ErrorReporter for details) - */ - function _setLiquidationIncentive(uint newLiquidationIncentiveMantissa) external returns (uint) { - // Check caller is admin - if (msg.sender != admin) { - return fail(Error.UNAUTHORIZED, FailureInfo.SET_LIQUIDATION_INCENTIVE_OWNER_CHECK); - } - - // Check de-scaled min <= newLiquidationIncentive <= max - Exp memory newLiquidationIncentive = Exp({mantissa: newLiquidationIncentiveMantissa}); - Exp memory minLiquidationIncentive = Exp({mantissa: liquidationIncentiveMinMantissa}); - if (lessThanExp(newLiquidationIncentive, minLiquidationIncentive)) { - return fail(Error.INVALID_LIQUIDATION_INCENTIVE, FailureInfo.SET_LIQUIDATION_INCENTIVE_VALIDATION); - } - - Exp memory maxLiquidationIncentive = Exp({mantissa: liquidationIncentiveMaxMantissa}); - if (lessThanExp(maxLiquidationIncentive, newLiquidationIncentive)) { - return fail(Error.INVALID_LIQUIDATION_INCENTIVE, FailureInfo.SET_LIQUIDATION_INCENTIVE_VALIDATION); - } - - // Save current value for use in log - uint oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa; - - // Set liquidation incentive to new incentive - liquidationIncentiveMantissa = newLiquidationIncentiveMantissa; - - // Emit event with old incentive, new incentive - emit NewLiquidationIncentive(oldLiquidationIncentiveMantissa, newLiquidationIncentiveMantissa); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Add the market to the markets mapping and set it as listed - * @dev Admin function to set isListed and add support for the market - * @param cToken The address of the market (token) to list - * @return uint 0=success, otherwise a failure. (See enum Error for details) - */ - function _supportMarket(CToken cToken) external returns (uint) { - if (msg.sender != admin) { - return fail(Error.UNAUTHORIZED, FailureInfo.SUPPORT_MARKET_OWNER_CHECK); - } - - if (markets[address(cToken)].isListed) { - return fail(Error.MARKET_ALREADY_LISTED, FailureInfo.SUPPORT_MARKET_EXISTS); - } - - cToken.isCToken(); // Sanity check to make sure its really a CToken - - markets[address(cToken)] = Market({isListed: true, isComped: false, collateralFactorMantissa: 0}); - - _addMarketInternal(address(cToken)); - - emit MarketListed(cToken); - - return uint(Error.NO_ERROR); - } - - function _addMarketInternal(address cToken) internal { - for (uint i = 0; i < allMarkets.length; i ++) { - require(allMarkets[i] != CToken(cToken), "market already added"); - } - allMarkets.push(CToken(cToken)); - } - - /** - * @notice Admin function to change the Pause Guardian - * @param newPauseGuardian The address of the new Pause Guardian - * @return uint 0=success, otherwise a failure. (See enum Error for details) - */ - function _setPauseGuardian(address newPauseGuardian) public returns (uint) { - if (msg.sender != admin) { - return fail(Error.UNAUTHORIZED, FailureInfo.SET_PAUSE_GUARDIAN_OWNER_CHECK); - } - - // Save current value for inclusion in log - address oldPauseGuardian = pauseGuardian; - - // Store pauseGuardian with value newPauseGuardian - pauseGuardian = newPauseGuardian; - - // Emit NewPauseGuardian(OldPauseGuardian, NewPauseGuardian) - emit NewPauseGuardian(oldPauseGuardian, pauseGuardian); - - return uint(Error.NO_ERROR); - } - - function _setMintPaused(CToken cToken, bool state) public returns (bool) { - require(markets[address(cToken)].isListed, "cannot pause a market that is not listed"); - require(msg.sender == pauseGuardian || msg.sender == admin, "only pause guardian and admin can pause"); - require(msg.sender == admin || state == true, "only admin can unpause"); - - mintGuardianPaused[address(cToken)] = state; - emit ActionPaused(cToken, "Mint", state); - return state; - } - - function _setBorrowPaused(CToken cToken, bool state) public returns (bool) { - require(markets[address(cToken)].isListed, "cannot pause a market that is not listed"); - require(msg.sender == pauseGuardian || msg.sender == admin, "only pause guardian and admin can pause"); - require(msg.sender == admin || state == true, "only admin can unpause"); - - borrowGuardianPaused[address(cToken)] = state; - emit ActionPaused(cToken, "Borrow", state); - return state; - } - - function _setTransferPaused(bool state) public returns (bool) { - require(msg.sender == pauseGuardian || msg.sender == admin, "only pause guardian and admin can pause"); - require(msg.sender == admin || state == true, "only admin can unpause"); - - transferGuardianPaused = state; - emit ActionPaused("Transfer", state); - return state; - } - - function _setSeizePaused(bool state) public returns (bool) { - require(msg.sender == pauseGuardian || msg.sender == admin, "only pause guardian and admin can pause"); - require(msg.sender == admin || state == true, "only admin can unpause"); - - seizeGuardianPaused = state; - emit ActionPaused("Seize", state); - return state; - } - - function _become(Unitroller unitroller, uint compRate_, address[] memory compMarketsToAdd, address[] memory otherMarketsToAdd) public { - require(msg.sender == unitroller.admin(), "only unitroller admin can change brains"); - require(unitroller._acceptImplementation() == 0, "change not authorized"); - - ComptrollerG3(address(unitroller))._becomeG3(compRate_, compMarketsToAdd, otherMarketsToAdd); - } - - function _becomeG3(uint compRate_, address[] memory compMarketsToAdd, address[] memory otherMarketsToAdd) public { - require(msg.sender == comptrollerImplementation, "only brains can become itself"); - - for (uint i = 0; i < compMarketsToAdd.length; i++) { - _addMarketInternal(address(compMarketsToAdd[i])); - } - - for (uint i = 0; i < otherMarketsToAdd.length; i++) { - _addMarketInternal(address(otherMarketsToAdd[i])); - } - - _setCompRate(compRate_); - _addCompMarkets(compMarketsToAdd); - } - - /** - * @notice Checks caller is admin, or this contract is becoming the new implementation - */ - function adminOrInitializing() internal view returns (bool) { - return msg.sender == admin || msg.sender == comptrollerImplementation; - } - - /*** Comp Distribution ***/ - - /** - * @notice Recalculate and update COMP speeds for all COMP markets - */ - function refreshCompSpeeds() public { - CToken[] memory allMarkets_ = allMarkets; - - for (uint i = 0; i < allMarkets_.length; i++) { - CToken cToken = allMarkets_[i]; - Exp memory borrowIndex = Exp({mantissa: cToken.borrowIndex()}); - updateCompSupplyIndex(address(cToken)); - updateCompBorrowIndex(address(cToken), borrowIndex); - } - - Exp memory totalUtility = Exp({mantissa: 0}); - Exp[] memory utilities = new Exp[](allMarkets_.length); - for (uint i = 0; i < allMarkets_.length; i++) { - CToken cToken = allMarkets_[i]; - if (markets[address(cToken)].isComped) { - Exp memory assetPrice = Exp({mantissa: oracle.getUnderlyingPrice(cToken)}); - Exp memory interestPerBlock = mul_(Exp({mantissa: cToken.borrowRatePerBlock()}), cToken.totalBorrows()); - Exp memory utility = mul_(interestPerBlock, assetPrice); - utilities[i] = utility; - totalUtility = add_(totalUtility, utility); - } - } - - for (uint i = 0; i < allMarkets_.length; i++) { - CToken cToken = allMarkets[i]; - uint newSpeed = totalUtility.mantissa > 0 ? mul_(compRate, div_(utilities[i], totalUtility)) : 0; - compSpeeds[address(cToken)] = newSpeed; - emit CompSpeedUpdated(cToken, newSpeed); - } - } - - /** - * @notice Accrue COMP to the market by updating the supply index - * @param cToken The market whose supply index to update - */ - function updateCompSupplyIndex(address cToken) internal { - CompMarketState storage supplyState = compSupplyState[cToken]; - uint supplySpeed = compSpeeds[cToken]; - uint blockNumber = getBlockNumber(); - uint deltaBlocks = sub_(blockNumber, uint(supplyState.block)); - if (deltaBlocks > 0 && supplySpeed > 0) { - uint supplyTokens = CToken(cToken).totalSupply(); - uint compAccrued = mul_(deltaBlocks, supplySpeed); - Double memory ratio = supplyTokens > 0 ? fraction(compAccrued, supplyTokens) : Double({mantissa: 0}); - Double memory index = add_(Double({mantissa: supplyState.index}), ratio); - compSupplyState[cToken] = CompMarketState({ - index: safe224(index.mantissa, "new index exceeds 224 bits"), - block: safe32(blockNumber, "block number exceeds 32 bits") - }); - } else if (deltaBlocks > 0) { - supplyState.block = safe32(blockNumber, "block number exceeds 32 bits"); - } - } - - /** - * @notice Accrue COMP to the market by updating the borrow index - * @param cToken The market whose borrow index to update - */ - function updateCompBorrowIndex(address cToken, Exp memory marketBorrowIndex) internal { - CompMarketState storage borrowState = compBorrowState[cToken]; - uint borrowSpeed = compSpeeds[cToken]; - uint blockNumber = getBlockNumber(); - uint deltaBlocks = sub_(blockNumber, uint(borrowState.block)); - if (deltaBlocks > 0 && borrowSpeed > 0) { - uint borrowAmount = div_(CToken(cToken).totalBorrows(), marketBorrowIndex); - uint compAccrued = mul_(deltaBlocks, borrowSpeed); - Double memory ratio = borrowAmount > 0 ? fraction(compAccrued, borrowAmount) : Double({mantissa: 0}); - Double memory index = add_(Double({mantissa: borrowState.index}), ratio); - compBorrowState[cToken] = CompMarketState({ - index: safe224(index.mantissa, "new index exceeds 224 bits"), - block: safe32(blockNumber, "block number exceeds 32 bits") - }); - } else if (deltaBlocks > 0) { - borrowState.block = safe32(blockNumber, "block number exceeds 32 bits"); - } - } - - /** - * @notice Calculate COMP accrued by a supplier and possibly transfer it to them - * @param cToken The market in which the supplier is interacting - * @param supplier The address of the supplier to distribute COMP to - */ - function distributeSupplierComp(address cToken, address supplier, bool distributeAll) internal { - CompMarketState storage supplyState = compSupplyState[cToken]; - Double memory supplyIndex = Double({mantissa: supplyState.index}); - Double memory supplierIndex = Double({mantissa: compSupplierIndex[cToken][supplier]}); - compSupplierIndex[cToken][supplier] = supplyIndex.mantissa; - - if (supplierIndex.mantissa == 0 && supplyIndex.mantissa > 0) { - supplierIndex.mantissa = compInitialIndex; - } - - Double memory deltaIndex = sub_(supplyIndex, supplierIndex); - uint supplierTokens = CToken(cToken).balanceOf(supplier); - uint supplierDelta = mul_(supplierTokens, deltaIndex); - uint supplierAccrued = add_(compAccrued[supplier], supplierDelta); - compAccrued[supplier] = transferComp(supplier, supplierAccrued, distributeAll ? 0 : compClaimThreshold); - emit DistributedSupplierComp(CToken(cToken), supplier, supplierDelta, supplyIndex.mantissa); - } - - /** - * @notice Calculate COMP accrued by a borrower and possibly transfer it to them - * @dev Borrowers will not begin to accrue until after the first interaction with the protocol. - * @param cToken The market in which the borrower is interacting - * @param borrower The address of the borrower to distribute COMP to - */ - function distributeBorrowerComp(address cToken, address borrower, Exp memory marketBorrowIndex, bool distributeAll) internal { - CompMarketState storage borrowState = compBorrowState[cToken]; - Double memory borrowIndex = Double({mantissa: borrowState.index}); - Double memory borrowerIndex = Double({mantissa: compBorrowerIndex[cToken][borrower]}); - compBorrowerIndex[cToken][borrower] = borrowIndex.mantissa; - - if (borrowerIndex.mantissa > 0) { - Double memory deltaIndex = sub_(borrowIndex, borrowerIndex); - uint borrowerAmount = div_(CToken(cToken).borrowBalanceStored(borrower), marketBorrowIndex); - uint borrowerDelta = mul_(borrowerAmount, deltaIndex); - uint borrowerAccrued = add_(compAccrued[borrower], borrowerDelta); - compAccrued[borrower] = transferComp(borrower, borrowerAccrued, distributeAll ? 0 : compClaimThreshold); - emit DistributedBorrowerComp(CToken(cToken), borrower, borrowerDelta, borrowIndex.mantissa); - } - } - - /** - * @notice Transfer COMP to the user, if they are above the threshold - * @dev Note: If there is not enough COMP, we do not perform the transfer all. - * @param user The address of the user to transfer COMP to - * @param userAccrued The amount of COMP to (possibly) transfer - * @return The amount of COMP which was NOT transferred to the user - */ - function transferComp(address user, uint userAccrued, uint threshold) internal returns (uint) { - if (userAccrued >= threshold && userAccrued > 0) { - Comp comp = Comp(getCompAddress()); - uint compRemaining = comp.balanceOf(address(this)); - if (userAccrued <= compRemaining) { - comp.transfer(user, userAccrued); - return 0; - } - } - return userAccrued; - } - - /** - * @notice Claim all the comp accrued by holder in all markets - * @param holder The address to claim COMP for - */ - function claimComp(address holder) public { - return claimComp(holder, allMarkets); - } - - /** - * @notice Claim all the comp accrued by holder in the specified markets - * @param holder The address to claim COMP for - * @param cTokens The list of markets to claim COMP in - */ - function claimComp(address holder, CToken[] memory cTokens) public { - address[] memory holders = new address[](1); - holders[0] = holder; - claimComp(holders, cTokens, true, true); - } - - /** - * @notice Claim all comp accrued by the holders - * @param holders The addresses to claim COMP for - * @param cTokens The list of markets to claim COMP in - * @param borrowers Whether or not to claim COMP earned by borrowing - * @param suppliers Whether or not to claim COMP earned by supplying - */ - function claimComp(address[] memory holders, CToken[] memory cTokens, bool borrowers, bool suppliers) public { - for (uint i = 0; i < cTokens.length; i++) { - CToken cToken = cTokens[i]; - require(markets[address(cToken)].isListed, "market must be listed"); - if (borrowers == true) { - Exp memory borrowIndex = Exp({mantissa: cToken.borrowIndex()}); - updateCompBorrowIndex(address(cToken), borrowIndex); - for (uint j = 0; j < holders.length; j++) { - distributeBorrowerComp(address(cToken), holders[j], borrowIndex, true); - } - } - if (suppliers == true) { - updateCompSupplyIndex(address(cToken)); - for (uint j = 0; j < holders.length; j++) { - distributeSupplierComp(address(cToken), holders[j], true); - } - } - } - } - - /*** Comp Distribution Admin ***/ - - /** - * @notice Set the amount of COMP distributed per block - * @param compRate_ The amount of COMP wei per block to distribute - */ - function _setCompRate(uint compRate_) public { - require(adminOrInitializing(), "only admin can change comp rate"); - - uint oldRate = compRate; - compRate = compRate_; - emit NewCompRate(oldRate, compRate_); - - refreshCompSpeeds(); - } - - /** - * @notice Add markets to compMarkets, allowing them to earn COMP in the flywheel - * @param cTokens The addresses of the markets to add - */ - function _addCompMarkets(address[] memory cTokens) public { - require(adminOrInitializing(), "only admin can add comp market"); - - for (uint i = 0; i < cTokens.length; i++) { - _addCompMarketInternal(cTokens[i]); - } - - refreshCompSpeeds(); - } - - function _addCompMarketInternal(address cToken) internal { - Market storage market = markets[cToken]; - require(market.isListed == true, "comp market is not listed"); - require(market.isComped == false, "comp market already added"); - - market.isComped = true; - emit MarketComped(CToken(cToken), true); - - if (compSupplyState[cToken].index == 0 && compSupplyState[cToken].block == 0) { - compSupplyState[cToken] = CompMarketState({ - index: compInitialIndex, - block: safe32(getBlockNumber(), "block number exceeds 32 bits") - }); - } - - if (compBorrowState[cToken].index == 0 && compBorrowState[cToken].block == 0) { - compBorrowState[cToken] = CompMarketState({ - index: compInitialIndex, - block: safe32(getBlockNumber(), "block number exceeds 32 bits") - }); - } - } - - /** - * @notice Remove a market from compMarkets, preventing it from earning COMP in the flywheel - * @param cToken The address of the market to drop - */ - function _dropCompMarket(address cToken) public { - require(msg.sender == admin, "only admin can drop comp market"); - - Market storage market = markets[cToken]; - require(market.isComped == true, "market is not a comp market"); - - market.isComped = false; - emit MarketComped(CToken(cToken), false); - - refreshCompSpeeds(); - } - - /** - * @notice Return all of the markets - * @dev The automatic getter may be used to access an individual market. - * @return The list of market addresses - */ - function getAllMarkets() public view returns (CToken[] memory) { - return allMarkets; - } - - function getBlockNumber() public view returns (uint) { - return block.number; - } - - /** - * @notice Return the address of the COMP token - * @return The address of COMP - */ - function getCompAddress() public view returns (address) { - return 0xc00e94Cb662C3520282E6f5717214004A7f26888; - } -} diff --git a/contracts/ComptrollerG4.sol b/contracts/ComptrollerG4.sol deleted file mode 100644 index 8563ef4e6..000000000 --- a/contracts/ComptrollerG4.sol +++ /dev/null @@ -1,1381 +0,0 @@ -pragma solidity ^0.5.16; - -import "./CToken.sol"; -import "./ErrorReporter.sol"; -import "./Exponential.sol"; -import "./PriceOracle.sol"; -import "./ComptrollerInterface.sol"; -import "./ComptrollerStorage.sol"; -import "./Unitroller.sol"; -import "./Governance/Comp.sol"; - -/** - * @title Compound's Comptroller Contract - * @author Compound - */ -contract ComptrollerG4 is ComptrollerV3Storage, ComptrollerInterface, ComptrollerErrorReporter, Exponential { - /// @notice Emitted when an admin supports a market - event MarketListed(CToken cToken); - - /// @notice Emitted when an account enters a market - event MarketEntered(CToken cToken, address account); - - /// @notice Emitted when an account exits a market - event MarketExited(CToken cToken, address account); - - /// @notice Emitted when close factor is changed by admin - event NewCloseFactor(uint oldCloseFactorMantissa, uint newCloseFactorMantissa); - - /// @notice Emitted when a collateral factor is changed by admin - event NewCollateralFactor(CToken cToken, uint oldCollateralFactorMantissa, uint newCollateralFactorMantissa); - - /// @notice Emitted when liquidation incentive is changed by admin - event NewLiquidationIncentive(uint oldLiquidationIncentiveMantissa, uint newLiquidationIncentiveMantissa); - - /// @notice Emitted when maxAssets is changed by admin - event NewMaxAssets(uint oldMaxAssets, uint newMaxAssets); - - /// @notice Emitted when price oracle is changed - event NewPriceOracle(PriceOracle oldPriceOracle, PriceOracle newPriceOracle); - - /// @notice Emitted when pause guardian is changed - event NewPauseGuardian(address oldPauseGuardian, address newPauseGuardian); - - /// @notice Emitted when an action is paused globally - event ActionPaused(string action, bool pauseState); - - /// @notice Emitted when an action is paused on a market - event ActionPaused(CToken cToken, string action, bool pauseState); - - /// @notice Emitted when market comped status is changed - event MarketComped(CToken cToken, bool isComped); - - /// @notice Emitted when COMP rate is changed - event NewCompRate(uint oldCompRate, uint newCompRate); - - /// @notice Emitted when a new COMP speed is calculated for a market - event CompSpeedUpdated(CToken indexed cToken, uint newSpeed); - - /// @notice Emitted when COMP is distributed to a supplier - event DistributedSupplierComp(CToken indexed cToken, address indexed supplier, uint compDelta, uint compSupplyIndex); - - /// @notice Emitted when COMP is distributed to a borrower - event DistributedBorrowerComp(CToken indexed cToken, address indexed borrower, uint compDelta, uint compBorrowIndex); - - /// @notice The threshold above which the flywheel transfers COMP, in wei - uint public constant compClaimThreshold = 0.001e18; - - /// @notice The initial COMP index for a market - uint224 public constant compInitialIndex = 1e36; - - // closeFactorMantissa must be strictly greater than this value - uint internal constant closeFactorMinMantissa = 0.05e18; // 0.05 - - // closeFactorMantissa must not exceed this value - uint internal constant closeFactorMaxMantissa = 0.9e18; // 0.9 - - // No collateralFactorMantissa may exceed this value - uint internal constant collateralFactorMaxMantissa = 0.9e18; // 0.9 - - // liquidationIncentiveMantissa must be no less than this value - uint internal constant liquidationIncentiveMinMantissa = 1.0e18; // 1.0 - - // liquidationIncentiveMantissa must be no greater than this value - uint internal constant liquidationIncentiveMaxMantissa = 1.5e18; // 1.5 - - constructor() public { - admin = msg.sender; - } - - /*** Assets You Are In ***/ - - /** - * @notice Returns the assets an account has entered - * @param account The address of the account to pull assets for - * @return A dynamic list with the assets the account has entered - */ - function getAssetsIn(address account) external view returns (CToken[] memory) { - CToken[] memory assetsIn = accountAssets[account]; - - return assetsIn; - } - - /** - * @notice Returns whether the given account is entered in the given asset - * @param account The address of the account to check - * @param cToken The cToken to check - * @return True if the account is in the asset, otherwise false. - */ - function checkMembership(address account, CToken cToken) external view returns (bool) { - return markets[address(cToken)].accountMembership[account]; - } - - /** - * @notice Add assets to be included in account liquidity calculation - * @param cTokens The list of addresses of the cToken markets to be enabled - * @return Success indicator for whether each corresponding market was entered - */ - function enterMarkets(address[] memory cTokens) public returns (uint[] memory) { - uint len = cTokens.length; - - uint[] memory results = new uint[](len); - for (uint i = 0; i < len; i++) { - CToken cToken = CToken(cTokens[i]); - - results[i] = uint(addToMarketInternal(cToken, msg.sender)); - } - - return results; - } - - /** - * @notice Add the market to the borrower's "assets in" for liquidity calculations - * @param cToken The market to enter - * @param borrower The address of the account to modify - * @return Success indicator for whether the market was entered - */ - function addToMarketInternal(CToken cToken, address borrower) internal returns (Error) { - Market storage marketToJoin = markets[address(cToken)]; - - if (!marketToJoin.isListed) { - // market is not listed, cannot join - return Error.MARKET_NOT_LISTED; - } - - if (marketToJoin.accountMembership[borrower] == true) { - // already joined - return Error.NO_ERROR; - } - - if (accountAssets[borrower].length >= maxAssets) { - // no space, cannot join - return Error.TOO_MANY_ASSETS; - } - - // survived the gauntlet, add to list - // NOTE: we store these somewhat redundantly as a significant optimization - // this avoids having to iterate through the list for the most common use cases - // that is, only when we need to perform liquidity checks - // and not whenever we want to check if an account is in a particular market - marketToJoin.accountMembership[borrower] = true; - accountAssets[borrower].push(cToken); - - emit MarketEntered(cToken, borrower); - - return Error.NO_ERROR; - } - - /** - * @notice Removes asset from sender's account liquidity calculation - * @dev Sender must not have an outstanding borrow balance in the asset, - * or be providing necessary collateral for an outstanding borrow. - * @param cTokenAddress The address of the asset to be removed - * @return Whether or not the account successfully exited the market - */ - function exitMarket(address cTokenAddress) external returns (uint) { - CToken cToken = CToken(cTokenAddress); - /* Get sender tokensHeld and amountOwed underlying from the cToken */ - (uint oErr, uint tokensHeld, uint amountOwed, ) = cToken.getAccountSnapshot(msg.sender); - require(oErr == 0, "exitMarket: getAccountSnapshot failed"); // semi-opaque error code - - /* Fail if the sender has a borrow balance */ - if (amountOwed != 0) { - return fail(Error.NONZERO_BORROW_BALANCE, FailureInfo.EXIT_MARKET_BALANCE_OWED); - } - - /* Fail if the sender is not permitted to redeem all of their tokens */ - uint allowed = redeemAllowedInternal(cTokenAddress, msg.sender, tokensHeld); - if (allowed != 0) { - return failOpaque(Error.REJECTION, FailureInfo.EXIT_MARKET_REJECTION, allowed); - } - - Market storage marketToExit = markets[address(cToken)]; - - /* Return true if the sender is not already ‘in’ the market */ - if (!marketToExit.accountMembership[msg.sender]) { - return uint(Error.NO_ERROR); - } - - /* Set cToken account membership to false */ - delete marketToExit.accountMembership[msg.sender]; - - /* Delete cToken from the account’s list of assets */ - // load into memory for faster iteration - CToken[] memory userAssetList = accountAssets[msg.sender]; - uint len = userAssetList.length; - uint assetIndex = len; - for (uint i = 0; i < len; i++) { - if (userAssetList[i] == cToken) { - assetIndex = i; - break; - } - } - - // We *must* have found the asset in the list or our redundant data structure is broken - assert(assetIndex < len); - - // copy last item in list to location of item to be removed, reduce length by 1 - CToken[] storage storedList = accountAssets[msg.sender]; - storedList[assetIndex] = storedList[storedList.length - 1]; - storedList.length--; - - emit MarketExited(cToken, msg.sender); - - return uint(Error.NO_ERROR); - } - - /*** Policy Hooks ***/ - - /** - * @notice Checks if the account should be allowed to mint tokens in the given market - * @param cToken The market to verify the mint against - * @param minter The account which would get the minted tokens - * @param mintAmount The amount of underlying being supplied to the market in exchange for tokens - * @return 0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol) - */ - function mintAllowed(address cToken, address minter, uint mintAmount) external returns (uint) { - // Pausing is a very serious situation - we revert to sound the alarms - require(!mintGuardianPaused[cToken], "mint is paused"); - - // Shh - currently unused - minter; - mintAmount; - - if (!markets[cToken].isListed) { - return uint(Error.MARKET_NOT_LISTED); - } - - // Keep the flywheel moving - updateCompSupplyIndex(cToken); - distributeSupplierComp(cToken, minter, false); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Validates mint and reverts on rejection. May emit logs. - * @param cToken Asset being minted - * @param minter The address minting the tokens - * @param actualMintAmount The amount of the underlying asset being minted - * @param mintTokens The number of tokens being minted - */ - function mintVerify(address cToken, address minter, uint actualMintAmount, uint mintTokens) external { - // Shh - currently unused - cToken; - minter; - actualMintAmount; - mintTokens; - - // Shh - we don't ever want this hook to be marked pure - if (false) { - maxAssets = maxAssets; - } - } - - /** - * @notice Checks if the account should be allowed to redeem tokens in the given market - * @param cToken The market to verify the redeem against - * @param redeemer The account which would redeem the tokens - * @param redeemTokens The number of cTokens to exchange for the underlying asset in the market - * @return 0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol) - */ - function redeemAllowed(address cToken, address redeemer, uint redeemTokens) external returns (uint) { - uint allowed = redeemAllowedInternal(cToken, redeemer, redeemTokens); - if (allowed != uint(Error.NO_ERROR)) { - return allowed; - } - - // Keep the flywheel moving - updateCompSupplyIndex(cToken); - distributeSupplierComp(cToken, redeemer, false); - - return uint(Error.NO_ERROR); - } - - function redeemAllowedInternal(address cToken, address redeemer, uint redeemTokens) internal view returns (uint) { - if (!markets[cToken].isListed) { - return uint(Error.MARKET_NOT_LISTED); - } - - /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */ - if (!markets[cToken].accountMembership[redeemer]) { - return uint(Error.NO_ERROR); - } - - /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */ - (Error err, , uint shortfall) = getHypotheticalAccountLiquidityInternal(redeemer, CToken(cToken), redeemTokens, 0); - if (err != Error.NO_ERROR) { - return uint(err); - } - if (shortfall > 0) { - return uint(Error.INSUFFICIENT_LIQUIDITY); - } - - return uint(Error.NO_ERROR); - } - - /** - * @notice Validates redeem and reverts on rejection. May emit logs. - * @param cToken Asset being redeemed - * @param redeemer The address redeeming the tokens - * @param redeemAmount The amount of the underlying asset being redeemed - * @param redeemTokens The number of tokens being redeemed - */ - function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) external { - // Shh - currently unused - cToken; - redeemer; - - // Require tokens is zero or amount is also zero - if (redeemTokens == 0 && redeemAmount > 0) { - revert("redeemTokens zero"); - } - } - - /** - * @notice Checks if the account should be allowed to borrow the underlying asset of the given market - * @param cToken The market to verify the borrow against - * @param borrower The account which would borrow the asset - * @param borrowAmount The amount of underlying the account would borrow - * @return 0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol) - */ - function borrowAllowed(address cToken, address borrower, uint borrowAmount) external returns (uint) { - // Pausing is a very serious situation - we revert to sound the alarms - require(!borrowGuardianPaused[cToken], "borrow is paused"); - - if (!markets[cToken].isListed) { - return uint(Error.MARKET_NOT_LISTED); - } - - if (!markets[cToken].accountMembership[borrower]) { - // only cTokens may call borrowAllowed if borrower not in market - require(msg.sender == cToken, "sender must be cToken"); - - // attempt to add borrower to the market - Error err = addToMarketInternal(CToken(msg.sender), borrower); - if (err != Error.NO_ERROR) { - return uint(err); - } - - // it should be impossible to break the important invariant - assert(markets[cToken].accountMembership[borrower]); - } - - if (oracle.getUnderlyingPrice(CToken(cToken)) == 0) { - return uint(Error.PRICE_ERROR); - } - - (Error err, , uint shortfall) = getHypotheticalAccountLiquidityInternal(borrower, CToken(cToken), 0, borrowAmount); - if (err != Error.NO_ERROR) { - return uint(err); - } - if (shortfall > 0) { - return uint(Error.INSUFFICIENT_LIQUIDITY); - } - - // Keep the flywheel moving - Exp memory borrowIndex = Exp({mantissa: CToken(cToken).borrowIndex()}); - updateCompBorrowIndex(cToken, borrowIndex); - distributeBorrowerComp(cToken, borrower, borrowIndex, false); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Validates borrow and reverts on rejection. May emit logs. - * @param cToken Asset whose underlying is being borrowed - * @param borrower The address borrowing the underlying - * @param borrowAmount The amount of the underlying asset requested to borrow - */ - function borrowVerify(address cToken, address borrower, uint borrowAmount) external { - // Shh - currently unused - cToken; - borrower; - borrowAmount; - - // Shh - we don't ever want this hook to be marked pure - if (false) { - maxAssets = maxAssets; - } - } - - /** - * @notice Checks if the account should be allowed to repay a borrow in the given market - * @param cToken The market to verify the repay against - * @param payer The account which would repay the asset - * @param borrower The account which would borrowed the asset - * @param repayAmount The amount of the underlying asset the account would repay - * @return 0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol) - */ - function repayBorrowAllowed( - address cToken, - address payer, - address borrower, - uint repayAmount) external returns (uint) { - // Shh - currently unused - payer; - borrower; - repayAmount; - - if (!markets[cToken].isListed) { - return uint(Error.MARKET_NOT_LISTED); - } - - // Keep the flywheel moving - Exp memory borrowIndex = Exp({mantissa: CToken(cToken).borrowIndex()}); - updateCompBorrowIndex(cToken, borrowIndex); - distributeBorrowerComp(cToken, borrower, borrowIndex, false); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Validates repayBorrow and reverts on rejection. May emit logs. - * @param cToken Asset being repaid - * @param payer The address repaying the borrow - * @param borrower The address of the borrower - * @param actualRepayAmount The amount of underlying being repaid - */ - function repayBorrowVerify( - address cToken, - address payer, - address borrower, - uint actualRepayAmount, - uint borrowerIndex) external { - // Shh - currently unused - cToken; - payer; - borrower; - actualRepayAmount; - borrowerIndex; - - // Shh - we don't ever want this hook to be marked pure - if (false) { - maxAssets = maxAssets; - } - } - - /** - * @notice Checks if the liquidation should be allowed to occur - * @param cTokenBorrowed Asset which was borrowed by the borrower - * @param cTokenCollateral Asset which was used as collateral and will be seized - * @param liquidator The address repaying the borrow and seizing the collateral - * @param borrower The address of the borrower - * @param repayAmount The amount of underlying being repaid - */ - function liquidateBorrowAllowed( - address cTokenBorrowed, - address cTokenCollateral, - address liquidator, - address borrower, - uint repayAmount) external returns (uint) { - // Shh - currently unused - liquidator; - - if (!markets[cTokenBorrowed].isListed || !markets[cTokenCollateral].isListed) { - return uint(Error.MARKET_NOT_LISTED); - } - - /* The borrower must have shortfall in order to be liquidatable */ - (Error err, , uint shortfall) = getAccountLiquidityInternal(borrower); - if (err != Error.NO_ERROR) { - return uint(err); - } - if (shortfall == 0) { - return uint(Error.INSUFFICIENT_SHORTFALL); - } - - /* The liquidator may not repay more than what is allowed by the closeFactor */ - uint borrowBalance = CToken(cTokenBorrowed).borrowBalanceStored(borrower); - (MathError mathErr, uint maxClose) = mulScalarTruncate(Exp({mantissa: closeFactorMantissa}), borrowBalance); - if (mathErr != MathError.NO_ERROR) { - return uint(Error.MATH_ERROR); - } - if (repayAmount > maxClose) { - return uint(Error.TOO_MUCH_REPAY); - } - - return uint(Error.NO_ERROR); - } - - /** - * @notice Validates liquidateBorrow and reverts on rejection. May emit logs. - * @param cTokenBorrowed Asset which was borrowed by the borrower - * @param cTokenCollateral Asset which was used as collateral and will be seized - * @param liquidator The address repaying the borrow and seizing the collateral - * @param borrower The address of the borrower - * @param actualRepayAmount The amount of underlying being repaid - */ - function liquidateBorrowVerify( - address cTokenBorrowed, - address cTokenCollateral, - address liquidator, - address borrower, - uint actualRepayAmount, - uint seizeTokens) external { - // Shh - currently unused - cTokenBorrowed; - cTokenCollateral; - liquidator; - borrower; - actualRepayAmount; - seizeTokens; - - // Shh - we don't ever want this hook to be marked pure - if (false) { - maxAssets = maxAssets; - } - } - - /** - * @notice Checks if the seizing of assets should be allowed to occur - * @param cTokenCollateral Asset which was used as collateral and will be seized - * @param cTokenBorrowed Asset which was borrowed by the borrower - * @param liquidator The address repaying the borrow and seizing the collateral - * @param borrower The address of the borrower - * @param seizeTokens The number of collateral tokens to seize - */ - function seizeAllowed( - address cTokenCollateral, - address cTokenBorrowed, - address liquidator, - address borrower, - uint seizeTokens) external returns (uint) { - // Pausing is a very serious situation - we revert to sound the alarms - require(!seizeGuardianPaused, "seize is paused"); - - // Shh - currently unused - seizeTokens; - - if (!markets[cTokenCollateral].isListed || !markets[cTokenBorrowed].isListed) { - return uint(Error.MARKET_NOT_LISTED); - } - - if (CToken(cTokenCollateral).comptroller() != CToken(cTokenBorrowed).comptroller()) { - return uint(Error.COMPTROLLER_MISMATCH); - } - - // Keep the flywheel moving - updateCompSupplyIndex(cTokenCollateral); - distributeSupplierComp(cTokenCollateral, borrower, false); - distributeSupplierComp(cTokenCollateral, liquidator, false); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Validates seize and reverts on rejection. May emit logs. - * @param cTokenCollateral Asset which was used as collateral and will be seized - * @param cTokenBorrowed Asset which was borrowed by the borrower - * @param liquidator The address repaying the borrow and seizing the collateral - * @param borrower The address of the borrower - * @param seizeTokens The number of collateral tokens to seize - */ - function seizeVerify( - address cTokenCollateral, - address cTokenBorrowed, - address liquidator, - address borrower, - uint seizeTokens) external { - // Shh - currently unused - cTokenCollateral; - cTokenBorrowed; - liquidator; - borrower; - seizeTokens; - - // Shh - we don't ever want this hook to be marked pure - if (false) { - maxAssets = maxAssets; - } - } - - /** - * @notice Checks if the account should be allowed to transfer tokens in the given market - * @param cToken The market to verify the transfer against - * @param src The account which sources the tokens - * @param dst The account which receives the tokens - * @param transferTokens The number of cTokens to transfer - * @return 0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol) - */ - function transferAllowed(address cToken, address src, address dst, uint transferTokens) external returns (uint) { - // Pausing is a very serious situation - we revert to sound the alarms - require(!transferGuardianPaused, "transfer is paused"); - - // Currently the only consideration is whether or not - // the src is allowed to redeem this many tokens - uint allowed = redeemAllowedInternal(cToken, src, transferTokens); - if (allowed != uint(Error.NO_ERROR)) { - return allowed; - } - - // Keep the flywheel moving - updateCompSupplyIndex(cToken); - distributeSupplierComp(cToken, src, false); - distributeSupplierComp(cToken, dst, false); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Validates transfer and reverts on rejection. May emit logs. - * @param cToken Asset being transferred - * @param src The account which sources the tokens - * @param dst The account which receives the tokens - * @param transferTokens The number of cTokens to transfer - */ - function transferVerify(address cToken, address src, address dst, uint transferTokens) external { - // Shh - currently unused - cToken; - src; - dst; - transferTokens; - - // Shh - we don't ever want this hook to be marked pure - if (false) { - maxAssets = maxAssets; - } - } - - /*** Liquidity/Liquidation Calculations ***/ - - /** - * @dev Local vars for avoiding stack-depth limits in calculating account liquidity. - * Note that `cTokenBalance` is the number of cTokens the account owns in the market, - * whereas `borrowBalance` is the amount of underlying that the account has borrowed. - */ - struct AccountLiquidityLocalVars { - uint sumCollateral; - uint sumBorrowPlusEffects; - uint cTokenBalance; - uint borrowBalance; - uint exchangeRateMantissa; - uint oraclePriceMantissa; - Exp collateralFactor; - Exp exchangeRate; - Exp oraclePrice; - Exp tokensToDenom; - } - - /** - * @notice Determine the current account liquidity wrt collateral requirements - * @return (possible error code (semi-opaque), - account liquidity in excess of collateral requirements, - * account shortfall below collateral requirements) - */ - function getAccountLiquidity(address account) public view returns (uint, uint, uint) { - (Error err, uint liquidity, uint shortfall) = getHypotheticalAccountLiquidityInternal(account, CToken(0), 0, 0); - - return (uint(err), liquidity, shortfall); - } - - /** - * @notice Determine the current account liquidity wrt collateral requirements - * @return (possible error code, - account liquidity in excess of collateral requirements, - * account shortfall below collateral requirements) - */ - function getAccountLiquidityInternal(address account) internal view returns (Error, uint, uint) { - return getHypotheticalAccountLiquidityInternal(account, CToken(0), 0, 0); - } - - /** - * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed - * @param cTokenModify The market to hypothetically redeem/borrow in - * @param account The account to determine liquidity for - * @param redeemTokens The number of tokens to hypothetically redeem - * @param borrowAmount The amount of underlying to hypothetically borrow - * @return (possible error code (semi-opaque), - hypothetical account liquidity in excess of collateral requirements, - * hypothetical account shortfall below collateral requirements) - */ - function getHypotheticalAccountLiquidity( - address account, - address cTokenModify, - uint redeemTokens, - uint borrowAmount) public view returns (uint, uint, uint) { - (Error err, uint liquidity, uint shortfall) = getHypotheticalAccountLiquidityInternal(account, CToken(cTokenModify), redeemTokens, borrowAmount); - return (uint(err), liquidity, shortfall); - } - - /** - * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed - * @param cTokenModify The market to hypothetically redeem/borrow in - * @param account The account to determine liquidity for - * @param redeemTokens The number of tokens to hypothetically redeem - * @param borrowAmount The amount of underlying to hypothetically borrow - * @dev Note that we calculate the exchangeRateStored for each collateral cToken using stored data, - * without calculating accumulated interest. - * @return (possible error code, - hypothetical account liquidity in excess of collateral requirements, - * hypothetical account shortfall below collateral requirements) - */ - function getHypotheticalAccountLiquidityInternal( - address account, - CToken cTokenModify, - uint redeemTokens, - uint borrowAmount) internal view returns (Error, uint, uint) { - - AccountLiquidityLocalVars memory vars; // Holds all our calculation results - uint oErr; - MathError mErr; - - // For each asset the account is in - CToken[] memory assets = accountAssets[account]; - for (uint i = 0; i < assets.length; i++) { - CToken asset = assets[i]; - - // Read the balances and exchange rate from the cToken - (oErr, vars.cTokenBalance, vars.borrowBalance, vars.exchangeRateMantissa) = asset.getAccountSnapshot(account); - if (oErr != 0) { // semi-opaque error code, we assume NO_ERROR == 0 is invariant between upgrades - return (Error.SNAPSHOT_ERROR, 0, 0); - } - vars.collateralFactor = Exp({mantissa: markets[address(asset)].collateralFactorMantissa}); - vars.exchangeRate = Exp({mantissa: vars.exchangeRateMantissa}); - - // Get the normalized price of the asset - vars.oraclePriceMantissa = oracle.getUnderlyingPrice(asset); - if (vars.oraclePriceMantissa == 0) { - return (Error.PRICE_ERROR, 0, 0); - } - vars.oraclePrice = Exp({mantissa: vars.oraclePriceMantissa}); - - // Pre-compute a conversion factor from tokens -> ether (normalized price value) - (mErr, vars.tokensToDenom) = mulExp3(vars.collateralFactor, vars.exchangeRate, vars.oraclePrice); - if (mErr != MathError.NO_ERROR) { - return (Error.MATH_ERROR, 0, 0); - } - - // sumCollateral += tokensToDenom * cTokenBalance - (mErr, vars.sumCollateral) = mulScalarTruncateAddUInt(vars.tokensToDenom, vars.cTokenBalance, vars.sumCollateral); - if (mErr != MathError.NO_ERROR) { - return (Error.MATH_ERROR, 0, 0); - } - - // sumBorrowPlusEffects += oraclePrice * borrowBalance - (mErr, vars.sumBorrowPlusEffects) = mulScalarTruncateAddUInt(vars.oraclePrice, vars.borrowBalance, vars.sumBorrowPlusEffects); - if (mErr != MathError.NO_ERROR) { - return (Error.MATH_ERROR, 0, 0); - } - - // Calculate effects of interacting with cTokenModify - if (asset == cTokenModify) { - // redeem effect - // sumBorrowPlusEffects += tokensToDenom * redeemTokens - (mErr, vars.sumBorrowPlusEffects) = mulScalarTruncateAddUInt(vars.tokensToDenom, redeemTokens, vars.sumBorrowPlusEffects); - if (mErr != MathError.NO_ERROR) { - return (Error.MATH_ERROR, 0, 0); - } - - // borrow effect - // sumBorrowPlusEffects += oraclePrice * borrowAmount - (mErr, vars.sumBorrowPlusEffects) = mulScalarTruncateAddUInt(vars.oraclePrice, borrowAmount, vars.sumBorrowPlusEffects); - if (mErr != MathError.NO_ERROR) { - return (Error.MATH_ERROR, 0, 0); - } - } - } - - // These are safe, as the underflow condition is checked first - if (vars.sumCollateral > vars.sumBorrowPlusEffects) { - return (Error.NO_ERROR, vars.sumCollateral - vars.sumBorrowPlusEffects, 0); - } else { - return (Error.NO_ERROR, 0, vars.sumBorrowPlusEffects - vars.sumCollateral); - } - } - - /** - * @notice Calculate number of tokens of collateral asset to seize given an underlying amount - * @dev Used in liquidation (called in cToken.liquidateBorrowFresh) - * @param cTokenBorrowed The address of the borrowed cToken - * @param cTokenCollateral The address of the collateral cToken - * @param actualRepayAmount The amount of cTokenBorrowed underlying to convert into cTokenCollateral tokens - * @return (errorCode, number of cTokenCollateral tokens to be seized in a liquidation) - */ - function liquidateCalculateSeizeTokens(address cTokenBorrowed, address cTokenCollateral, uint actualRepayAmount) external view returns (uint, uint) { - /* Read oracle prices for borrowed and collateral markets */ - uint priceBorrowedMantissa = oracle.getUnderlyingPrice(CToken(cTokenBorrowed)); - uint priceCollateralMantissa = oracle.getUnderlyingPrice(CToken(cTokenCollateral)); - if (priceBorrowedMantissa == 0 || priceCollateralMantissa == 0) { - return (uint(Error.PRICE_ERROR), 0); - } - - /* - * Get the exchange rate and calculate the number of collateral tokens to seize: - * seizeAmount = actualRepayAmount * liquidationIncentive * priceBorrowed / priceCollateral - * seizeTokens = seizeAmount / exchangeRate - * = actualRepayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate) - */ - uint exchangeRateMantissa = CToken(cTokenCollateral).exchangeRateStored(); // Note: reverts on error - uint seizeTokens; - Exp memory numerator; - Exp memory denominator; - Exp memory ratio; - MathError mathErr; - - (mathErr, numerator) = mulExp(liquidationIncentiveMantissa, priceBorrowedMantissa); - if (mathErr != MathError.NO_ERROR) { - return (uint(Error.MATH_ERROR), 0); - } - - (mathErr, denominator) = mulExp(priceCollateralMantissa, exchangeRateMantissa); - if (mathErr != MathError.NO_ERROR) { - return (uint(Error.MATH_ERROR), 0); - } - - (mathErr, ratio) = divExp(numerator, denominator); - if (mathErr != MathError.NO_ERROR) { - return (uint(Error.MATH_ERROR), 0); - } - - (mathErr, seizeTokens) = mulScalarTruncate(ratio, actualRepayAmount); - if (mathErr != MathError.NO_ERROR) { - return (uint(Error.MATH_ERROR), 0); - } - - return (uint(Error.NO_ERROR), seizeTokens); - } - - /*** Admin Functions ***/ - - /** - * @notice Sets a new price oracle for the comptroller - * @dev Admin function to set a new price oracle - * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) - */ - function _setPriceOracle(PriceOracle newOracle) public returns (uint) { - // Check caller is admin - if (msg.sender != admin) { - return fail(Error.UNAUTHORIZED, FailureInfo.SET_PRICE_ORACLE_OWNER_CHECK); - } - - // Track the old oracle for the comptroller - PriceOracle oldOracle = oracle; - - // Set comptroller's oracle to newOracle - oracle = newOracle; - - // Emit NewPriceOracle(oldOracle, newOracle) - emit NewPriceOracle(oldOracle, newOracle); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Sets the closeFactor used when liquidating borrows - * @dev Admin function to set closeFactor - * @param newCloseFactorMantissa New close factor, scaled by 1e18 - * @return uint 0=success, otherwise a failure. (See ErrorReporter for details) - */ - function _setCloseFactor(uint newCloseFactorMantissa) external returns (uint) { - // Check caller is admin - if (msg.sender != admin) { - return fail(Error.UNAUTHORIZED, FailureInfo.SET_CLOSE_FACTOR_OWNER_CHECK); - } - - Exp memory newCloseFactorExp = Exp({mantissa: newCloseFactorMantissa}); - Exp memory lowLimit = Exp({mantissa: closeFactorMinMantissa}); - if (lessThanOrEqualExp(newCloseFactorExp, lowLimit)) { - return fail(Error.INVALID_CLOSE_FACTOR, FailureInfo.SET_CLOSE_FACTOR_VALIDATION); - } - - Exp memory highLimit = Exp({mantissa: closeFactorMaxMantissa}); - if (lessThanExp(highLimit, newCloseFactorExp)) { - return fail(Error.INVALID_CLOSE_FACTOR, FailureInfo.SET_CLOSE_FACTOR_VALIDATION); - } - - uint oldCloseFactorMantissa = closeFactorMantissa; - closeFactorMantissa = newCloseFactorMantissa; - emit NewCloseFactor(oldCloseFactorMantissa, closeFactorMantissa); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Sets the collateralFactor for a market - * @dev Admin function to set per-market collateralFactor - * @param cToken The market to set the factor on - * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18 - * @return uint 0=success, otherwise a failure. (See ErrorReporter for details) - */ - function _setCollateralFactor(CToken cToken, uint newCollateralFactorMantissa) external returns (uint) { - // Check caller is admin - if (msg.sender != admin) { - return fail(Error.UNAUTHORIZED, FailureInfo.SET_COLLATERAL_FACTOR_OWNER_CHECK); - } - - // Verify market is listed - Market storage market = markets[address(cToken)]; - if (!market.isListed) { - return fail(Error.MARKET_NOT_LISTED, FailureInfo.SET_COLLATERAL_FACTOR_NO_EXISTS); - } - - Exp memory newCollateralFactorExp = Exp({mantissa: newCollateralFactorMantissa}); - - // Check collateral factor <= 0.9 - Exp memory highLimit = Exp({mantissa: collateralFactorMaxMantissa}); - if (lessThanExp(highLimit, newCollateralFactorExp)) { - return fail(Error.INVALID_COLLATERAL_FACTOR, FailureInfo.SET_COLLATERAL_FACTOR_VALIDATION); - } - - // If collateral factor != 0, fail if price == 0 - if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(cToken) == 0) { - return fail(Error.PRICE_ERROR, FailureInfo.SET_COLLATERAL_FACTOR_WITHOUT_PRICE); - } - - // Set market's collateral factor to new collateral factor, remember old value - uint oldCollateralFactorMantissa = market.collateralFactorMantissa; - market.collateralFactorMantissa = newCollateralFactorMantissa; - - // Emit event with asset, old collateral factor, and new collateral factor - emit NewCollateralFactor(cToken, oldCollateralFactorMantissa, newCollateralFactorMantissa); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Sets maxAssets which controls how many markets can be entered - * @dev Admin function to set maxAssets - * @param newMaxAssets New max assets - * @return uint 0=success, otherwise a failure. (See ErrorReporter for details) - */ - function _setMaxAssets(uint newMaxAssets) external returns (uint) { - // Check caller is admin - if (msg.sender != admin) { - return fail(Error.UNAUTHORIZED, FailureInfo.SET_MAX_ASSETS_OWNER_CHECK); - } - - uint oldMaxAssets = maxAssets; - maxAssets = newMaxAssets; - emit NewMaxAssets(oldMaxAssets, newMaxAssets); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Sets liquidationIncentive - * @dev Admin function to set liquidationIncentive - * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18 - * @return uint 0=success, otherwise a failure. (See ErrorReporter for details) - */ - function _setLiquidationIncentive(uint newLiquidationIncentiveMantissa) external returns (uint) { - // Check caller is admin - if (msg.sender != admin) { - return fail(Error.UNAUTHORIZED, FailureInfo.SET_LIQUIDATION_INCENTIVE_OWNER_CHECK); - } - - // Check de-scaled min <= newLiquidationIncentive <= max - Exp memory newLiquidationIncentive = Exp({mantissa: newLiquidationIncentiveMantissa}); - Exp memory minLiquidationIncentive = Exp({mantissa: liquidationIncentiveMinMantissa}); - if (lessThanExp(newLiquidationIncentive, minLiquidationIncentive)) { - return fail(Error.INVALID_LIQUIDATION_INCENTIVE, FailureInfo.SET_LIQUIDATION_INCENTIVE_VALIDATION); - } - - Exp memory maxLiquidationIncentive = Exp({mantissa: liquidationIncentiveMaxMantissa}); - if (lessThanExp(maxLiquidationIncentive, newLiquidationIncentive)) { - return fail(Error.INVALID_LIQUIDATION_INCENTIVE, FailureInfo.SET_LIQUIDATION_INCENTIVE_VALIDATION); - } - - // Save current value for use in log - uint oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa; - - // Set liquidation incentive to new incentive - liquidationIncentiveMantissa = newLiquidationIncentiveMantissa; - - // Emit event with old incentive, new incentive - emit NewLiquidationIncentive(oldLiquidationIncentiveMantissa, newLiquidationIncentiveMantissa); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Add the market to the markets mapping and set it as listed - * @dev Admin function to set isListed and add support for the market - * @param cToken The address of the market (token) to list - * @return uint 0=success, otherwise a failure. (See enum Error for details) - */ - function _supportMarket(CToken cToken) external returns (uint) { - if (msg.sender != admin) { - return fail(Error.UNAUTHORIZED, FailureInfo.SUPPORT_MARKET_OWNER_CHECK); - } - - if (markets[address(cToken)].isListed) { - return fail(Error.MARKET_ALREADY_LISTED, FailureInfo.SUPPORT_MARKET_EXISTS); - } - - cToken.isCToken(); // Sanity check to make sure its really a CToken - - markets[address(cToken)] = Market({isListed: true, isComped: false, collateralFactorMantissa: 0}); - - _addMarketInternal(address(cToken)); - - emit MarketListed(cToken); - - return uint(Error.NO_ERROR); - } - - function _addMarketInternal(address cToken) internal { - for (uint i = 0; i < allMarkets.length; i ++) { - require(allMarkets[i] != CToken(cToken), "market already added"); - } - allMarkets.push(CToken(cToken)); - } - - /** - * @notice Admin function to change the Pause Guardian - * @param newPauseGuardian The address of the new Pause Guardian - * @return uint 0=success, otherwise a failure. (See enum Error for details) - */ - function _setPauseGuardian(address newPauseGuardian) public returns (uint) { - if (msg.sender != admin) { - return fail(Error.UNAUTHORIZED, FailureInfo.SET_PAUSE_GUARDIAN_OWNER_CHECK); - } - - // Save current value for inclusion in log - address oldPauseGuardian = pauseGuardian; - - // Store pauseGuardian with value newPauseGuardian - pauseGuardian = newPauseGuardian; - - // Emit NewPauseGuardian(OldPauseGuardian, NewPauseGuardian) - emit NewPauseGuardian(oldPauseGuardian, pauseGuardian); - - return uint(Error.NO_ERROR); - } - - function _setMintPaused(CToken cToken, bool state) public returns (bool) { - require(markets[address(cToken)].isListed, "cannot pause a market that is not listed"); - require(msg.sender == pauseGuardian || msg.sender == admin, "only pause guardian and admin can pause"); - require(msg.sender == admin || state == true, "only admin can unpause"); - - mintGuardianPaused[address(cToken)] = state; - emit ActionPaused(cToken, "Mint", state); - return state; - } - - function _setBorrowPaused(CToken cToken, bool state) public returns (bool) { - require(markets[address(cToken)].isListed, "cannot pause a market that is not listed"); - require(msg.sender == pauseGuardian || msg.sender == admin, "only pause guardian and admin can pause"); - require(msg.sender == admin || state == true, "only admin can unpause"); - - borrowGuardianPaused[address(cToken)] = state; - emit ActionPaused(cToken, "Borrow", state); - return state; - } - - function _setTransferPaused(bool state) public returns (bool) { - require(msg.sender == pauseGuardian || msg.sender == admin, "only pause guardian and admin can pause"); - require(msg.sender == admin || state == true, "only admin can unpause"); - - transferGuardianPaused = state; - emit ActionPaused("Transfer", state); - return state; - } - - function _setSeizePaused(bool state) public returns (bool) { - require(msg.sender == pauseGuardian || msg.sender == admin, "only pause guardian and admin can pause"); - require(msg.sender == admin || state == true, "only admin can unpause"); - - seizeGuardianPaused = state; - emit ActionPaused("Seize", state); - return state; - } - - function _become(Unitroller unitroller) public { - require(msg.sender == unitroller.admin(), "only unitroller admin can change brains"); - require(unitroller._acceptImplementation() == 0, "change not authorized"); - } - - /** - * @notice Checks caller is admin, or this contract is becoming the new implementation - */ - function adminOrInitializing() internal view returns (bool) { - return msg.sender == admin || msg.sender == comptrollerImplementation; - } - - /*** Comp Distribution ***/ - - /** - * @notice Recalculate and update COMP speeds for all COMP markets - */ - function refreshCompSpeeds() public { - require(msg.sender == tx.origin, "only externally owned accounts may refresh speeds"); - refreshCompSpeedsInternal(); - } - - function refreshCompSpeedsInternal() internal { - CToken[] memory allMarkets_ = allMarkets; - - for (uint i = 0; i < allMarkets_.length; i++) { - CToken cToken = allMarkets_[i]; - Exp memory borrowIndex = Exp({mantissa: cToken.borrowIndex()}); - updateCompSupplyIndex(address(cToken)); - updateCompBorrowIndex(address(cToken), borrowIndex); - } - - Exp memory totalUtility = Exp({mantissa: 0}); - Exp[] memory utilities = new Exp[](allMarkets_.length); - for (uint i = 0; i < allMarkets_.length; i++) { - CToken cToken = allMarkets_[i]; - if (markets[address(cToken)].isComped) { - Exp memory assetPrice = Exp({mantissa: oracle.getUnderlyingPrice(cToken)}); - Exp memory utility = mul_(assetPrice, cToken.totalBorrows()); - utilities[i] = utility; - totalUtility = add_(totalUtility, utility); - } - } - - for (uint i = 0; i < allMarkets_.length; i++) { - CToken cToken = allMarkets[i]; - uint newSpeed = totalUtility.mantissa > 0 ? mul_(compRate, div_(utilities[i], totalUtility)) : 0; - compSpeeds[address(cToken)] = newSpeed; - emit CompSpeedUpdated(cToken, newSpeed); - } - } - - /** - * @notice Accrue COMP to the market by updating the supply index - * @param cToken The market whose supply index to update - */ - function updateCompSupplyIndex(address cToken) internal { - CompMarketState storage supplyState = compSupplyState[cToken]; - uint supplySpeed = compSpeeds[cToken]; - uint blockNumber = getBlockNumber(); - uint deltaBlocks = sub_(blockNumber, uint(supplyState.block)); - if (deltaBlocks > 0 && supplySpeed > 0) { - uint supplyTokens = CToken(cToken).totalSupply(); - uint compAccrued = mul_(deltaBlocks, supplySpeed); - Double memory ratio = supplyTokens > 0 ? fraction(compAccrued, supplyTokens) : Double({mantissa: 0}); - Double memory index = add_(Double({mantissa: supplyState.index}), ratio); - compSupplyState[cToken] = CompMarketState({ - index: safe224(index.mantissa, "new index exceeds 224 bits"), - block: safe32(blockNumber, "block number exceeds 32 bits") - }); - } else if (deltaBlocks > 0) { - supplyState.block = safe32(blockNumber, "block number exceeds 32 bits"); - } - } - - /** - * @notice Accrue COMP to the market by updating the borrow index - * @param cToken The market whose borrow index to update - */ - function updateCompBorrowIndex(address cToken, Exp memory marketBorrowIndex) internal { - CompMarketState storage borrowState = compBorrowState[cToken]; - uint borrowSpeed = compSpeeds[cToken]; - uint blockNumber = getBlockNumber(); - uint deltaBlocks = sub_(blockNumber, uint(borrowState.block)); - if (deltaBlocks > 0 && borrowSpeed > 0) { - uint borrowAmount = div_(CToken(cToken).totalBorrows(), marketBorrowIndex); - uint compAccrued = mul_(deltaBlocks, borrowSpeed); - Double memory ratio = borrowAmount > 0 ? fraction(compAccrued, borrowAmount) : Double({mantissa: 0}); - Double memory index = add_(Double({mantissa: borrowState.index}), ratio); - compBorrowState[cToken] = CompMarketState({ - index: safe224(index.mantissa, "new index exceeds 224 bits"), - block: safe32(blockNumber, "block number exceeds 32 bits") - }); - } else if (deltaBlocks > 0) { - borrowState.block = safe32(blockNumber, "block number exceeds 32 bits"); - } - } - - /** - * @notice Calculate COMP accrued by a supplier and possibly transfer it to them - * @param cToken The market in which the supplier is interacting - * @param supplier The address of the supplier to distribute COMP to - */ - function distributeSupplierComp(address cToken, address supplier, bool distributeAll) internal { - CompMarketState storage supplyState = compSupplyState[cToken]; - Double memory supplyIndex = Double({mantissa: supplyState.index}); - Double memory supplierIndex = Double({mantissa: compSupplierIndex[cToken][supplier]}); - compSupplierIndex[cToken][supplier] = supplyIndex.mantissa; - - if (supplierIndex.mantissa == 0 && supplyIndex.mantissa > 0) { - supplierIndex.mantissa = compInitialIndex; - } - - Double memory deltaIndex = sub_(supplyIndex, supplierIndex); - uint supplierTokens = CToken(cToken).balanceOf(supplier); - uint supplierDelta = mul_(supplierTokens, deltaIndex); - uint supplierAccrued = add_(compAccrued[supplier], supplierDelta); - compAccrued[supplier] = transferComp(supplier, supplierAccrued, distributeAll ? 0 : compClaimThreshold); - emit DistributedSupplierComp(CToken(cToken), supplier, supplierDelta, supplyIndex.mantissa); - } - - /** - * @notice Calculate COMP accrued by a borrower and possibly transfer it to them - * @dev Borrowers will not begin to accrue until after the first interaction with the protocol. - * @param cToken The market in which the borrower is interacting - * @param borrower The address of the borrower to distribute COMP to - */ - function distributeBorrowerComp(address cToken, address borrower, Exp memory marketBorrowIndex, bool distributeAll) internal { - CompMarketState storage borrowState = compBorrowState[cToken]; - Double memory borrowIndex = Double({mantissa: borrowState.index}); - Double memory borrowerIndex = Double({mantissa: compBorrowerIndex[cToken][borrower]}); - compBorrowerIndex[cToken][borrower] = borrowIndex.mantissa; - - if (borrowerIndex.mantissa > 0) { - Double memory deltaIndex = sub_(borrowIndex, borrowerIndex); - uint borrowerAmount = div_(CToken(cToken).borrowBalanceStored(borrower), marketBorrowIndex); - uint borrowerDelta = mul_(borrowerAmount, deltaIndex); - uint borrowerAccrued = add_(compAccrued[borrower], borrowerDelta); - compAccrued[borrower] = transferComp(borrower, borrowerAccrued, distributeAll ? 0 : compClaimThreshold); - emit DistributedBorrowerComp(CToken(cToken), borrower, borrowerDelta, borrowIndex.mantissa); - } - } - - /** - * @notice Transfer COMP to the user, if they are above the threshold - * @dev Note: If there is not enough COMP, we do not perform the transfer all. - * @param user The address of the user to transfer COMP to - * @param userAccrued The amount of COMP to (possibly) transfer - * @return The amount of COMP which was NOT transferred to the user - */ - function transferComp(address user, uint userAccrued, uint threshold) internal returns (uint) { - if (userAccrued >= threshold && userAccrued > 0) { - Comp comp = Comp(getCompAddress()); - uint compRemaining = comp.balanceOf(address(this)); - if (userAccrued <= compRemaining) { - comp.transfer(user, userAccrued); - return 0; - } - } - return userAccrued; - } - - /** - * @notice Claim all the comp accrued by holder in all markets - * @param holder The address to claim COMP for - */ - function claimComp(address holder) public { - return claimComp(holder, allMarkets); - } - - /** - * @notice Claim all the comp accrued by holder in the specified markets - * @param holder The address to claim COMP for - * @param cTokens The list of markets to claim COMP in - */ - function claimComp(address holder, CToken[] memory cTokens) public { - address[] memory holders = new address[](1); - holders[0] = holder; - claimComp(holders, cTokens, true, true); - } - - /** - * @notice Claim all comp accrued by the holders - * @param holders The addresses to claim COMP for - * @param cTokens The list of markets to claim COMP in - * @param borrowers Whether or not to claim COMP earned by borrowing - * @param suppliers Whether or not to claim COMP earned by supplying - */ - function claimComp(address[] memory holders, CToken[] memory cTokens, bool borrowers, bool suppliers) public { - for (uint i = 0; i < cTokens.length; i++) { - CToken cToken = cTokens[i]; - require(markets[address(cToken)].isListed, "market must be listed"); - if (borrowers == true) { - Exp memory borrowIndex = Exp({mantissa: cToken.borrowIndex()}); - updateCompBorrowIndex(address(cToken), borrowIndex); - for (uint j = 0; j < holders.length; j++) { - distributeBorrowerComp(address(cToken), holders[j], borrowIndex, true); - } - } - if (suppliers == true) { - updateCompSupplyIndex(address(cToken)); - for (uint j = 0; j < holders.length; j++) { - distributeSupplierComp(address(cToken), holders[j], true); - } - } - } - } - - /*** Comp Distribution Admin ***/ - - /** - * @notice Set the amount of COMP distributed per block - * @param compRate_ The amount of COMP wei per block to distribute - */ - function _setCompRate(uint compRate_) public { - require(adminOrInitializing(), "only admin can change comp rate"); - - uint oldRate = compRate; - compRate = compRate_; - emit NewCompRate(oldRate, compRate_); - - refreshCompSpeedsInternal(); - } - - /** - * @notice Add markets to compMarkets, allowing them to earn COMP in the flywheel - * @param cTokens The addresses of the markets to add - */ - function _addCompMarkets(address[] memory cTokens) public { - require(adminOrInitializing(), "only admin can add comp market"); - - for (uint i = 0; i < cTokens.length; i++) { - _addCompMarketInternal(cTokens[i]); - } - - refreshCompSpeedsInternal(); - } - - function _addCompMarketInternal(address cToken) internal { - Market storage market = markets[cToken]; - require(market.isListed == true, "comp market is not listed"); - require(market.isComped == false, "comp market already added"); - - market.isComped = true; - emit MarketComped(CToken(cToken), true); - - if (compSupplyState[cToken].index == 0 && compSupplyState[cToken].block == 0) { - compSupplyState[cToken] = CompMarketState({ - index: compInitialIndex, - block: safe32(getBlockNumber(), "block number exceeds 32 bits") - }); - } - - if (compBorrowState[cToken].index == 0 && compBorrowState[cToken].block == 0) { - compBorrowState[cToken] = CompMarketState({ - index: compInitialIndex, - block: safe32(getBlockNumber(), "block number exceeds 32 bits") - }); - } - } - - /** - * @notice Remove a market from compMarkets, preventing it from earning COMP in the flywheel - * @param cToken The address of the market to drop - */ - function _dropCompMarket(address cToken) public { - require(msg.sender == admin, "only admin can drop comp market"); - - Market storage market = markets[cToken]; - require(market.isComped == true, "market is not a comp market"); - - market.isComped = false; - emit MarketComped(CToken(cToken), false); - - refreshCompSpeedsInternal(); - } - - /** - * @notice Return all of the markets - * @dev The automatic getter may be used to access an individual market. - * @return The list of market addresses - */ - function getAllMarkets() public view returns (CToken[] memory) { - return allMarkets; - } - - function getBlockNumber() public view returns (uint) { - return block.number; - } - - /** - * @notice Return the address of the COMP token - * @return The address of COMP - */ - function getCompAddress() public view returns (address) { - return 0xc00e94Cb662C3520282E6f5717214004A7f26888; - } -} diff --git a/contracts/ComptrollerG5.sol b/contracts/ComptrollerG5.sol deleted file mode 100644 index 6f2e2b6c0..000000000 --- a/contracts/ComptrollerG5.sol +++ /dev/null @@ -1,1435 +0,0 @@ -pragma solidity ^0.5.16; - -import "./CToken.sol"; -import "./ErrorReporter.sol"; -import "./Exponential.sol"; -import "./PriceOracle.sol"; -import "./ComptrollerInterface.sol"; -import "./ComptrollerStorage.sol"; -import "./Unitroller.sol"; -import "./Governance/Comp.sol"; - -/** - * @title Compound's Comptroller Contract - * @author Compound (modified by Arr00) - */ -contract ComptrollerG5 is ComptrollerV4Storage, ComptrollerInterface, ComptrollerErrorReporter, Exponential { - /// @notice Emitted when an admin supports a market - event MarketListed(CToken cToken); - - /// @notice Emitted when an account enters a market - event MarketEntered(CToken cToken, address account); - - /// @notice Emitted when an account exits a market - event MarketExited(CToken cToken, address account); - - /// @notice Emitted when close factor is changed by admin - event NewCloseFactor(uint oldCloseFactorMantissa, uint newCloseFactorMantissa); - - /// @notice Emitted when a collateral factor is changed by admin - event NewCollateralFactor(CToken cToken, uint oldCollateralFactorMantissa, uint newCollateralFactorMantissa); - - /// @notice Emitted when liquidation incentive is changed by admin - event NewLiquidationIncentive(uint oldLiquidationIncentiveMantissa, uint newLiquidationIncentiveMantissa); - - /// @notice Emitted when maxAssets is changed by admin - event NewMaxAssets(uint oldMaxAssets, uint newMaxAssets); - - /// @notice Emitted when price oracle is changed - event NewPriceOracle(PriceOracle oldPriceOracle, PriceOracle newPriceOracle); - - /// @notice Emitted when pause guardian is changed - event NewPauseGuardian(address oldPauseGuardian, address newPauseGuardian); - - /// @notice Emitted when an action is paused globally - event ActionPaused(string action, bool pauseState); - - /// @notice Emitted when an action is paused on a market - event ActionPaused(CToken cToken, string action, bool pauseState); - - /// @notice Emitted when market comped status is changed - event MarketComped(CToken cToken, bool isComped); - - /// @notice Emitted when COMP rate is changed - event NewCompRate(uint oldCompRate, uint newCompRate); - - /// @notice Emitted when a new COMP speed is calculated for a market - event CompSpeedUpdated(CToken indexed cToken, uint newSpeed); - - /// @notice Emitted when COMP is distributed to a supplier - event DistributedSupplierComp(CToken indexed cToken, address indexed supplier, uint compDelta, uint compSupplyIndex); - - /// @notice Emitted when COMP is distributed to a borrower - event DistributedBorrowerComp(CToken indexed cToken, address indexed borrower, uint compDelta, uint compBorrowIndex); - - /// @notice Emitted when borrow cap for a cToken is changed - event NewBorrowCap(CToken indexed cToken, uint newBorrowCap); - - /// @notice Emitted when borrow cap guardian is changed - event NewBorrowCapGuardian(address oldBorrowCapGuardian, address newBorrowCapGuardian); - - /// @notice The threshold above which the flywheel transfers COMP, in wei - uint public constant compClaimThreshold = 0.001e18; - - /// @notice The initial COMP index for a market - uint224 public constant compInitialIndex = 1e36; - - // closeFactorMantissa must be strictly greater than this value - uint internal constant closeFactorMinMantissa = 0.05e18; // 0.05 - - // closeFactorMantissa must not exceed this value - uint internal constant closeFactorMaxMantissa = 0.9e18; // 0.9 - - // No collateralFactorMantissa may exceed this value - uint internal constant collateralFactorMaxMantissa = 0.9e18; // 0.9 - - // liquidationIncentiveMantissa must be no less than this value - uint internal constant liquidationIncentiveMinMantissa = 1.0e18; // 1.0 - - // liquidationIncentiveMantissa must be no greater than this value - uint internal constant liquidationIncentiveMaxMantissa = 1.5e18; // 1.5 - - constructor() public { - admin = msg.sender; - } - - /*** Assets You Are In ***/ - - /** - * @notice Returns the assets an account has entered - * @param account The address of the account to pull assets for - * @return A dynamic list with the assets the account has entered - */ - function getAssetsIn(address account) external view returns (CToken[] memory) { - CToken[] memory assetsIn = accountAssets[account]; - - return assetsIn; - } - - /** - * @notice Returns whether the given account is entered in the given asset - * @param account The address of the account to check - * @param cToken The cToken to check - * @return True if the account is in the asset, otherwise false. - */ - function checkMembership(address account, CToken cToken) external view returns (bool) { - return markets[address(cToken)].accountMembership[account]; - } - - /** - * @notice Add assets to be included in account liquidity calculation - * @param cTokens The list of addresses of the cToken markets to be enabled - * @return Success indicator for whether each corresponding market was entered - */ - function enterMarkets(address[] memory cTokens) public returns (uint[] memory) { - uint len = cTokens.length; - - uint[] memory results = new uint[](len); - for (uint i = 0; i < len; i++) { - CToken cToken = CToken(cTokens[i]); - - results[i] = uint(addToMarketInternal(cToken, msg.sender)); - } - - return results; - } - - /** - * @notice Add the market to the borrower's "assets in" for liquidity calculations - * @param cToken The market to enter - * @param borrower The address of the account to modify - * @return Success indicator for whether the market was entered - */ - function addToMarketInternal(CToken cToken, address borrower) internal returns (Error) { - Market storage marketToJoin = markets[address(cToken)]; - - if (!marketToJoin.isListed) { - // market is not listed, cannot join - return Error.MARKET_NOT_LISTED; - } - - if (marketToJoin.accountMembership[borrower] == true) { - // already joined - return Error.NO_ERROR; - } - - if (accountAssets[borrower].length >= maxAssets) { - // no space, cannot join - return Error.TOO_MANY_ASSETS; - } - - // survived the gauntlet, add to list - // NOTE: we store these somewhat redundantly as a significant optimization - // this avoids having to iterate through the list for the most common use cases - // that is, only when we need to perform liquidity checks - // and not whenever we want to check if an account is in a particular market - marketToJoin.accountMembership[borrower] = true; - accountAssets[borrower].push(cToken); - - emit MarketEntered(cToken, borrower); - - return Error.NO_ERROR; - } - - /** - * @notice Removes asset from sender's account liquidity calculation - * @dev Sender must not have an outstanding borrow balance in the asset, - * or be providing necessary collateral for an outstanding borrow. - * @param cTokenAddress The address of the asset to be removed - * @return Whether or not the account successfully exited the market - */ - function exitMarket(address cTokenAddress) external returns (uint) { - CToken cToken = CToken(cTokenAddress); - /* Get sender tokensHeld and amountOwed underlying from the cToken */ - (uint oErr, uint tokensHeld, uint amountOwed, ) = cToken.getAccountSnapshot(msg.sender); - require(oErr == 0, "exitMarket: getAccountSnapshot failed"); // semi-opaque error code - - /* Fail if the sender has a borrow balance */ - if (amountOwed != 0) { - return fail(Error.NONZERO_BORROW_BALANCE, FailureInfo.EXIT_MARKET_BALANCE_OWED); - } - - /* Fail if the sender is not permitted to redeem all of their tokens */ - uint allowed = redeemAllowedInternal(cTokenAddress, msg.sender, tokensHeld); - if (allowed != 0) { - return failOpaque(Error.REJECTION, FailureInfo.EXIT_MARKET_REJECTION, allowed); - } - - Market storage marketToExit = markets[address(cToken)]; - - /* Return true if the sender is not already ‘in’ the market */ - if (!marketToExit.accountMembership[msg.sender]) { - return uint(Error.NO_ERROR); - } - - /* Set cToken account membership to false */ - delete marketToExit.accountMembership[msg.sender]; - - /* Delete cToken from the account’s list of assets */ - // load into memory for faster iteration - CToken[] memory userAssetList = accountAssets[msg.sender]; - uint len = userAssetList.length; - uint assetIndex = len; - for (uint i = 0; i < len; i++) { - if (userAssetList[i] == cToken) { - assetIndex = i; - break; - } - } - - // We *must* have found the asset in the list or our redundant data structure is broken - assert(assetIndex < len); - - // copy last item in list to location of item to be removed, reduce length by 1 - CToken[] storage storedList = accountAssets[msg.sender]; - storedList[assetIndex] = storedList[storedList.length - 1]; - storedList.length--; - - emit MarketExited(cToken, msg.sender); - - return uint(Error.NO_ERROR); - } - - /*** Policy Hooks ***/ - - /** - * @notice Checks if the account should be allowed to mint tokens in the given market - * @param cToken The market to verify the mint against - * @param minter The account which would get the minted tokens - * @param mintAmount The amount of underlying being supplied to the market in exchange for tokens - * @return 0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol) - */ - function mintAllowed(address cToken, address minter, uint mintAmount) external returns (uint) { - // Pausing is a very serious situation - we revert to sound the alarms - require(!mintGuardianPaused[cToken], "mint is paused"); - - // Shh - currently unused - minter; - mintAmount; - - if (!markets[cToken].isListed) { - return uint(Error.MARKET_NOT_LISTED); - } - - // Keep the flywheel moving - updateCompSupplyIndex(cToken); - distributeSupplierComp(cToken, minter, false); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Validates mint and reverts on rejection. May emit logs. - * @param cToken Asset being minted - * @param minter The address minting the tokens - * @param actualMintAmount The amount of the underlying asset being minted - * @param mintTokens The number of tokens being minted - */ - function mintVerify(address cToken, address minter, uint actualMintAmount, uint mintTokens) external { - // Shh - currently unused - cToken; - minter; - actualMintAmount; - mintTokens; - - // Shh - we don't ever want this hook to be marked pure - if (false) { - maxAssets = maxAssets; - } - } - - /** - * @notice Checks if the account should be allowed to redeem tokens in the given market - * @param cToken The market to verify the redeem against - * @param redeemer The account which would redeem the tokens - * @param redeemTokens The number of cTokens to exchange for the underlying asset in the market - * @return 0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol) - */ - function redeemAllowed(address cToken, address redeemer, uint redeemTokens) external returns (uint) { - uint allowed = redeemAllowedInternal(cToken, redeemer, redeemTokens); - if (allowed != uint(Error.NO_ERROR)) { - return allowed; - } - - // Keep the flywheel moving - updateCompSupplyIndex(cToken); - distributeSupplierComp(cToken, redeemer, false); - - return uint(Error.NO_ERROR); - } - - function redeemAllowedInternal(address cToken, address redeemer, uint redeemTokens) internal view returns (uint) { - if (!markets[cToken].isListed) { - return uint(Error.MARKET_NOT_LISTED); - } - - /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */ - if (!markets[cToken].accountMembership[redeemer]) { - return uint(Error.NO_ERROR); - } - - /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */ - (Error err, , uint shortfall) = getHypotheticalAccountLiquidityInternal(redeemer, CToken(cToken), redeemTokens, 0); - if (err != Error.NO_ERROR) { - return uint(err); - } - if (shortfall > 0) { - return uint(Error.INSUFFICIENT_LIQUIDITY); - } - - return uint(Error.NO_ERROR); - } - - /** - * @notice Validates redeem and reverts on rejection. May emit logs. - * @param cToken Asset being redeemed - * @param redeemer The address redeeming the tokens - * @param redeemAmount The amount of the underlying asset being redeemed - * @param redeemTokens The number of tokens being redeemed - */ - function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) external { - // Shh - currently unused - cToken; - redeemer; - - // Require tokens is zero or amount is also zero - if (redeemTokens == 0 && redeemAmount > 0) { - revert("redeemTokens zero"); - } - } - - /** - * @notice Checks if the account should be allowed to borrow the underlying asset of the given market - * @param cToken The market to verify the borrow against - * @param borrower The account which would borrow the asset - * @param borrowAmount The amount of underlying the account would borrow - * @return 0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol) - */ - function borrowAllowed(address cToken, address borrower, uint borrowAmount) external returns (uint) { - // Pausing is a very serious situation - we revert to sound the alarms - require(!borrowGuardianPaused[cToken], "borrow is paused"); - - if (!markets[cToken].isListed) { - return uint(Error.MARKET_NOT_LISTED); - } - - if (!markets[cToken].accountMembership[borrower]) { - // only cTokens may call borrowAllowed if borrower not in market - require(msg.sender == cToken, "sender must be cToken"); - - // attempt to add borrower to the market - Error err = addToMarketInternal(CToken(msg.sender), borrower); - if (err != Error.NO_ERROR) { - return uint(err); - } - - // it should be impossible to break the important invariant - assert(markets[cToken].accountMembership[borrower]); - } - - if (oracle.getUnderlyingPrice(CToken(cToken)) == 0) { - return uint(Error.PRICE_ERROR); - } - - - uint borrowCap = borrowCaps[cToken]; - // Borrow cap of 0 corresponds to unlimited borrowing - if (borrowCap != 0) { - uint totalBorrows = CToken(cToken).totalBorrows(); - (MathError mathErr, uint nextTotalBorrows) = addUInt(totalBorrows, borrowAmount); - require(mathErr == MathError.NO_ERROR, "total borrows overflow"); - require(nextTotalBorrows < borrowCap, "market borrow cap reached"); - } - - (Error err, , uint shortfall) = getHypotheticalAccountLiquidityInternal(borrower, CToken(cToken), 0, borrowAmount); - if (err != Error.NO_ERROR) { - return uint(err); - } - if (shortfall > 0) { - return uint(Error.INSUFFICIENT_LIQUIDITY); - } - - // Keep the flywheel moving - Exp memory borrowIndex = Exp({mantissa: CToken(cToken).borrowIndex()}); - updateCompBorrowIndex(cToken, borrowIndex); - distributeBorrowerComp(cToken, borrower, borrowIndex, false); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Validates borrow and reverts on rejection. May emit logs. - * @param cToken Asset whose underlying is being borrowed - * @param borrower The address borrowing the underlying - * @param borrowAmount The amount of the underlying asset requested to borrow - */ - function borrowVerify(address cToken, address borrower, uint borrowAmount) external { - // Shh - currently unused - cToken; - borrower; - borrowAmount; - - // Shh - we don't ever want this hook to be marked pure - if (false) { - maxAssets = maxAssets; - } - } - - /** - * @notice Checks if the account should be allowed to repay a borrow in the given market - * @param cToken The market to verify the repay against - * @param payer The account which would repay the asset - * @param borrower The account which would borrowed the asset - * @param repayAmount The amount of the underlying asset the account would repay - * @return 0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol) - */ - function repayBorrowAllowed( - address cToken, - address payer, - address borrower, - uint repayAmount) external returns (uint) { - // Shh - currently unused - payer; - borrower; - repayAmount; - - if (!markets[cToken].isListed) { - return uint(Error.MARKET_NOT_LISTED); - } - - // Keep the flywheel moving - Exp memory borrowIndex = Exp({mantissa: CToken(cToken).borrowIndex()}); - updateCompBorrowIndex(cToken, borrowIndex); - distributeBorrowerComp(cToken, borrower, borrowIndex, false); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Validates repayBorrow and reverts on rejection. May emit logs. - * @param cToken Asset being repaid - * @param payer The address repaying the borrow - * @param borrower The address of the borrower - * @param actualRepayAmount The amount of underlying being repaid - */ - function repayBorrowVerify( - address cToken, - address payer, - address borrower, - uint actualRepayAmount, - uint borrowerIndex) external { - // Shh - currently unused - cToken; - payer; - borrower; - actualRepayAmount; - borrowerIndex; - - // Shh - we don't ever want this hook to be marked pure - if (false) { - maxAssets = maxAssets; - } - } - - /** - * @notice Checks if the liquidation should be allowed to occur - * @param cTokenBorrowed Asset which was borrowed by the borrower - * @param cTokenCollateral Asset which was used as collateral and will be seized - * @param liquidator The address repaying the borrow and seizing the collateral - * @param borrower The address of the borrower - * @param repayAmount The amount of underlying being repaid - */ - function liquidateBorrowAllowed( - address cTokenBorrowed, - address cTokenCollateral, - address liquidator, - address borrower, - uint repayAmount) external returns (uint) { - // Shh - currently unused - liquidator; - - if (!markets[cTokenBorrowed].isListed || !markets[cTokenCollateral].isListed) { - return uint(Error.MARKET_NOT_LISTED); - } - - /* The borrower must have shortfall in order to be liquidatable */ - (Error err, , uint shortfall) = getAccountLiquidityInternal(borrower); - if (err != Error.NO_ERROR) { - return uint(err); - } - if (shortfall == 0) { - return uint(Error.INSUFFICIENT_SHORTFALL); - } - - /* The liquidator may not repay more than what is allowed by the closeFactor */ - uint borrowBalance = CToken(cTokenBorrowed).borrowBalanceStored(borrower); - (MathError mathErr, uint maxClose) = mulScalarTruncate(Exp({mantissa: closeFactorMantissa}), borrowBalance); - if (mathErr != MathError.NO_ERROR) { - return uint(Error.MATH_ERROR); - } - if (repayAmount > maxClose) { - return uint(Error.TOO_MUCH_REPAY); - } - - return uint(Error.NO_ERROR); - } - - /** - * @notice Validates liquidateBorrow and reverts on rejection. May emit logs. - * @param cTokenBorrowed Asset which was borrowed by the borrower - * @param cTokenCollateral Asset which was used as collateral and will be seized - * @param liquidator The address repaying the borrow and seizing the collateral - * @param borrower The address of the borrower - * @param actualRepayAmount The amount of underlying being repaid - */ - function liquidateBorrowVerify( - address cTokenBorrowed, - address cTokenCollateral, - address liquidator, - address borrower, - uint actualRepayAmount, - uint seizeTokens) external { - // Shh - currently unused - cTokenBorrowed; - cTokenCollateral; - liquidator; - borrower; - actualRepayAmount; - seizeTokens; - - // Shh - we don't ever want this hook to be marked pure - if (false) { - maxAssets = maxAssets; - } - } - - /** - * @notice Checks if the seizing of assets should be allowed to occur - * @param cTokenCollateral Asset which was used as collateral and will be seized - * @param cTokenBorrowed Asset which was borrowed by the borrower - * @param liquidator The address repaying the borrow and seizing the collateral - * @param borrower The address of the borrower - * @param seizeTokens The number of collateral tokens to seize - */ - function seizeAllowed( - address cTokenCollateral, - address cTokenBorrowed, - address liquidator, - address borrower, - uint seizeTokens) external returns (uint) { - // Pausing is a very serious situation - we revert to sound the alarms - require(!seizeGuardianPaused, "seize is paused"); - - // Shh - currently unused - seizeTokens; - - if (!markets[cTokenCollateral].isListed || !markets[cTokenBorrowed].isListed) { - return uint(Error.MARKET_NOT_LISTED); - } - - if (CToken(cTokenCollateral).comptroller() != CToken(cTokenBorrowed).comptroller()) { - return uint(Error.COMPTROLLER_MISMATCH); - } - - // Keep the flywheel moving - updateCompSupplyIndex(cTokenCollateral); - distributeSupplierComp(cTokenCollateral, borrower, false); - distributeSupplierComp(cTokenCollateral, liquidator, false); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Validates seize and reverts on rejection. May emit logs. - * @param cTokenCollateral Asset which was used as collateral and will be seized - * @param cTokenBorrowed Asset which was borrowed by the borrower - * @param liquidator The address repaying the borrow and seizing the collateral - * @param borrower The address of the borrower - * @param seizeTokens The number of collateral tokens to seize - */ - function seizeVerify( - address cTokenCollateral, - address cTokenBorrowed, - address liquidator, - address borrower, - uint seizeTokens) external { - // Shh - currently unused - cTokenCollateral; - cTokenBorrowed; - liquidator; - borrower; - seizeTokens; - - // Shh - we don't ever want this hook to be marked pure - if (false) { - maxAssets = maxAssets; - } - } - - /** - * @notice Checks if the account should be allowed to transfer tokens in the given market - * @param cToken The market to verify the transfer against - * @param src The account which sources the tokens - * @param dst The account which receives the tokens - * @param transferTokens The number of cTokens to transfer - * @return 0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol) - */ - function transferAllowed(address cToken, address src, address dst, uint transferTokens) external returns (uint) { - // Pausing is a very serious situation - we revert to sound the alarms - require(!transferGuardianPaused, "transfer is paused"); - - // Currently the only consideration is whether or not - // the src is allowed to redeem this many tokens - uint allowed = redeemAllowedInternal(cToken, src, transferTokens); - if (allowed != uint(Error.NO_ERROR)) { - return allowed; - } - - // Keep the flywheel moving - updateCompSupplyIndex(cToken); - distributeSupplierComp(cToken, src, false); - distributeSupplierComp(cToken, dst, false); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Validates transfer and reverts on rejection. May emit logs. - * @param cToken Asset being transferred - * @param src The account which sources the tokens - * @param dst The account which receives the tokens - * @param transferTokens The number of cTokens to transfer - */ - function transferVerify(address cToken, address src, address dst, uint transferTokens) external { - // Shh - currently unused - cToken; - src; - dst; - transferTokens; - - // Shh - we don't ever want this hook to be marked pure - if (false) { - maxAssets = maxAssets; - } - } - - /*** Liquidity/Liquidation Calculations ***/ - - /** - * @dev Local vars for avoiding stack-depth limits in calculating account liquidity. - * Note that `cTokenBalance` is the number of cTokens the account owns in the market, - * whereas `borrowBalance` is the amount of underlying that the account has borrowed. - */ - struct AccountLiquidityLocalVars { - uint sumCollateral; - uint sumBorrowPlusEffects; - uint cTokenBalance; - uint borrowBalance; - uint exchangeRateMantissa; - uint oraclePriceMantissa; - Exp collateralFactor; - Exp exchangeRate; - Exp oraclePrice; - Exp tokensToDenom; - } - - /** - * @notice Determine the current account liquidity wrt collateral requirements - * @return (possible error code (semi-opaque), - account liquidity in excess of collateral requirements, - * account shortfall below collateral requirements) - */ - function getAccountLiquidity(address account) public view returns (uint, uint, uint) { - (Error err, uint liquidity, uint shortfall) = getHypotheticalAccountLiquidityInternal(account, CToken(0), 0, 0); - - return (uint(err), liquidity, shortfall); - } - - /** - * @notice Determine the current account liquidity wrt collateral requirements - * @return (possible error code, - account liquidity in excess of collateral requirements, - * account shortfall below collateral requirements) - */ - function getAccountLiquidityInternal(address account) internal view returns (Error, uint, uint) { - return getHypotheticalAccountLiquidityInternal(account, CToken(0), 0, 0); - } - - /** - * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed - * @param cTokenModify The market to hypothetically redeem/borrow in - * @param account The account to determine liquidity for - * @param redeemTokens The number of tokens to hypothetically redeem - * @param borrowAmount The amount of underlying to hypothetically borrow - * @return (possible error code (semi-opaque), - hypothetical account liquidity in excess of collateral requirements, - * hypothetical account shortfall below collateral requirements) - */ - function getHypotheticalAccountLiquidity( - address account, - address cTokenModify, - uint redeemTokens, - uint borrowAmount) public view returns (uint, uint, uint) { - (Error err, uint liquidity, uint shortfall) = getHypotheticalAccountLiquidityInternal(account, CToken(cTokenModify), redeemTokens, borrowAmount); - return (uint(err), liquidity, shortfall); - } - - /** - * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed - * @param cTokenModify The market to hypothetically redeem/borrow in - * @param account The account to determine liquidity for - * @param redeemTokens The number of tokens to hypothetically redeem - * @param borrowAmount The amount of underlying to hypothetically borrow - * @dev Note that we calculate the exchangeRateStored for each collateral cToken using stored data, - * without calculating accumulated interest. - * @return (possible error code, - hypothetical account liquidity in excess of collateral requirements, - * hypothetical account shortfall below collateral requirements) - */ - function getHypotheticalAccountLiquidityInternal( - address account, - CToken cTokenModify, - uint redeemTokens, - uint borrowAmount) internal view returns (Error, uint, uint) { - - AccountLiquidityLocalVars memory vars; // Holds all our calculation results - uint oErr; - MathError mErr; - - // For each asset the account is in - CToken[] memory assets = accountAssets[account]; - for (uint i = 0; i < assets.length; i++) { - CToken asset = assets[i]; - - // Read the balances and exchange rate from the cToken - (oErr, vars.cTokenBalance, vars.borrowBalance, vars.exchangeRateMantissa) = asset.getAccountSnapshot(account); - if (oErr != 0) { // semi-opaque error code, we assume NO_ERROR == 0 is invariant between upgrades - return (Error.SNAPSHOT_ERROR, 0, 0); - } - vars.collateralFactor = Exp({mantissa: markets[address(asset)].collateralFactorMantissa}); - vars.exchangeRate = Exp({mantissa: vars.exchangeRateMantissa}); - - // Get the normalized price of the asset - vars.oraclePriceMantissa = oracle.getUnderlyingPrice(asset); - if (vars.oraclePriceMantissa == 0) { - return (Error.PRICE_ERROR, 0, 0); - } - vars.oraclePrice = Exp({mantissa: vars.oraclePriceMantissa}); - - // Pre-compute a conversion factor from tokens -> ether (normalized price value) - (mErr, vars.tokensToDenom) = mulExp3(vars.collateralFactor, vars.exchangeRate, vars.oraclePrice); - if (mErr != MathError.NO_ERROR) { - return (Error.MATH_ERROR, 0, 0); - } - - // sumCollateral += tokensToDenom * cTokenBalance - (mErr, vars.sumCollateral) = mulScalarTruncateAddUInt(vars.tokensToDenom, vars.cTokenBalance, vars.sumCollateral); - if (mErr != MathError.NO_ERROR) { - return (Error.MATH_ERROR, 0, 0); - } - - // sumBorrowPlusEffects += oraclePrice * borrowBalance - (mErr, vars.sumBorrowPlusEffects) = mulScalarTruncateAddUInt(vars.oraclePrice, vars.borrowBalance, vars.sumBorrowPlusEffects); - if (mErr != MathError.NO_ERROR) { - return (Error.MATH_ERROR, 0, 0); - } - - // Calculate effects of interacting with cTokenModify - if (asset == cTokenModify) { - // redeem effect - // sumBorrowPlusEffects += tokensToDenom * redeemTokens - (mErr, vars.sumBorrowPlusEffects) = mulScalarTruncateAddUInt(vars.tokensToDenom, redeemTokens, vars.sumBorrowPlusEffects); - if (mErr != MathError.NO_ERROR) { - return (Error.MATH_ERROR, 0, 0); - } - - // borrow effect - // sumBorrowPlusEffects += oraclePrice * borrowAmount - (mErr, vars.sumBorrowPlusEffects) = mulScalarTruncateAddUInt(vars.oraclePrice, borrowAmount, vars.sumBorrowPlusEffects); - if (mErr != MathError.NO_ERROR) { - return (Error.MATH_ERROR, 0, 0); - } - } - } - - // These are safe, as the underflow condition is checked first - if (vars.sumCollateral > vars.sumBorrowPlusEffects) { - return (Error.NO_ERROR, vars.sumCollateral - vars.sumBorrowPlusEffects, 0); - } else { - return (Error.NO_ERROR, 0, vars.sumBorrowPlusEffects - vars.sumCollateral); - } - } - - /** - * @notice Calculate number of tokens of collateral asset to seize given an underlying amount - * @dev Used in liquidation (called in cToken.liquidateBorrowFresh) - * @param cTokenBorrowed The address of the borrowed cToken - * @param cTokenCollateral The address of the collateral cToken - * @param actualRepayAmount The amount of cTokenBorrowed underlying to convert into cTokenCollateral tokens - * @return (errorCode, number of cTokenCollateral tokens to be seized in a liquidation) - */ - function liquidateCalculateSeizeTokens(address cTokenBorrowed, address cTokenCollateral, uint actualRepayAmount) external view returns (uint, uint) { - /* Read oracle prices for borrowed and collateral markets */ - uint priceBorrowedMantissa = oracle.getUnderlyingPrice(CToken(cTokenBorrowed)); - uint priceCollateralMantissa = oracle.getUnderlyingPrice(CToken(cTokenCollateral)); - if (priceBorrowedMantissa == 0 || priceCollateralMantissa == 0) { - return (uint(Error.PRICE_ERROR), 0); - } - - /* - * Get the exchange rate and calculate the number of collateral tokens to seize: - * seizeAmount = actualRepayAmount * liquidationIncentive * priceBorrowed / priceCollateral - * seizeTokens = seizeAmount / exchangeRate - * = actualRepayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate) - */ - uint exchangeRateMantissa = CToken(cTokenCollateral).exchangeRateStored(); // Note: reverts on error - uint seizeTokens; - Exp memory numerator; - Exp memory denominator; - Exp memory ratio; - MathError mathErr; - - (mathErr, numerator) = mulExp(liquidationIncentiveMantissa, priceBorrowedMantissa); - if (mathErr != MathError.NO_ERROR) { - return (uint(Error.MATH_ERROR), 0); - } - - (mathErr, denominator) = mulExp(priceCollateralMantissa, exchangeRateMantissa); - if (mathErr != MathError.NO_ERROR) { - return (uint(Error.MATH_ERROR), 0); - } - - (mathErr, ratio) = divExp(numerator, denominator); - if (mathErr != MathError.NO_ERROR) { - return (uint(Error.MATH_ERROR), 0); - } - - (mathErr, seizeTokens) = mulScalarTruncate(ratio, actualRepayAmount); - if (mathErr != MathError.NO_ERROR) { - return (uint(Error.MATH_ERROR), 0); - } - - return (uint(Error.NO_ERROR), seizeTokens); - } - - /*** Admin Functions ***/ - - /** - * @notice Sets a new price oracle for the comptroller - * @dev Admin function to set a new price oracle - * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) - */ - function _setPriceOracle(PriceOracle newOracle) public returns (uint) { - // Check caller is admin - if (msg.sender != admin) { - return fail(Error.UNAUTHORIZED, FailureInfo.SET_PRICE_ORACLE_OWNER_CHECK); - } - - // Track the old oracle for the comptroller - PriceOracle oldOracle = oracle; - - // Set comptroller's oracle to newOracle - oracle = newOracle; - - // Emit NewPriceOracle(oldOracle, newOracle) - emit NewPriceOracle(oldOracle, newOracle); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Sets the closeFactor used when liquidating borrows - * @dev Admin function to set closeFactor - * @param newCloseFactorMantissa New close factor, scaled by 1e18 - * @return uint 0=success, otherwise a failure. (See ErrorReporter for details) - */ - function _setCloseFactor(uint newCloseFactorMantissa) external returns (uint) { - // Check caller is admin - if (msg.sender != admin) { - return fail(Error.UNAUTHORIZED, FailureInfo.SET_CLOSE_FACTOR_OWNER_CHECK); - } - - Exp memory newCloseFactorExp = Exp({mantissa: newCloseFactorMantissa}); - Exp memory lowLimit = Exp({mantissa: closeFactorMinMantissa}); - if (lessThanOrEqualExp(newCloseFactorExp, lowLimit)) { - return fail(Error.INVALID_CLOSE_FACTOR, FailureInfo.SET_CLOSE_FACTOR_VALIDATION); - } - - Exp memory highLimit = Exp({mantissa: closeFactorMaxMantissa}); - if (lessThanExp(highLimit, newCloseFactorExp)) { - return fail(Error.INVALID_CLOSE_FACTOR, FailureInfo.SET_CLOSE_FACTOR_VALIDATION); - } - - uint oldCloseFactorMantissa = closeFactorMantissa; - closeFactorMantissa = newCloseFactorMantissa; - emit NewCloseFactor(oldCloseFactorMantissa, closeFactorMantissa); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Sets the collateralFactor for a market - * @dev Admin function to set per-market collateralFactor - * @param cToken The market to set the factor on - * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18 - * @return uint 0=success, otherwise a failure. (See ErrorReporter for details) - */ - function _setCollateralFactor(CToken cToken, uint newCollateralFactorMantissa) external returns (uint) { - // Check caller is admin - if (msg.sender != admin) { - return fail(Error.UNAUTHORIZED, FailureInfo.SET_COLLATERAL_FACTOR_OWNER_CHECK); - } - - // Verify market is listed - Market storage market = markets[address(cToken)]; - if (!market.isListed) { - return fail(Error.MARKET_NOT_LISTED, FailureInfo.SET_COLLATERAL_FACTOR_NO_EXISTS); - } - - Exp memory newCollateralFactorExp = Exp({mantissa: newCollateralFactorMantissa}); - - // Check collateral factor <= 0.9 - Exp memory highLimit = Exp({mantissa: collateralFactorMaxMantissa}); - if (lessThanExp(highLimit, newCollateralFactorExp)) { - return fail(Error.INVALID_COLLATERAL_FACTOR, FailureInfo.SET_COLLATERAL_FACTOR_VALIDATION); - } - - // If collateral factor != 0, fail if price == 0 - if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(cToken) == 0) { - return fail(Error.PRICE_ERROR, FailureInfo.SET_COLLATERAL_FACTOR_WITHOUT_PRICE); - } - - // Set market's collateral factor to new collateral factor, remember old value - uint oldCollateralFactorMantissa = market.collateralFactorMantissa; - market.collateralFactorMantissa = newCollateralFactorMantissa; - - // Emit event with asset, old collateral factor, and new collateral factor - emit NewCollateralFactor(cToken, oldCollateralFactorMantissa, newCollateralFactorMantissa); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Sets maxAssets which controls how many markets can be entered - * @dev Admin function to set maxAssets - * @param newMaxAssets New max assets - * @return uint 0=success, otherwise a failure. (See ErrorReporter for details) - */ - function _setMaxAssets(uint newMaxAssets) external returns (uint) { - // Check caller is admin - if (msg.sender != admin) { - return fail(Error.UNAUTHORIZED, FailureInfo.SET_MAX_ASSETS_OWNER_CHECK); - } - - uint oldMaxAssets = maxAssets; - maxAssets = newMaxAssets; - emit NewMaxAssets(oldMaxAssets, newMaxAssets); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Sets liquidationIncentive - * @dev Admin function to set liquidationIncentive - * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18 - * @return uint 0=success, otherwise a failure. (See ErrorReporter for details) - */ - function _setLiquidationIncentive(uint newLiquidationIncentiveMantissa) external returns (uint) { - // Check caller is admin - if (msg.sender != admin) { - return fail(Error.UNAUTHORIZED, FailureInfo.SET_LIQUIDATION_INCENTIVE_OWNER_CHECK); - } - - // Check de-scaled min <= newLiquidationIncentive <= max - Exp memory newLiquidationIncentive = Exp({mantissa: newLiquidationIncentiveMantissa}); - Exp memory minLiquidationIncentive = Exp({mantissa: liquidationIncentiveMinMantissa}); - if (lessThanExp(newLiquidationIncentive, minLiquidationIncentive)) { - return fail(Error.INVALID_LIQUIDATION_INCENTIVE, FailureInfo.SET_LIQUIDATION_INCENTIVE_VALIDATION); - } - - Exp memory maxLiquidationIncentive = Exp({mantissa: liquidationIncentiveMaxMantissa}); - if (lessThanExp(maxLiquidationIncentive, newLiquidationIncentive)) { - return fail(Error.INVALID_LIQUIDATION_INCENTIVE, FailureInfo.SET_LIQUIDATION_INCENTIVE_VALIDATION); - } - - // Save current value for use in log - uint oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa; - - // Set liquidation incentive to new incentive - liquidationIncentiveMantissa = newLiquidationIncentiveMantissa; - - // Emit event with old incentive, new incentive - emit NewLiquidationIncentive(oldLiquidationIncentiveMantissa, newLiquidationIncentiveMantissa); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Add the market to the markets mapping and set it as listed - * @dev Admin function to set isListed and add support for the market - * @param cToken The address of the market (token) to list - * @return uint 0=success, otherwise a failure. (See enum Error for details) - */ - function _supportMarket(CToken cToken) external returns (uint) { - if (msg.sender != admin) { - return fail(Error.UNAUTHORIZED, FailureInfo.SUPPORT_MARKET_OWNER_CHECK); - } - - if (markets[address(cToken)].isListed) { - return fail(Error.MARKET_ALREADY_LISTED, FailureInfo.SUPPORT_MARKET_EXISTS); - } - - cToken.isCToken(); // Sanity check to make sure its really a CToken - - markets[address(cToken)] = Market({isListed: true, isComped: false, collateralFactorMantissa: 0}); - - _addMarketInternal(address(cToken)); - - emit MarketListed(cToken); - - return uint(Error.NO_ERROR); - } - - function _addMarketInternal(address cToken) internal { - for (uint i = 0; i < allMarkets.length; i ++) { - require(allMarkets[i] != CToken(cToken), "market already added"); - } - allMarkets.push(CToken(cToken)); - } - - - /** - * @notice Set the given borrow caps for the given cToken markets. Borrowing that brings total borrows to or above borrow cap will revert. - * @dev Admin or borrowCapGuardian function to set the borrow caps. A borrow cap of 0 corresponds to unlimited borrowing. - * @param cTokens The addresses of the markets (tokens) to change the borrow caps for - * @param newBorrowCaps The new borrow cap values in underlying to be set. A value of 0 corresponds to unlimited borrowing. - */ - function _setMarketBorrowCaps(CToken[] calldata cTokens, uint[] calldata newBorrowCaps) external { - require(msg.sender == admin || msg.sender == borrowCapGuardian, "only admin or borrow cap guardian can set borrow caps"); - - uint numMarkets = cTokens.length; - uint numBorrowCaps = newBorrowCaps.length; - - require(numMarkets != 0 && numMarkets == numBorrowCaps, "invalid input"); - - for(uint i = 0; i < numMarkets; i++) { - borrowCaps[address(cTokens[i])] = newBorrowCaps[i]; - emit NewBorrowCap(cTokens[i], newBorrowCaps[i]); - } - } - - /** - * @notice Admin function to change the Borrow Cap Guardian - * @param newBorrowCapGuardian The address of the new Borrow Cap Guardian - */ - function _setBorrowCapGuardian(address newBorrowCapGuardian) external { - require(msg.sender == admin, "only admin can set borrow cap guardian"); - - // Save current value for inclusion in log - address oldBorrowCapGuardian = borrowCapGuardian; - - // Store borrowCapGuardian with value newBorrowCapGuardian - borrowCapGuardian = newBorrowCapGuardian; - - // Emit NewBorrowCapGuardian(OldBorrowCapGuardian, NewBorrowCapGuardian) - emit NewBorrowCapGuardian(oldBorrowCapGuardian, newBorrowCapGuardian); - } - - /** - * @notice Admin function to change the Pause Guardian - * @param newPauseGuardian The address of the new Pause Guardian - * @return uint 0=success, otherwise a failure. (See enum Error for details) - */ - function _setPauseGuardian(address newPauseGuardian) public returns (uint) { - if (msg.sender != admin) { - return fail(Error.UNAUTHORIZED, FailureInfo.SET_PAUSE_GUARDIAN_OWNER_CHECK); - } - - // Save current value for inclusion in log - address oldPauseGuardian = pauseGuardian; - - // Store pauseGuardian with value newPauseGuardian - pauseGuardian = newPauseGuardian; - - // Emit NewPauseGuardian(OldPauseGuardian, NewPauseGuardian) - emit NewPauseGuardian(oldPauseGuardian, pauseGuardian); - - return uint(Error.NO_ERROR); - } - - function _setMintPaused(CToken cToken, bool state) public returns (bool) { - require(markets[address(cToken)].isListed, "cannot pause a market that is not listed"); - require(msg.sender == pauseGuardian || msg.sender == admin, "only pause guardian and admin can pause"); - require(msg.sender == admin || state == true, "only admin can unpause"); - - mintGuardianPaused[address(cToken)] = state; - emit ActionPaused(cToken, "Mint", state); - return state; - } - - function _setBorrowPaused(CToken cToken, bool state) public returns (bool) { - require(markets[address(cToken)].isListed, "cannot pause a market that is not listed"); - require(msg.sender == pauseGuardian || msg.sender == admin, "only pause guardian and admin can pause"); - require(msg.sender == admin || state == true, "only admin can unpause"); - - borrowGuardianPaused[address(cToken)] = state; - emit ActionPaused(cToken, "Borrow", state); - return state; - } - - function _setTransferPaused(bool state) public returns (bool) { - require(msg.sender == pauseGuardian || msg.sender == admin, "only pause guardian and admin can pause"); - require(msg.sender == admin || state == true, "only admin can unpause"); - - transferGuardianPaused = state; - emit ActionPaused("Transfer", state); - return state; - } - - function _setSeizePaused(bool state) public returns (bool) { - require(msg.sender == pauseGuardian || msg.sender == admin, "only pause guardian and admin can pause"); - require(msg.sender == admin || state == true, "only admin can unpause"); - - seizeGuardianPaused = state; - emit ActionPaused("Seize", state); - return state; - } - - function _become(Unitroller unitroller) public { - require(msg.sender == unitroller.admin(), "only unitroller admin can change brains"); - require(unitroller._acceptImplementation() == 0, "change not authorized"); - } - - /** - * @notice Checks caller is admin, or this contract is becoming the new implementation - */ - function adminOrInitializing() internal view returns (bool) { - return msg.sender == admin || msg.sender == comptrollerImplementation; - } - - /*** Comp Distribution ***/ - - /** - * @notice Recalculate and update COMP speeds for all COMP markets - */ - function refreshCompSpeeds() public { - require(msg.sender == tx.origin, "only externally owned accounts may refresh speeds"); - refreshCompSpeedsInternal(); - } - - function refreshCompSpeedsInternal() internal { - CToken[] memory allMarkets_ = allMarkets; - - for (uint i = 0; i < allMarkets_.length; i++) { - CToken cToken = allMarkets_[i]; - Exp memory borrowIndex = Exp({mantissa: cToken.borrowIndex()}); - updateCompSupplyIndex(address(cToken)); - updateCompBorrowIndex(address(cToken), borrowIndex); - } - - Exp memory totalUtility = Exp({mantissa: 0}); - Exp[] memory utilities = new Exp[](allMarkets_.length); - for (uint i = 0; i < allMarkets_.length; i++) { - CToken cToken = allMarkets_[i]; - if (markets[address(cToken)].isComped) { - Exp memory assetPrice = Exp({mantissa: oracle.getUnderlyingPrice(cToken)}); - Exp memory utility = mul_(assetPrice, cToken.totalBorrows()); - utilities[i] = utility; - totalUtility = add_(totalUtility, utility); - } - } - - for (uint i = 0; i < allMarkets_.length; i++) { - CToken cToken = allMarkets[i]; - uint newSpeed = totalUtility.mantissa > 0 ? mul_(compRate, div_(utilities[i], totalUtility)) : 0; - compSpeeds[address(cToken)] = newSpeed; - emit CompSpeedUpdated(cToken, newSpeed); - } - } - - /** - * @notice Accrue COMP to the market by updating the supply index - * @param cToken The market whose supply index to update - */ - function updateCompSupplyIndex(address cToken) internal { - CompMarketState storage supplyState = compSupplyState[cToken]; - uint supplySpeed = compSpeeds[cToken]; - uint blockNumber = getBlockNumber(); - uint deltaBlocks = sub_(blockNumber, uint(supplyState.block)); - if (deltaBlocks > 0 && supplySpeed > 0) { - uint supplyTokens = CToken(cToken).totalSupply(); - uint compAccrued = mul_(deltaBlocks, supplySpeed); - Double memory ratio = supplyTokens > 0 ? fraction(compAccrued, supplyTokens) : Double({mantissa: 0}); - Double memory index = add_(Double({mantissa: supplyState.index}), ratio); - compSupplyState[cToken] = CompMarketState({ - index: safe224(index.mantissa, "new index exceeds 224 bits"), - block: safe32(blockNumber, "block number exceeds 32 bits") - }); - } else if (deltaBlocks > 0) { - supplyState.block = safe32(blockNumber, "block number exceeds 32 bits"); - } - } - - /** - * @notice Accrue COMP to the market by updating the borrow index - * @param cToken The market whose borrow index to update - */ - function updateCompBorrowIndex(address cToken, Exp memory marketBorrowIndex) internal { - CompMarketState storage borrowState = compBorrowState[cToken]; - uint borrowSpeed = compSpeeds[cToken]; - uint blockNumber = getBlockNumber(); - uint deltaBlocks = sub_(blockNumber, uint(borrowState.block)); - if (deltaBlocks > 0 && borrowSpeed > 0) { - uint borrowAmount = div_(CToken(cToken).totalBorrows(), marketBorrowIndex); - uint compAccrued = mul_(deltaBlocks, borrowSpeed); - Double memory ratio = borrowAmount > 0 ? fraction(compAccrued, borrowAmount) : Double({mantissa: 0}); - Double memory index = add_(Double({mantissa: borrowState.index}), ratio); - compBorrowState[cToken] = CompMarketState({ - index: safe224(index.mantissa, "new index exceeds 224 bits"), - block: safe32(blockNumber, "block number exceeds 32 bits") - }); - } else if (deltaBlocks > 0) { - borrowState.block = safe32(blockNumber, "block number exceeds 32 bits"); - } - } - - /** - * @notice Calculate COMP accrued by a supplier and possibly transfer it to them - * @param cToken The market in which the supplier is interacting - * @param supplier The address of the supplier to distribute COMP to - */ - function distributeSupplierComp(address cToken, address supplier, bool distributeAll) internal { - CompMarketState storage supplyState = compSupplyState[cToken]; - Double memory supplyIndex = Double({mantissa: supplyState.index}); - Double memory supplierIndex = Double({mantissa: compSupplierIndex[cToken][supplier]}); - compSupplierIndex[cToken][supplier] = supplyIndex.mantissa; - - if (supplierIndex.mantissa == 0 && supplyIndex.mantissa > 0) { - supplierIndex.mantissa = compInitialIndex; - } - - Double memory deltaIndex = sub_(supplyIndex, supplierIndex); - uint supplierTokens = CToken(cToken).balanceOf(supplier); - uint supplierDelta = mul_(supplierTokens, deltaIndex); - uint supplierAccrued = add_(compAccrued[supplier], supplierDelta); - compAccrued[supplier] = transferComp(supplier, supplierAccrued, distributeAll ? 0 : compClaimThreshold); - emit DistributedSupplierComp(CToken(cToken), supplier, supplierDelta, supplyIndex.mantissa); - } - - /** - * @notice Calculate COMP accrued by a borrower and possibly transfer it to them - * @dev Borrowers will not begin to accrue until after the first interaction with the protocol. - * @param cToken The market in which the borrower is interacting - * @param borrower The address of the borrower to distribute COMP to - */ - function distributeBorrowerComp(address cToken, address borrower, Exp memory marketBorrowIndex, bool distributeAll) internal { - CompMarketState storage borrowState = compBorrowState[cToken]; - Double memory borrowIndex = Double({mantissa: borrowState.index}); - Double memory borrowerIndex = Double({mantissa: compBorrowerIndex[cToken][borrower]}); - compBorrowerIndex[cToken][borrower] = borrowIndex.mantissa; - - if (borrowerIndex.mantissa > 0) { - Double memory deltaIndex = sub_(borrowIndex, borrowerIndex); - uint borrowerAmount = div_(CToken(cToken).borrowBalanceStored(borrower), marketBorrowIndex); - uint borrowerDelta = mul_(borrowerAmount, deltaIndex); - uint borrowerAccrued = add_(compAccrued[borrower], borrowerDelta); - compAccrued[borrower] = transferComp(borrower, borrowerAccrued, distributeAll ? 0 : compClaimThreshold); - emit DistributedBorrowerComp(CToken(cToken), borrower, borrowerDelta, borrowIndex.mantissa); - } - } - - /** - * @notice Transfer COMP to the user, if they are above the threshold - * @dev Note: If there is not enough COMP, we do not perform the transfer all. - * @param user The address of the user to transfer COMP to - * @param userAccrued The amount of COMP to (possibly) transfer - * @return The amount of COMP which was NOT transferred to the user - */ - function transferComp(address user, uint userAccrued, uint threshold) internal returns (uint) { - if (userAccrued >= threshold && userAccrued > 0) { - Comp comp = Comp(getCompAddress()); - uint compRemaining = comp.balanceOf(address(this)); - if (userAccrued <= compRemaining) { - comp.transfer(user, userAccrued); - return 0; - } - } - return userAccrued; - } - - /** - * @notice Claim all the comp accrued by holder in all markets - * @param holder The address to claim COMP for - */ - function claimComp(address holder) public { - return claimComp(holder, allMarkets); - } - - /** - * @notice Claim all the comp accrued by holder in the specified markets - * @param holder The address to claim COMP for - * @param cTokens The list of markets to claim COMP in - */ - function claimComp(address holder, CToken[] memory cTokens) public { - address[] memory holders = new address[](1); - holders[0] = holder; - claimComp(holders, cTokens, true, true); - } - - /** - * @notice Claim all comp accrued by the holders - * @param holders The addresses to claim COMP for - * @param cTokens The list of markets to claim COMP in - * @param borrowers Whether or not to claim COMP earned by borrowing - * @param suppliers Whether or not to claim COMP earned by supplying - */ - function claimComp(address[] memory holders, CToken[] memory cTokens, bool borrowers, bool suppliers) public { - for (uint i = 0; i < cTokens.length; i++) { - CToken cToken = cTokens[i]; - require(markets[address(cToken)].isListed, "market must be listed"); - if (borrowers == true) { - Exp memory borrowIndex = Exp({mantissa: cToken.borrowIndex()}); - updateCompBorrowIndex(address(cToken), borrowIndex); - for (uint j = 0; j < holders.length; j++) { - distributeBorrowerComp(address(cToken), holders[j], borrowIndex, true); - } - } - if (suppliers == true) { - updateCompSupplyIndex(address(cToken)); - for (uint j = 0; j < holders.length; j++) { - distributeSupplierComp(address(cToken), holders[j], true); - } - } - } - } - - /*** Comp Distribution Admin ***/ - - /** - * @notice Set the amount of COMP distributed per block - * @param compRate_ The amount of COMP wei per block to distribute - */ - function _setCompRate(uint compRate_) public { - require(adminOrInitializing(), "only admin can change comp rate"); - - uint oldRate = compRate; - compRate = compRate_; - emit NewCompRate(oldRate, compRate_); - - refreshCompSpeedsInternal(); - } - - /** - * @notice Add markets to compMarkets, allowing them to earn COMP in the flywheel - * @param cTokens The addresses of the markets to add - */ - function _addCompMarkets(address[] memory cTokens) public { - require(adminOrInitializing(), "only admin can add comp market"); - - for (uint i = 0; i < cTokens.length; i++) { - _addCompMarketInternal(cTokens[i]); - } - - refreshCompSpeedsInternal(); - } - - function _addCompMarketInternal(address cToken) internal { - Market storage market = markets[cToken]; - require(market.isListed == true, "comp market is not listed"); - require(market.isComped == false, "comp market already added"); - - market.isComped = true; - emit MarketComped(CToken(cToken), true); - - if (compSupplyState[cToken].index == 0 && compSupplyState[cToken].block == 0) { - compSupplyState[cToken] = CompMarketState({ - index: compInitialIndex, - block: safe32(getBlockNumber(), "block number exceeds 32 bits") - }); - } - - if (compBorrowState[cToken].index == 0 && compBorrowState[cToken].block == 0) { - compBorrowState[cToken] = CompMarketState({ - index: compInitialIndex, - block: safe32(getBlockNumber(), "block number exceeds 32 bits") - }); - } - } - - /** - * @notice Remove a market from compMarkets, preventing it from earning COMP in the flywheel - * @param cToken The address of the market to drop - */ - function _dropCompMarket(address cToken) public { - require(msg.sender == admin, "only admin can drop comp market"); - - Market storage market = markets[cToken]; - require(market.isComped == true, "market is not a comp market"); - - market.isComped = false; - emit MarketComped(CToken(cToken), false); - - refreshCompSpeedsInternal(); - } - - /** - * @notice Return all of the markets - * @dev The automatic getter may be used to access an individual market. - * @return The list of market addresses - */ - function getAllMarkets() public view returns (CToken[] memory) { - return allMarkets; - } - - function getBlockNumber() public view returns (uint) { - return block.number; - } - - /** - * @notice Return the address of the COMP token - * @return The address of COMP - */ - function getCompAddress() public view returns (address) { - return 0xc00e94Cb662C3520282E6f5717214004A7f26888; - } -} diff --git a/contracts/ComptrollerG6.sol b/contracts/ComptrollerG6.sol deleted file mode 100644 index 763017f60..000000000 --- a/contracts/ComptrollerG6.sol +++ /dev/null @@ -1,1414 +0,0 @@ -pragma solidity ^0.5.16; - -import "./CToken.sol"; -import "./ErrorReporter.sol"; -import "./PriceOracle.sol"; -import "./ComptrollerInterface.sol"; -import "./ComptrollerStorage.sol"; -import "./Unitroller.sol"; -import "./Governance/Comp.sol"; - -/** - * @title Compound's Comptroller Contract - * @author Compound - */ -contract ComptrollerG6 is ComptrollerV5Storage, ComptrollerInterface, ComptrollerErrorReporter, ExponentialNoError { - /// @notice Emitted when an admin supports a market - event MarketListed(CToken cToken); - - /// @notice Emitted when an account enters a market - event MarketEntered(CToken cToken, address account); - - /// @notice Emitted when an account exits a market - event MarketExited(CToken cToken, address account); - - /// @notice Emitted when close factor is changed by admin - event NewCloseFactor(uint oldCloseFactorMantissa, uint newCloseFactorMantissa); - - /// @notice Emitted when a collateral factor is changed by admin - event NewCollateralFactor(CToken cToken, uint oldCollateralFactorMantissa, uint newCollateralFactorMantissa); - - /// @notice Emitted when liquidation incentive is changed by admin - event NewLiquidationIncentive(uint oldLiquidationIncentiveMantissa, uint newLiquidationIncentiveMantissa); - - /// @notice Emitted when price oracle is changed - event NewPriceOracle(PriceOracle oldPriceOracle, PriceOracle newPriceOracle); - - /// @notice Emitted when pause guardian is changed - event NewPauseGuardian(address oldPauseGuardian, address newPauseGuardian); - - /// @notice Emitted when an action is paused globally - event ActionPaused(string action, bool pauseState); - - /// @notice Emitted when an action is paused on a market - event ActionPaused(CToken cToken, string action, bool pauseState); - - /// @notice Emitted when market comped status is changed - event MarketComped(CToken cToken, bool isComped); - - /// @notice Emitted when COMP rate is changed - event NewCompRate(uint oldCompRate, uint newCompRate); - - /// @notice Emitted when a new COMP speed is calculated for a market - event CompSpeedUpdated(CToken indexed cToken, uint newSpeed); - - /// @notice Emitted when a new COMP speed is set for a contributor - event ContributorCompSpeedUpdated(address indexed contributor, uint newSpeed); - - /// @notice Emitted when COMP is distributed to a supplier - event DistributedSupplierComp(CToken indexed cToken, address indexed supplier, uint compDelta, uint compSupplyIndex); - - /// @notice Emitted when COMP is distributed to a borrower - event DistributedBorrowerComp(CToken indexed cToken, address indexed borrower, uint compDelta, uint compBorrowIndex); - - /// @notice Emitted when borrow cap for a cToken is changed - event NewBorrowCap(CToken indexed cToken, uint newBorrowCap); - - /// @notice Emitted when borrow cap guardian is changed - event NewBorrowCapGuardian(address oldBorrowCapGuardian, address newBorrowCapGuardian); - - /// @notice Emitted when COMP is granted by admin - event CompGranted(address recipient, uint amount); - - /// @notice The threshold above which the flywheel transfers COMP, in wei - uint public constant compClaimThreshold = 0.001e18; - - /// @notice The initial COMP index for a market - uint224 public constant compInitialIndex = 1e36; - - // closeFactorMantissa must be strictly greater than this value - uint internal constant closeFactorMinMantissa = 0.05e18; // 0.05 - - // closeFactorMantissa must not exceed this value - uint internal constant closeFactorMaxMantissa = 0.9e18; // 0.9 - - // No collateralFactorMantissa may exceed this value - uint internal constant collateralFactorMaxMantissa = 0.9e18; // 0.9 - - constructor() public { - admin = msg.sender; - } - - /*** Assets You Are In ***/ - - /** - * @notice Returns the assets an account has entered - * @param account The address of the account to pull assets for - * @return A dynamic list with the assets the account has entered - */ - function getAssetsIn(address account) external view returns (CToken[] memory) { - CToken[] memory assetsIn = accountAssets[account]; - - return assetsIn; - } - - /** - * @notice Returns whether the given account is entered in the given asset - * @param account The address of the account to check - * @param cToken The cToken to check - * @return True if the account is in the asset, otherwise false. - */ - function checkMembership(address account, CToken cToken) external view returns (bool) { - return markets[address(cToken)].accountMembership[account]; - } - - /** - * @notice Add assets to be included in account liquidity calculation - * @param cTokens The list of addresses of the cToken markets to be enabled - * @return Success indicator for whether each corresponding market was entered - */ - function enterMarkets(address[] memory cTokens) public returns (uint[] memory) { - uint len = cTokens.length; - - uint[] memory results = new uint[](len); - for (uint i = 0; i < len; i++) { - CToken cToken = CToken(cTokens[i]); - - results[i] = uint(addToMarketInternal(cToken, msg.sender)); - } - - return results; - } - - /** - * @notice Add the market to the borrower's "assets in" for liquidity calculations - * @param cToken The market to enter - * @param borrower The address of the account to modify - * @return Success indicator for whether the market was entered - */ - function addToMarketInternal(CToken cToken, address borrower) internal returns (Error) { - Market storage marketToJoin = markets[address(cToken)]; - - if (!marketToJoin.isListed) { - // market is not listed, cannot join - return Error.MARKET_NOT_LISTED; - } - - if (marketToJoin.accountMembership[borrower] == true) { - // already joined - return Error.NO_ERROR; - } - - // survived the gauntlet, add to list - // NOTE: we store these somewhat redundantly as a significant optimization - // this avoids having to iterate through the list for the most common use cases - // that is, only when we need to perform liquidity checks - // and not whenever we want to check if an account is in a particular market - marketToJoin.accountMembership[borrower] = true; - accountAssets[borrower].push(cToken); - - emit MarketEntered(cToken, borrower); - - return Error.NO_ERROR; - } - - /** - * @notice Removes asset from sender's account liquidity calculation - * @dev Sender must not have an outstanding borrow balance in the asset, - * or be providing necessary collateral for an outstanding borrow. - * @param cTokenAddress The address of the asset to be removed - * @return Whether or not the account successfully exited the market - */ - function exitMarket(address cTokenAddress) external returns (uint) { - CToken cToken = CToken(cTokenAddress); - /* Get sender tokensHeld and amountOwed underlying from the cToken */ - (uint oErr, uint tokensHeld, uint amountOwed, ) = cToken.getAccountSnapshot(msg.sender); - require(oErr == 0, "exitMarket: getAccountSnapshot failed"); // semi-opaque error code - - /* Fail if the sender has a borrow balance */ - if (amountOwed != 0) { - return fail(Error.NONZERO_BORROW_BALANCE, FailureInfo.EXIT_MARKET_BALANCE_OWED); - } - - /* Fail if the sender is not permitted to redeem all of their tokens */ - uint allowed = redeemAllowedInternal(cTokenAddress, msg.sender, tokensHeld); - if (allowed != 0) { - return failOpaque(Error.REJECTION, FailureInfo.EXIT_MARKET_REJECTION, allowed); - } - - Market storage marketToExit = markets[address(cToken)]; - - /* Return true if the sender is not already ‘in’ the market */ - if (!marketToExit.accountMembership[msg.sender]) { - return uint(Error.NO_ERROR); - } - - /* Set cToken account membership to false */ - delete marketToExit.accountMembership[msg.sender]; - - /* Delete cToken from the account’s list of assets */ - // load into memory for faster iteration - CToken[] memory userAssetList = accountAssets[msg.sender]; - uint len = userAssetList.length; - uint assetIndex = len; - for (uint i = 0; i < len; i++) { - if (userAssetList[i] == cToken) { - assetIndex = i; - break; - } - } - - // We *must* have found the asset in the list or our redundant data structure is broken - assert(assetIndex < len); - - // copy last item in list to location of item to be removed, reduce length by 1 - CToken[] storage storedList = accountAssets[msg.sender]; - storedList[assetIndex] = storedList[storedList.length - 1]; - storedList.length--; - - emit MarketExited(cToken, msg.sender); - - return uint(Error.NO_ERROR); - } - - /*** Policy Hooks ***/ - - /** - * @notice Checks if the account should be allowed to mint tokens in the given market - * @param cToken The market to verify the mint against - * @param minter The account which would get the minted tokens - * @param mintAmount The amount of underlying being supplied to the market in exchange for tokens - * @return 0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol) - */ - function mintAllowed(address cToken, address minter, uint mintAmount) external returns (uint) { - // Pausing is a very serious situation - we revert to sound the alarms - require(!mintGuardianPaused[cToken], "mint is paused"); - - // Shh - currently unused - minter; - mintAmount; - - if (!markets[cToken].isListed) { - return uint(Error.MARKET_NOT_LISTED); - } - - // Keep the flywheel moving - updateCompSupplyIndex(cToken); - distributeSupplierComp(cToken, minter, false); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Validates mint and reverts on rejection. May emit logs. - * @param cToken Asset being minted - * @param minter The address minting the tokens - * @param actualMintAmount The amount of the underlying asset being minted - * @param mintTokens The number of tokens being minted - */ - function mintVerify(address cToken, address minter, uint actualMintAmount, uint mintTokens) external { - // Shh - currently unused - cToken; - minter; - actualMintAmount; - mintTokens; - - // Shh - we don't ever want this hook to be marked pure - if (false) { - maxAssets = maxAssets; - } - } - - /** - * @notice Checks if the account should be allowed to redeem tokens in the given market - * @param cToken The market to verify the redeem against - * @param redeemer The account which would redeem the tokens - * @param redeemTokens The number of cTokens to exchange for the underlying asset in the market - * @return 0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol) - */ - function redeemAllowed(address cToken, address redeemer, uint redeemTokens) external returns (uint) { - uint allowed = redeemAllowedInternal(cToken, redeemer, redeemTokens); - if (allowed != uint(Error.NO_ERROR)) { - return allowed; - } - - // Keep the flywheel moving - updateCompSupplyIndex(cToken); - distributeSupplierComp(cToken, redeemer, false); - - return uint(Error.NO_ERROR); - } - - function redeemAllowedInternal(address cToken, address redeemer, uint redeemTokens) internal view returns (uint) { - if (!markets[cToken].isListed) { - return uint(Error.MARKET_NOT_LISTED); - } - - /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */ - if (!markets[cToken].accountMembership[redeemer]) { - return uint(Error.NO_ERROR); - } - - /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */ - (Error err, , uint shortfall) = getHypotheticalAccountLiquidityInternal(redeemer, CToken(cToken), redeemTokens, 0); - if (err != Error.NO_ERROR) { - return uint(err); - } - if (shortfall > 0) { - return uint(Error.INSUFFICIENT_LIQUIDITY); - } - - return uint(Error.NO_ERROR); - } - - /** - * @notice Validates redeem and reverts on rejection. May emit logs. - * @param cToken Asset being redeemed - * @param redeemer The address redeeming the tokens - * @param redeemAmount The amount of the underlying asset being redeemed - * @param redeemTokens The number of tokens being redeemed - */ - function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) external { - // Shh - currently unused - cToken; - redeemer; - - // Require tokens is zero or amount is also zero - if (redeemTokens == 0 && redeemAmount > 0) { - revert("redeemTokens zero"); - } - } - - /** - * @notice Checks if the account should be allowed to borrow the underlying asset of the given market - * @param cToken The market to verify the borrow against - * @param borrower The account which would borrow the asset - * @param borrowAmount The amount of underlying the account would borrow - * @return 0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol) - */ - function borrowAllowed(address cToken, address borrower, uint borrowAmount) external returns (uint) { - // Pausing is a very serious situation - we revert to sound the alarms - require(!borrowGuardianPaused[cToken], "borrow is paused"); - - if (!markets[cToken].isListed) { - return uint(Error.MARKET_NOT_LISTED); - } - - if (!markets[cToken].accountMembership[borrower]) { - // only cTokens may call borrowAllowed if borrower not in market - require(msg.sender == cToken, "sender must be cToken"); - - // attempt to add borrower to the market - Error err = addToMarketInternal(CToken(msg.sender), borrower); - if (err != Error.NO_ERROR) { - return uint(err); - } - - // it should be impossible to break the important invariant - assert(markets[cToken].accountMembership[borrower]); - } - - if (oracle.getUnderlyingPrice(CToken(cToken)) == 0) { - return uint(Error.PRICE_ERROR); - } - - - uint borrowCap = borrowCaps[cToken]; - // Borrow cap of 0 corresponds to unlimited borrowing - if (borrowCap != 0) { - uint totalBorrows = CToken(cToken).totalBorrows(); - uint nextTotalBorrows = add_(totalBorrows, borrowAmount); - require(nextTotalBorrows < borrowCap, "market borrow cap reached"); - } - - (Error err, , uint shortfall) = getHypotheticalAccountLiquidityInternal(borrower, CToken(cToken), 0, borrowAmount); - if (err != Error.NO_ERROR) { - return uint(err); - } - if (shortfall > 0) { - return uint(Error.INSUFFICIENT_LIQUIDITY); - } - - // Keep the flywheel moving - Exp memory borrowIndex = Exp({mantissa: CToken(cToken).borrowIndex()}); - updateCompBorrowIndex(cToken, borrowIndex); - distributeBorrowerComp(cToken, borrower, borrowIndex, false); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Validates borrow and reverts on rejection. May emit logs. - * @param cToken Asset whose underlying is being borrowed - * @param borrower The address borrowing the underlying - * @param borrowAmount The amount of the underlying asset requested to borrow - */ - function borrowVerify(address cToken, address borrower, uint borrowAmount) external { - // Shh - currently unused - cToken; - borrower; - borrowAmount; - - // Shh - we don't ever want this hook to be marked pure - if (false) { - maxAssets = maxAssets; - } - } - - /** - * @notice Checks if the account should be allowed to repay a borrow in the given market - * @param cToken The market to verify the repay against - * @param payer The account which would repay the asset - * @param borrower The account which would borrowed the asset - * @param repayAmount The amount of the underlying asset the account would repay - * @return 0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol) - */ - function repayBorrowAllowed( - address cToken, - address payer, - address borrower, - uint repayAmount) external returns (uint) { - // Shh - currently unused - payer; - borrower; - repayAmount; - - if (!markets[cToken].isListed) { - return uint(Error.MARKET_NOT_LISTED); - } - - // Keep the flywheel moving - Exp memory borrowIndex = Exp({mantissa: CToken(cToken).borrowIndex()}); - updateCompBorrowIndex(cToken, borrowIndex); - distributeBorrowerComp(cToken, borrower, borrowIndex, false); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Validates repayBorrow and reverts on rejection. May emit logs. - * @param cToken Asset being repaid - * @param payer The address repaying the borrow - * @param borrower The address of the borrower - * @param actualRepayAmount The amount of underlying being repaid - */ - function repayBorrowVerify( - address cToken, - address payer, - address borrower, - uint actualRepayAmount, - uint borrowerIndex) external { - // Shh - currently unused - cToken; - payer; - borrower; - actualRepayAmount; - borrowerIndex; - - // Shh - we don't ever want this hook to be marked pure - if (false) { - maxAssets = maxAssets; - } - } - - /** - * @notice Checks if the liquidation should be allowed to occur - * @param cTokenBorrowed Asset which was borrowed by the borrower - * @param cTokenCollateral Asset which was used as collateral and will be seized - * @param liquidator The address repaying the borrow and seizing the collateral - * @param borrower The address of the borrower - * @param repayAmount The amount of underlying being repaid - */ - function liquidateBorrowAllowed( - address cTokenBorrowed, - address cTokenCollateral, - address liquidator, - address borrower, - uint repayAmount) external returns (uint) { - // Shh - currently unused - liquidator; - - if (!markets[cTokenBorrowed].isListed || !markets[cTokenCollateral].isListed) { - return uint(Error.MARKET_NOT_LISTED); - } - - /* The borrower must have shortfall in order to be liquidatable */ - (Error err, , uint shortfall) = getAccountLiquidityInternal(borrower); - if (err != Error.NO_ERROR) { - return uint(err); - } - if (shortfall == 0) { - return uint(Error.INSUFFICIENT_SHORTFALL); - } - - /* The liquidator may not repay more than what is allowed by the closeFactor */ - uint borrowBalance = CToken(cTokenBorrowed).borrowBalanceStored(borrower); - uint maxClose = mul_ScalarTruncate(Exp({mantissa: closeFactorMantissa}), borrowBalance); - if (repayAmount > maxClose) { - return uint(Error.TOO_MUCH_REPAY); - } - - return uint(Error.NO_ERROR); - } - - /** - * @notice Validates liquidateBorrow and reverts on rejection. May emit logs. - * @param cTokenBorrowed Asset which was borrowed by the borrower - * @param cTokenCollateral Asset which was used as collateral and will be seized - * @param liquidator The address repaying the borrow and seizing the collateral - * @param borrower The address of the borrower - * @param actualRepayAmount The amount of underlying being repaid - */ - function liquidateBorrowVerify( - address cTokenBorrowed, - address cTokenCollateral, - address liquidator, - address borrower, - uint actualRepayAmount, - uint seizeTokens) external { - // Shh - currently unused - cTokenBorrowed; - cTokenCollateral; - liquidator; - borrower; - actualRepayAmount; - seizeTokens; - - // Shh - we don't ever want this hook to be marked pure - if (false) { - maxAssets = maxAssets; - } - } - - /** - * @notice Checks if the seizing of assets should be allowed to occur - * @param cTokenCollateral Asset which was used as collateral and will be seized - * @param cTokenBorrowed Asset which was borrowed by the borrower - * @param liquidator The address repaying the borrow and seizing the collateral - * @param borrower The address of the borrower - * @param seizeTokens The number of collateral tokens to seize - */ - function seizeAllowed( - address cTokenCollateral, - address cTokenBorrowed, - address liquidator, - address borrower, - uint seizeTokens) external returns (uint) { - // Pausing is a very serious situation - we revert to sound the alarms - require(!seizeGuardianPaused, "seize is paused"); - - // Shh - currently unused - seizeTokens; - - if (!markets[cTokenCollateral].isListed || !markets[cTokenBorrowed].isListed) { - return uint(Error.MARKET_NOT_LISTED); - } - - if (CToken(cTokenCollateral).comptroller() != CToken(cTokenBorrowed).comptroller()) { - return uint(Error.COMPTROLLER_MISMATCH); - } - - // Keep the flywheel moving - updateCompSupplyIndex(cTokenCollateral); - distributeSupplierComp(cTokenCollateral, borrower, false); - distributeSupplierComp(cTokenCollateral, liquidator, false); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Validates seize and reverts on rejection. May emit logs. - * @param cTokenCollateral Asset which was used as collateral and will be seized - * @param cTokenBorrowed Asset which was borrowed by the borrower - * @param liquidator The address repaying the borrow and seizing the collateral - * @param borrower The address of the borrower - * @param seizeTokens The number of collateral tokens to seize - */ - function seizeVerify( - address cTokenCollateral, - address cTokenBorrowed, - address liquidator, - address borrower, - uint seizeTokens) external { - // Shh - currently unused - cTokenCollateral; - cTokenBorrowed; - liquidator; - borrower; - seizeTokens; - - // Shh - we don't ever want this hook to be marked pure - if (false) { - maxAssets = maxAssets; - } - } - - /** - * @notice Checks if the account should be allowed to transfer tokens in the given market - * @param cToken The market to verify the transfer against - * @param src The account which sources the tokens - * @param dst The account which receives the tokens - * @param transferTokens The number of cTokens to transfer - * @return 0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol) - */ - function transferAllowed(address cToken, address src, address dst, uint transferTokens) external returns (uint) { - // Pausing is a very serious situation - we revert to sound the alarms - require(!transferGuardianPaused, "transfer is paused"); - - // Currently the only consideration is whether or not - // the src is allowed to redeem this many tokens - uint allowed = redeemAllowedInternal(cToken, src, transferTokens); - if (allowed != uint(Error.NO_ERROR)) { - return allowed; - } - - // Keep the flywheel moving - updateCompSupplyIndex(cToken); - distributeSupplierComp(cToken, src, false); - distributeSupplierComp(cToken, dst, false); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Validates transfer and reverts on rejection. May emit logs. - * @param cToken Asset being transferred - * @param src The account which sources the tokens - * @param dst The account which receives the tokens - * @param transferTokens The number of cTokens to transfer - */ - function transferVerify(address cToken, address src, address dst, uint transferTokens) external { - // Shh - currently unused - cToken; - src; - dst; - transferTokens; - - // Shh - we don't ever want this hook to be marked pure - if (false) { - maxAssets = maxAssets; - } - } - - /*** Liquidity/Liquidation Calculations ***/ - - /** - * @dev Local vars for avoiding stack-depth limits in calculating account liquidity. - * Note that `cTokenBalance` is the number of cTokens the account owns in the market, - * whereas `borrowBalance` is the amount of underlying that the account has borrowed. - */ - struct AccountLiquidityLocalVars { - uint sumCollateral; - uint sumBorrowPlusEffects; - uint cTokenBalance; - uint borrowBalance; - uint exchangeRateMantissa; - uint oraclePriceMantissa; - Exp collateralFactor; - Exp exchangeRate; - Exp oraclePrice; - Exp tokensToDenom; - } - - /** - * @notice Determine the current account liquidity wrt collateral requirements - * @return (possible error code (semi-opaque), - account liquidity in excess of collateral requirements, - * account shortfall below collateral requirements) - */ - function getAccountLiquidity(address account) public view returns (uint, uint, uint) { - (Error err, uint liquidity, uint shortfall) = getHypotheticalAccountLiquidityInternal(account, CToken(0), 0, 0); - - return (uint(err), liquidity, shortfall); - } - - /** - * @notice Determine the current account liquidity wrt collateral requirements - * @return (possible error code, - account liquidity in excess of collateral requirements, - * account shortfall below collateral requirements) - */ - function getAccountLiquidityInternal(address account) internal view returns (Error, uint, uint) { - return getHypotheticalAccountLiquidityInternal(account, CToken(0), 0, 0); - } - - /** - * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed - * @param cTokenModify The market to hypothetically redeem/borrow in - * @param account The account to determine liquidity for - * @param redeemTokens The number of tokens to hypothetically redeem - * @param borrowAmount The amount of underlying to hypothetically borrow - * @return (possible error code (semi-opaque), - hypothetical account liquidity in excess of collateral requirements, - * hypothetical account shortfall below collateral requirements) - */ - function getHypotheticalAccountLiquidity( - address account, - address cTokenModify, - uint redeemTokens, - uint borrowAmount) public view returns (uint, uint, uint) { - (Error err, uint liquidity, uint shortfall) = getHypotheticalAccountLiquidityInternal(account, CToken(cTokenModify), redeemTokens, borrowAmount); - return (uint(err), liquidity, shortfall); - } - - /** - * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed - * @param cTokenModify The market to hypothetically redeem/borrow in - * @param account The account to determine liquidity for - * @param redeemTokens The number of tokens to hypothetically redeem - * @param borrowAmount The amount of underlying to hypothetically borrow - * @dev Note that we calculate the exchangeRateStored for each collateral cToken using stored data, - * without calculating accumulated interest. - * @return (possible error code, - hypothetical account liquidity in excess of collateral requirements, - * hypothetical account shortfall below collateral requirements) - */ - function getHypotheticalAccountLiquidityInternal( - address account, - CToken cTokenModify, - uint redeemTokens, - uint borrowAmount) internal view returns (Error, uint, uint) { - - AccountLiquidityLocalVars memory vars; // Holds all our calculation results - uint oErr; - - // For each asset the account is in - CToken[] memory assets = accountAssets[account]; - for (uint i = 0; i < assets.length; i++) { - CToken asset = assets[i]; - - // Read the balances and exchange rate from the cToken - (oErr, vars.cTokenBalance, vars.borrowBalance, vars.exchangeRateMantissa) = asset.getAccountSnapshot(account); - if (oErr != 0) { // semi-opaque error code, we assume NO_ERROR == 0 is invariant between upgrades - return (Error.SNAPSHOT_ERROR, 0, 0); - } - vars.collateralFactor = Exp({mantissa: markets[address(asset)].collateralFactorMantissa}); - vars.exchangeRate = Exp({mantissa: vars.exchangeRateMantissa}); - - // Get the normalized price of the asset - vars.oraclePriceMantissa = oracle.getUnderlyingPrice(asset); - if (vars.oraclePriceMantissa == 0) { - return (Error.PRICE_ERROR, 0, 0); - } - vars.oraclePrice = Exp({mantissa: vars.oraclePriceMantissa}); - - // Pre-compute a conversion factor from tokens -> ether (normalized price value) - vars.tokensToDenom = mul_(mul_(vars.collateralFactor, vars.exchangeRate), vars.oraclePrice); - - // sumCollateral += tokensToDenom * cTokenBalance - vars.sumCollateral = mul_ScalarTruncateAddUInt(vars.tokensToDenom, vars.cTokenBalance, vars.sumCollateral); - - // sumBorrowPlusEffects += oraclePrice * borrowBalance - vars.sumBorrowPlusEffects = mul_ScalarTruncateAddUInt(vars.oraclePrice, vars.borrowBalance, vars.sumBorrowPlusEffects); - - // Calculate effects of interacting with cTokenModify - if (asset == cTokenModify) { - // redeem effect - // sumBorrowPlusEffects += tokensToDenom * redeemTokens - vars.sumBorrowPlusEffects = mul_ScalarTruncateAddUInt(vars.tokensToDenom, redeemTokens, vars.sumBorrowPlusEffects); - - // borrow effect - // sumBorrowPlusEffects += oraclePrice * borrowAmount - vars.sumBorrowPlusEffects = mul_ScalarTruncateAddUInt(vars.oraclePrice, borrowAmount, vars.sumBorrowPlusEffects); - } - } - - // These are safe, as the underflow condition is checked first - if (vars.sumCollateral > vars.sumBorrowPlusEffects) { - return (Error.NO_ERROR, vars.sumCollateral - vars.sumBorrowPlusEffects, 0); - } else { - return (Error.NO_ERROR, 0, vars.sumBorrowPlusEffects - vars.sumCollateral); - } - } - - /** - * @notice Calculate number of tokens of collateral asset to seize given an underlying amount - * @dev Used in liquidation (called in cToken.liquidateBorrowFresh) - * @param cTokenBorrowed The address of the borrowed cToken - * @param cTokenCollateral The address of the collateral cToken - * @param actualRepayAmount The amount of cTokenBorrowed underlying to convert into cTokenCollateral tokens - * @return (errorCode, number of cTokenCollateral tokens to be seized in a liquidation) - */ - function liquidateCalculateSeizeTokens(address cTokenBorrowed, address cTokenCollateral, uint actualRepayAmount) external view returns (uint, uint) { - /* Read oracle prices for borrowed and collateral markets */ - uint priceBorrowedMantissa = oracle.getUnderlyingPrice(CToken(cTokenBorrowed)); - uint priceCollateralMantissa = oracle.getUnderlyingPrice(CToken(cTokenCollateral)); - if (priceBorrowedMantissa == 0 || priceCollateralMantissa == 0) { - return (uint(Error.PRICE_ERROR), 0); - } - - /* - * Get the exchange rate and calculate the number of collateral tokens to seize: - * seizeAmount = actualRepayAmount * liquidationIncentive * priceBorrowed / priceCollateral - * seizeTokens = seizeAmount / exchangeRate - * = actualRepayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate) - */ - uint exchangeRateMantissa = CToken(cTokenCollateral).exchangeRateStored(); // Note: reverts on error - uint seizeTokens; - Exp memory numerator; - Exp memory denominator; - Exp memory ratio; - - numerator = mul_(Exp({mantissa: liquidationIncentiveMantissa}), Exp({mantissa: priceBorrowedMantissa})); - denominator = mul_(Exp({mantissa: priceCollateralMantissa}), Exp({mantissa: exchangeRateMantissa})); - ratio = div_(numerator, denominator); - - seizeTokens = mul_ScalarTruncate(ratio, actualRepayAmount); - - return (uint(Error.NO_ERROR), seizeTokens); - } - - /*** Admin Functions ***/ - - /** - * @notice Sets a new price oracle for the comptroller - * @dev Admin function to set a new price oracle - * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) - */ - function _setPriceOracle(PriceOracle newOracle) public returns (uint) { - // Check caller is admin - if (msg.sender != admin) { - return fail(Error.UNAUTHORIZED, FailureInfo.SET_PRICE_ORACLE_OWNER_CHECK); - } - - // Track the old oracle for the comptroller - PriceOracle oldOracle = oracle; - - // Set comptroller's oracle to newOracle - oracle = newOracle; - - // Emit NewPriceOracle(oldOracle, newOracle) - emit NewPriceOracle(oldOracle, newOracle); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Sets the closeFactor used when liquidating borrows - * @dev Admin function to set closeFactor - * @param newCloseFactorMantissa New close factor, scaled by 1e18 - * @return uint 0=success, otherwise a failure - */ - function _setCloseFactor(uint newCloseFactorMantissa) external returns (uint) { - // Check caller is admin - require(msg.sender == admin, "only admin can set close factor"); - - uint oldCloseFactorMantissa = closeFactorMantissa; - closeFactorMantissa = newCloseFactorMantissa; - emit NewCloseFactor(oldCloseFactorMantissa, closeFactorMantissa); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Sets the collateralFactor for a market - * @dev Admin function to set per-market collateralFactor - * @param cToken The market to set the factor on - * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18 - * @return uint 0=success, otherwise a failure. (See ErrorReporter for details) - */ - function _setCollateralFactor(CToken cToken, uint newCollateralFactorMantissa) external returns (uint) { - // Check caller is admin - if (msg.sender != admin) { - return fail(Error.UNAUTHORIZED, FailureInfo.SET_COLLATERAL_FACTOR_OWNER_CHECK); - } - - // Verify market is listed - Market storage market = markets[address(cToken)]; - if (!market.isListed) { - return fail(Error.MARKET_NOT_LISTED, FailureInfo.SET_COLLATERAL_FACTOR_NO_EXISTS); - } - - Exp memory newCollateralFactorExp = Exp({mantissa: newCollateralFactorMantissa}); - - // Check collateral factor <= 0.9 - Exp memory highLimit = Exp({mantissa: collateralFactorMaxMantissa}); - if (lessThanExp(highLimit, newCollateralFactorExp)) { - return fail(Error.INVALID_COLLATERAL_FACTOR, FailureInfo.SET_COLLATERAL_FACTOR_VALIDATION); - } - - // If collateral factor != 0, fail if price == 0 - if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(cToken) == 0) { - return fail(Error.PRICE_ERROR, FailureInfo.SET_COLLATERAL_FACTOR_WITHOUT_PRICE); - } - - // Set market's collateral factor to new collateral factor, remember old value - uint oldCollateralFactorMantissa = market.collateralFactorMantissa; - market.collateralFactorMantissa = newCollateralFactorMantissa; - - // Emit event with asset, old collateral factor, and new collateral factor - emit NewCollateralFactor(cToken, oldCollateralFactorMantissa, newCollateralFactorMantissa); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Sets liquidationIncentive - * @dev Admin function to set liquidationIncentive - * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18 - * @return uint 0=success, otherwise a failure. (See ErrorReporter for details) - */ - function _setLiquidationIncentive(uint newLiquidationIncentiveMantissa) external returns (uint) { - // Check caller is admin - if (msg.sender != admin) { - return fail(Error.UNAUTHORIZED, FailureInfo.SET_LIQUIDATION_INCENTIVE_OWNER_CHECK); - } - - // Save current value for use in log - uint oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa; - - // Set liquidation incentive to new incentive - liquidationIncentiveMantissa = newLiquidationIncentiveMantissa; - - // Emit event with old incentive, new incentive - emit NewLiquidationIncentive(oldLiquidationIncentiveMantissa, newLiquidationIncentiveMantissa); - - return uint(Error.NO_ERROR); - } - - /** - * @notice Add the market to the markets mapping and set it as listed - * @dev Admin function to set isListed and add support for the market - * @param cToken The address of the market (token) to list - * @return uint 0=success, otherwise a failure. (See enum Error for details) - */ - function _supportMarket(CToken cToken) external returns (uint) { - if (msg.sender != admin) { - return fail(Error.UNAUTHORIZED, FailureInfo.SUPPORT_MARKET_OWNER_CHECK); - } - - if (markets[address(cToken)].isListed) { - return fail(Error.MARKET_ALREADY_LISTED, FailureInfo.SUPPORT_MARKET_EXISTS); - } - - cToken.isCToken(); // Sanity check to make sure its really a CToken - - markets[address(cToken)] = Market({isListed: true, isComped: false, collateralFactorMantissa: 0}); - - _addMarketInternal(address(cToken)); - - emit MarketListed(cToken); - - return uint(Error.NO_ERROR); - } - - function _addMarketInternal(address cToken) internal { - for (uint i = 0; i < allMarkets.length; i ++) { - require(allMarkets[i] != CToken(cToken), "market already added"); - } - allMarkets.push(CToken(cToken)); - } - - - /** - * @notice Set the given borrow caps for the given cToken markets. Borrowing that brings total borrows to or above borrow cap will revert. - * @dev Admin or borrowCapGuardian function to set the borrow caps. A borrow cap of 0 corresponds to unlimited borrowing. - * @param cTokens The addresses of the markets (tokens) to change the borrow caps for - * @param newBorrowCaps The new borrow cap values in underlying to be set. A value of 0 corresponds to unlimited borrowing. - */ - function _setMarketBorrowCaps(CToken[] calldata cTokens, uint[] calldata newBorrowCaps) external { - require(msg.sender == admin || msg.sender == borrowCapGuardian, "only admin or borrow cap guardian can set borrow caps"); - - uint numMarkets = cTokens.length; - uint numBorrowCaps = newBorrowCaps.length; - - require(numMarkets != 0 && numMarkets == numBorrowCaps, "invalid input"); - - for(uint i = 0; i < numMarkets; i++) { - borrowCaps[address(cTokens[i])] = newBorrowCaps[i]; - emit NewBorrowCap(cTokens[i], newBorrowCaps[i]); - } - } - - /** - * @notice Admin function to change the Borrow Cap Guardian - * @param newBorrowCapGuardian The address of the new Borrow Cap Guardian - */ - function _setBorrowCapGuardian(address newBorrowCapGuardian) external { - require(msg.sender == admin, "only admin can set borrow cap guardian"); - - // Save current value for inclusion in log - address oldBorrowCapGuardian = borrowCapGuardian; - - // Store borrowCapGuardian with value newBorrowCapGuardian - borrowCapGuardian = newBorrowCapGuardian; - - // Emit NewBorrowCapGuardian(OldBorrowCapGuardian, NewBorrowCapGuardian) - emit NewBorrowCapGuardian(oldBorrowCapGuardian, newBorrowCapGuardian); - } - - /** - * @notice Admin function to change the Pause Guardian - * @param newPauseGuardian The address of the new Pause Guardian - * @return uint 0=success, otherwise a failure. (See enum Error for details) - */ - function _setPauseGuardian(address newPauseGuardian) public returns (uint) { - if (msg.sender != admin) { - return fail(Error.UNAUTHORIZED, FailureInfo.SET_PAUSE_GUARDIAN_OWNER_CHECK); - } - - // Save current value for inclusion in log - address oldPauseGuardian = pauseGuardian; - - // Store pauseGuardian with value newPauseGuardian - pauseGuardian = newPauseGuardian; - - // Emit NewPauseGuardian(OldPauseGuardian, NewPauseGuardian) - emit NewPauseGuardian(oldPauseGuardian, pauseGuardian); - - return uint(Error.NO_ERROR); - } - - function _setMintPaused(CToken cToken, bool state) public returns (bool) { - require(markets[address(cToken)].isListed, "cannot pause a market that is not listed"); - require(msg.sender == pauseGuardian || msg.sender == admin, "only pause guardian and admin can pause"); - require(msg.sender == admin || state == true, "only admin can unpause"); - - mintGuardianPaused[address(cToken)] = state; - emit ActionPaused(cToken, "Mint", state); - return state; - } - - function _setBorrowPaused(CToken cToken, bool state) public returns (bool) { - require(markets[address(cToken)].isListed, "cannot pause a market that is not listed"); - require(msg.sender == pauseGuardian || msg.sender == admin, "only pause guardian and admin can pause"); - require(msg.sender == admin || state == true, "only admin can unpause"); - - borrowGuardianPaused[address(cToken)] = state; - emit ActionPaused(cToken, "Borrow", state); - return state; - } - - function _setTransferPaused(bool state) public returns (bool) { - require(msg.sender == pauseGuardian || msg.sender == admin, "only pause guardian and admin can pause"); - require(msg.sender == admin || state == true, "only admin can unpause"); - - transferGuardianPaused = state; - emit ActionPaused("Transfer", state); - return state; - } - - function _setSeizePaused(bool state) public returns (bool) { - require(msg.sender == pauseGuardian || msg.sender == admin, "only pause guardian and admin can pause"); - require(msg.sender == admin || state == true, "only admin can unpause"); - - seizeGuardianPaused = state; - emit ActionPaused("Seize", state); - return state; - } - - function _become(Unitroller unitroller) public { - require(msg.sender == unitroller.admin(), "only unitroller admin can change brains"); - require(unitroller._acceptImplementation() == 0, "change not authorized"); - } - - /** - * @notice Checks caller is admin, or this contract is becoming the new implementation - */ - function adminOrInitializing() internal view returns (bool) { - return msg.sender == admin || msg.sender == comptrollerImplementation; - } - - /*** Comp Distribution ***/ - - /** - * @notice Recalculate and update COMP speeds for all COMP markets - */ - function refreshCompSpeeds() public { - require(msg.sender == tx.origin, "only externally owned accounts may refresh speeds"); - refreshCompSpeedsInternal(); - } - - function refreshCompSpeedsInternal() internal { - CToken[] memory allMarkets_ = allMarkets; - - for (uint i = 0; i < allMarkets_.length; i++) { - CToken cToken = allMarkets_[i]; - Exp memory borrowIndex = Exp({mantissa: cToken.borrowIndex()}); - updateCompSupplyIndex(address(cToken)); - updateCompBorrowIndex(address(cToken), borrowIndex); - } - - Exp memory totalUtility = Exp({mantissa: 0}); - Exp[] memory utilities = new Exp[](allMarkets_.length); - for (uint i = 0; i < allMarkets_.length; i++) { - CToken cToken = allMarkets_[i]; - if (markets[address(cToken)].isComped) { - Exp memory assetPrice = Exp({mantissa: oracle.getUnderlyingPrice(cToken)}); - Exp memory utility = mul_(assetPrice, cToken.totalBorrows()); - utilities[i] = utility; - totalUtility = add_(totalUtility, utility); - } - } - - for (uint i = 0; i < allMarkets_.length; i++) { - CToken cToken = allMarkets[i]; - uint newSpeed = totalUtility.mantissa > 0 ? mul_(compRate, div_(utilities[i], totalUtility)) : 0; - compSpeeds[address(cToken)] = newSpeed; - emit CompSpeedUpdated(cToken, newSpeed); - } - } - - /** - * @notice Accrue COMP to the market by updating the supply index - * @param cToken The market whose supply index to update - */ - function updateCompSupplyIndex(address cToken) internal { - CompMarketState storage supplyState = compSupplyState[cToken]; - uint supplySpeed = compSpeeds[cToken]; - uint blockNumber = getBlockNumber(); - uint deltaBlocks = sub_(blockNumber, uint(supplyState.block)); - if (deltaBlocks > 0 && supplySpeed > 0) { - uint supplyTokens = CToken(cToken).totalSupply(); - uint compAccrued = mul_(deltaBlocks, supplySpeed); - Double memory ratio = supplyTokens > 0 ? fraction(compAccrued, supplyTokens) : Double({mantissa: 0}); - Double memory index = add_(Double({mantissa: supplyState.index}), ratio); - compSupplyState[cToken] = CompMarketState({ - index: safe224(index.mantissa, "new index exceeds 224 bits"), - block: safe32(blockNumber, "block number exceeds 32 bits") - }); - } else if (deltaBlocks > 0) { - supplyState.block = safe32(blockNumber, "block number exceeds 32 bits"); - } - } - - /** - * @notice Accrue COMP to the market by updating the borrow index - * @param cToken The market whose borrow index to update - */ - function updateCompBorrowIndex(address cToken, Exp memory marketBorrowIndex) internal { - CompMarketState storage borrowState = compBorrowState[cToken]; - uint borrowSpeed = compSpeeds[cToken]; - uint blockNumber = getBlockNumber(); - uint deltaBlocks = sub_(blockNumber, uint(borrowState.block)); - if (deltaBlocks > 0 && borrowSpeed > 0) { - uint borrowAmount = div_(CToken(cToken).totalBorrows(), marketBorrowIndex); - uint compAccrued = mul_(deltaBlocks, borrowSpeed); - Double memory ratio = borrowAmount > 0 ? fraction(compAccrued, borrowAmount) : Double({mantissa: 0}); - Double memory index = add_(Double({mantissa: borrowState.index}), ratio); - compBorrowState[cToken] = CompMarketState({ - index: safe224(index.mantissa, "new index exceeds 224 bits"), - block: safe32(blockNumber, "block number exceeds 32 bits") - }); - } else if (deltaBlocks > 0) { - borrowState.block = safe32(blockNumber, "block number exceeds 32 bits"); - } - } - - /** - * @notice Calculate COMP accrued by a supplier and possibly transfer it to them - * @param cToken The market in which the supplier is interacting - * @param supplier The address of the supplier to distribute COMP to - */ - function distributeSupplierComp(address cToken, address supplier, bool distributeAll) internal { - CompMarketState storage supplyState = compSupplyState[cToken]; - Double memory supplyIndex = Double({mantissa: supplyState.index}); - Double memory supplierIndex = Double({mantissa: compSupplierIndex[cToken][supplier]}); - compSupplierIndex[cToken][supplier] = supplyIndex.mantissa; - - if (supplierIndex.mantissa == 0 && supplyIndex.mantissa > 0) { - supplierIndex.mantissa = compInitialIndex; - } - - Double memory deltaIndex = sub_(supplyIndex, supplierIndex); - uint supplierTokens = CToken(cToken).balanceOf(supplier); - uint supplierDelta = mul_(supplierTokens, deltaIndex); - uint supplierAccrued = add_(compAccrued[supplier], supplierDelta); - compAccrued[supplier] = transferComp(supplier, supplierAccrued, distributeAll ? 0 : compClaimThreshold); - emit DistributedSupplierComp(CToken(cToken), supplier, supplierDelta, supplyIndex.mantissa); - } - - /** - * @notice Calculate COMP accrued by a borrower and possibly transfer it to them - * @dev Borrowers will not begin to accrue until after the first interaction with the protocol. - * @param cToken The market in which the borrower is interacting - * @param borrower The address of the borrower to distribute COMP to - */ - function distributeBorrowerComp(address cToken, address borrower, Exp memory marketBorrowIndex, bool distributeAll) internal { - CompMarketState storage borrowState = compBorrowState[cToken]; - Double memory borrowIndex = Double({mantissa: borrowState.index}); - Double memory borrowerIndex = Double({mantissa: compBorrowerIndex[cToken][borrower]}); - compBorrowerIndex[cToken][borrower] = borrowIndex.mantissa; - - if (borrowerIndex.mantissa > 0) { - Double memory deltaIndex = sub_(borrowIndex, borrowerIndex); - uint borrowerAmount = div_(CToken(cToken).borrowBalanceStored(borrower), marketBorrowIndex); - uint borrowerDelta = mul_(borrowerAmount, deltaIndex); - uint borrowerAccrued = add_(compAccrued[borrower], borrowerDelta); - compAccrued[borrower] = transferComp(borrower, borrowerAccrued, distributeAll ? 0 : compClaimThreshold); - emit DistributedBorrowerComp(CToken(cToken), borrower, borrowerDelta, borrowIndex.mantissa); - } - } - - /** - * @notice Transfer COMP to the user, if they are above the threshold - * @dev Note: If there is not enough COMP, we do not perform the transfer all. - * @param user The address of the user to transfer COMP to - * @param userAccrued The amount of COMP to (possibly) transfer - * @return The amount of COMP which was NOT transferred to the user - */ - function transferComp(address user, uint userAccrued, uint threshold) internal returns (uint) { - if (userAccrued >= threshold && userAccrued > 0) { - Comp comp = Comp(getCompAddress()); - uint compRemaining = comp.balanceOf(address(this)); - if (userAccrued <= compRemaining) { - comp.transfer(user, userAccrued); - return 0; - } - } - return userAccrued; - } - - /** - * @notice Calculate additional accrued COMP for a contributor since last accrual - * @param contributor The address to calculate contributor rewards for - */ - function updateContributorRewards(address contributor) public { - uint compSpeed = compContributorSpeeds[contributor]; - uint blockNumber = getBlockNumber(); - uint deltaBlocks = sub_(blockNumber, lastContributorBlock[contributor]); - if (deltaBlocks > 0 && compSpeed > 0) { - uint newAccrued = mul_(deltaBlocks, compSpeed); - uint contributorAccrued = add_(compAccrued[contributor], newAccrued); - - compAccrued[contributor] = contributorAccrued; - lastContributorBlock[contributor] = blockNumber; - } - } - - /** - * @notice Claim all the comp accrued by holder in all markets - * @param holder The address to claim COMP for - */ - function claimComp(address holder) public { - return claimComp(holder, allMarkets); - } - - /** - * @notice Claim all the comp accrued by holder in the specified markets - * @param holder The address to claim COMP for - * @param cTokens The list of markets to claim COMP in - */ - function claimComp(address holder, CToken[] memory cTokens) public { - address[] memory holders = new address[](1); - holders[0] = holder; - claimComp(holders, cTokens, true, true); - } - - /** - * @notice Claim all comp accrued by the holders - * @param holders The addresses to claim COMP for - * @param cTokens The list of markets to claim COMP in - * @param borrowers Whether or not to claim COMP earned by borrowing - * @param suppliers Whether or not to claim COMP earned by supplying - */ - function claimComp(address[] memory holders, CToken[] memory cTokens, bool borrowers, bool suppliers) public { - for (uint i = 0; i < cTokens.length; i++) { - CToken cToken = cTokens[i]; - require(markets[address(cToken)].isListed, "market must be listed"); - if (borrowers == true) { - Exp memory borrowIndex = Exp({mantissa: cToken.borrowIndex()}); - updateCompBorrowIndex(address(cToken), borrowIndex); - for (uint j = 0; j < holders.length; j++) { - distributeBorrowerComp(address(cToken), holders[j], borrowIndex, true); - } - } - if (suppliers == true) { - updateCompSupplyIndex(address(cToken)); - for (uint j = 0; j < holders.length; j++) { - distributeSupplierComp(address(cToken), holders[j], true); - } - } - } - } - - /** - * @notice Transfer COMP to the user - * @dev Note: If there is not enough COMP, we do not perform the transfer all. - * @param user The address of the user to transfer COMP to - * @param amount The amount of COMP to (possibly) transfer - * @return The amount of COMP which was NOT transferred to the user - */ - function grantCompInternal(address user, uint amount) internal returns (uint) { - Comp comp = Comp(getCompAddress()); - uint compRemaining = comp.balanceOf(address(this)); - if (amount <= compRemaining) { - comp.transfer(user, amount); - return 0; - } - return amount; - } - - /*** Comp Distribution Admin ***/ - - /** - * @notice Transfer COMP to the recipient - * @dev Note: If there is not enough COMP, we do not perform the transfer all. - * @param recipient The address of the recipient to transfer COMP to - * @param amount The amount of COMP to (possibly) transfer - */ - function _grantComp(address recipient, uint amount) public { - require(adminOrInitializing(), "only admin can grant comp"); - uint amountLeft = grantCompInternal(recipient, amount); - require(amountLeft == 0, "insufficient comp for grant"); - emit CompGranted(recipient, amount); - } - - /** - * @notice Set COMP speed for a single contributor - * @param contributor The contributor whose COMP speed to update - * @param compSpeed New COMP speed for contributor - */ - function _setContributorCompSpeed(address contributor, uint compSpeed) public { - require(adminOrInitializing(), "only admin can set comp speed"); - - // note that COMP speed could be set to 0 to halt liquidity rewards for a contributor - updateContributorRewards(contributor); - if (compSpeed == 0) { - // release storage - delete lastContributorBlock[contributor]; - } - lastContributorBlock[contributor] = getBlockNumber(); - compContributorSpeeds[contributor] = compSpeed; - - emit ContributorCompSpeedUpdated(contributor, compSpeed); - } - - /** - * @notice Set the amount of COMP distributed per block - * @param compRate_ The amount of COMP wei per block to distribute - */ - function _setCompRate(uint compRate_) public { - require(adminOrInitializing(), "only admin can change comp rate"); - - uint oldRate = compRate; - compRate = compRate_; - emit NewCompRate(oldRate, compRate_); - - refreshCompSpeedsInternal(); - } - - /** - * @notice Add markets to compMarkets, allowing them to earn COMP in the flywheel - * @param cTokens The addresses of the markets to add - */ - function _addCompMarkets(address[] memory cTokens) public { - require(adminOrInitializing(), "only admin can add comp market"); - - for (uint i = 0; i < cTokens.length; i++) { - _addCompMarketInternal(cTokens[i]); - } - - refreshCompSpeedsInternal(); - } - - function _addCompMarketInternal(address cToken) internal { - Market storage market = markets[cToken]; - require(market.isListed == true, "comp market is not listed"); - require(market.isComped == false, "comp market already added"); - - market.isComped = true; - emit MarketComped(CToken(cToken), true); - - if (compSupplyState[cToken].index == 0 && compSupplyState[cToken].block == 0) { - compSupplyState[cToken] = CompMarketState({ - index: compInitialIndex, - block: safe32(getBlockNumber(), "block number exceeds 32 bits") - }); - } - - if (compBorrowState[cToken].index == 0 && compBorrowState[cToken].block == 0) { - compBorrowState[cToken] = CompMarketState({ - index: compInitialIndex, - block: safe32(getBlockNumber(), "block number exceeds 32 bits") - }); - } - } - - /** - * @notice Remove a market from compMarkets, preventing it from earning COMP in the flywheel - * @param cToken The address of the market to drop - */ - function _dropCompMarket(address cToken) public { - require(msg.sender == admin, "only admin can drop comp market"); - - Market storage market = markets[cToken]; - require(market.isComped == true, "market is not a comp market"); - - market.isComped = false; - emit MarketComped(CToken(cToken), false); - - refreshCompSpeedsInternal(); - } - - /** - * @notice Return all of the markets - * @dev The automatic getter may be used to access an individual market. - * @return The list of market addresses - */ - function getAllMarkets() public view returns (CToken[] memory) { - return allMarkets; - } - - function getBlockNumber() public view returns (uint) { - return block.number; - } - - /** - * @notice Return the address of the COMP token - * @return The address of COMP - */ - function getCompAddress() public view returns (address) { - return 0xc00e94Cb662C3520282E6f5717214004A7f26888; - } -} diff --git a/contracts/ComptrollerG7.sol b/contracts/ComptrollerG7.sol index fb1b280b2..15ab1f953 100644 --- a/contracts/ComptrollerG7.sol +++ b/contracts/ComptrollerG7.sol @@ -1,4 +1,5 @@ -pragma solidity ^0.5.16; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; import "./CToken.sol"; import "./ErrorReporter.sol"; @@ -108,7 +109,7 @@ contract ComptrollerG7 is ComptrollerV5Storage, ComptrollerInterface, Comptrolle * @param cTokens The list of addresses of the cToken markets to be enabled * @return Success indicator for whether each corresponding market was entered */ - function enterMarkets(address[] memory cTokens) public returns (uint[] memory) { + function enterMarkets(address[] memory cTokens) override public returns (uint[] memory) { uint len = cTokens.length; uint[] memory results = new uint[](len); @@ -160,7 +161,7 @@ contract ComptrollerG7 is ComptrollerV5Storage, ComptrollerInterface, Comptrolle * @param cTokenAddress The address of the asset to be removed * @return Whether or not the account successfully exited the market */ - function exitMarket(address cTokenAddress) external returns (uint) { + function exitMarket(address cTokenAddress) override external returns (uint) { CToken cToken = CToken(cTokenAddress); /* Get sender tokensHeld and amountOwed underlying from the cToken */ (uint oErr, uint tokensHeld, uint amountOwed, ) = cToken.getAccountSnapshot(msg.sender); @@ -205,7 +206,7 @@ contract ComptrollerG7 is ComptrollerV5Storage, ComptrollerInterface, Comptrolle // copy last item in list to location of item to be removed, reduce length by 1 CToken[] storage storedList = accountAssets[msg.sender]; storedList[assetIndex] = storedList[storedList.length - 1]; - storedList.length--; + storedList.pop(); emit MarketExited(cToken, msg.sender); @@ -221,7 +222,7 @@ contract ComptrollerG7 is ComptrollerV5Storage, ComptrollerInterface, Comptrolle * @param mintAmount The amount of underlying being supplied to the market in exchange for tokens * @return 0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol) */ - function mintAllowed(address cToken, address minter, uint mintAmount) external returns (uint) { + function mintAllowed(address cToken, address minter, uint mintAmount) override external returns (uint) { // Pausing is a very serious situation - we revert to sound the alarms require(!mintGuardianPaused[cToken], "mint is paused"); @@ -247,7 +248,7 @@ contract ComptrollerG7 is ComptrollerV5Storage, ComptrollerInterface, Comptrolle * @param actualMintAmount The amount of the underlying asset being minted * @param mintTokens The number of tokens being minted */ - function mintVerify(address cToken, address minter, uint actualMintAmount, uint mintTokens) external { + function mintVerify(address cToken, address minter, uint actualMintAmount, uint mintTokens) override external { // Shh - currently unused cToken; minter; @@ -267,7 +268,7 @@ contract ComptrollerG7 is ComptrollerV5Storage, ComptrollerInterface, Comptrolle * @param redeemTokens The number of cTokens to exchange for the underlying asset in the market * @return 0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol) */ - function redeemAllowed(address cToken, address redeemer, uint redeemTokens) external returns (uint) { + function redeemAllowed(address cToken, address redeemer, uint redeemTokens) override external returns (uint) { uint allowed = redeemAllowedInternal(cToken, redeemer, redeemTokens); if (allowed != uint(Error.NO_ERROR)) { return allowed; @@ -309,7 +310,7 @@ contract ComptrollerG7 is ComptrollerV5Storage, ComptrollerInterface, Comptrolle * @param redeemAmount The amount of the underlying asset being redeemed * @param redeemTokens The number of tokens being redeemed */ - function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) external { + function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) override external { // Shh - currently unused cToken; redeemer; @@ -327,7 +328,7 @@ contract ComptrollerG7 is ComptrollerV5Storage, ComptrollerInterface, Comptrolle * @param borrowAmount The amount of underlying the account would borrow * @return 0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol) */ - function borrowAllowed(address cToken, address borrower, uint borrowAmount) external returns (uint) { + function borrowAllowed(address cToken, address borrower, uint borrowAmount) override external returns (uint) { // Pausing is a very serious situation - we revert to sound the alarms require(!borrowGuardianPaused[cToken], "borrow is paused"); @@ -384,7 +385,7 @@ contract ComptrollerG7 is ComptrollerV5Storage, ComptrollerInterface, Comptrolle * @param borrower The address borrowing the underlying * @param borrowAmount The amount of the underlying asset requested to borrow */ - function borrowVerify(address cToken, address borrower, uint borrowAmount) external { + function borrowVerify(address cToken, address borrower, uint borrowAmount) override external { // Shh - currently unused cToken; borrower; @@ -408,7 +409,7 @@ contract ComptrollerG7 is ComptrollerV5Storage, ComptrollerInterface, Comptrolle address cToken, address payer, address borrower, - uint repayAmount) external returns (uint) { + uint repayAmount) override external returns (uint) { // Shh - currently unused payer; borrower; @@ -438,7 +439,7 @@ contract ComptrollerG7 is ComptrollerV5Storage, ComptrollerInterface, Comptrolle address payer, address borrower, uint actualRepayAmount, - uint borrowerIndex) external { + uint borrowerIndex) override external { // Shh - currently unused cToken; payer; @@ -465,7 +466,7 @@ contract ComptrollerG7 is ComptrollerV5Storage, ComptrollerInterface, Comptrolle address cTokenCollateral, address liquidator, address borrower, - uint repayAmount) external returns (uint) { + uint repayAmount) override external returns (uint) { // Shh - currently unused liquidator; @@ -506,7 +507,7 @@ contract ComptrollerG7 is ComptrollerV5Storage, ComptrollerInterface, Comptrolle address liquidator, address borrower, uint actualRepayAmount, - uint seizeTokens) external { + uint seizeTokens) override external { // Shh - currently unused cTokenBorrowed; cTokenCollateral; @@ -534,7 +535,7 @@ contract ComptrollerG7 is ComptrollerV5Storage, ComptrollerInterface, Comptrolle address cTokenBorrowed, address liquidator, address borrower, - uint seizeTokens) external returns (uint) { + uint seizeTokens) override external returns (uint) { // Pausing is a very serious situation - we revert to sound the alarms require(!seizeGuardianPaused, "seize is paused"); @@ -570,7 +571,7 @@ contract ComptrollerG7 is ComptrollerV5Storage, ComptrollerInterface, Comptrolle address cTokenBorrowed, address liquidator, address borrower, - uint seizeTokens) external { + uint seizeTokens) override external { // Shh - currently unused cTokenCollateral; cTokenBorrowed; @@ -592,7 +593,7 @@ contract ComptrollerG7 is ComptrollerV5Storage, ComptrollerInterface, Comptrolle * @param transferTokens The number of cTokens to transfer * @return 0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol) */ - function transferAllowed(address cToken, address src, address dst, uint transferTokens) external returns (uint) { + function transferAllowed(address cToken, address src, address dst, uint transferTokens) override external returns (uint) { // Pausing is a very serious situation - we revert to sound the alarms require(!transferGuardianPaused, "transfer is paused"); @@ -618,7 +619,7 @@ contract ComptrollerG7 is ComptrollerV5Storage, ComptrollerInterface, Comptrolle * @param dst The account which receives the tokens * @param transferTokens The number of cTokens to transfer */ - function transferVerify(address cToken, address src, address dst, uint transferTokens) external { + function transferVerify(address cToken, address src, address dst, uint transferTokens) override external { // Shh - currently unused cToken; src; @@ -658,7 +659,7 @@ contract ComptrollerG7 is ComptrollerV5Storage, ComptrollerInterface, Comptrolle * account shortfall below collateral requirements) */ function getAccountLiquidity(address account) public view returns (uint, uint, uint) { - (Error err, uint liquidity, uint shortfall) = getHypotheticalAccountLiquidityInternal(account, CToken(0), 0, 0); + (Error err, uint liquidity, uint shortfall) = getHypotheticalAccountLiquidityInternal(account, CToken(address(0)), 0, 0); return (uint(err), liquidity, shortfall); } @@ -670,7 +671,7 @@ contract ComptrollerG7 is ComptrollerV5Storage, ComptrollerInterface, Comptrolle * account shortfall below collateral requirements) */ function getAccountLiquidityInternal(address account) internal view returns (Error, uint, uint) { - return getHypotheticalAccountLiquidityInternal(account, CToken(0), 0, 0); + return getHypotheticalAccountLiquidityInternal(account, CToken(address(0)), 0, 0); } /** @@ -770,7 +771,7 @@ contract ComptrollerG7 is ComptrollerV5Storage, ComptrollerInterface, Comptrolle * @param actualRepayAmount The amount of cTokenBorrowed underlying to convert into cTokenCollateral tokens * @return (errorCode, number of cTokenCollateral tokens to be seized in a liquidation) */ - function liquidateCalculateSeizeTokens(address cTokenBorrowed, address cTokenCollateral, uint actualRepayAmount) external view returns (uint, uint) { + function liquidateCalculateSeizeTokens(address cTokenBorrowed, address cTokenCollateral, uint actualRepayAmount) override external view returns (uint, uint) { /* Read oracle prices for borrowed and collateral markets */ uint priceBorrowedMantissa = oracle.getUnderlyingPrice(CToken(cTokenBorrowed)); uint priceCollateralMantissa = oracle.getUnderlyingPrice(CToken(cTokenCollateral)); @@ -925,7 +926,10 @@ contract ComptrollerG7 is ComptrollerV5Storage, ComptrollerInterface, Comptrolle cToken.isCToken(); // Sanity check to make sure its really a CToken // Note that isComped is not in active use anymore - markets[address(cToken)] = Market({isListed: true, isComped: false, collateralFactorMantissa: 0}); + Market storage market = markets[address(cToken)]; + market.isListed = true; + market.isComped = false; + market.collateralFactorMantissa = 0; _addMarketInternal(address(cToken)); @@ -949,7 +953,7 @@ contract ComptrollerG7 is ComptrollerV5Storage, ComptrollerInterface, Comptrolle * @param newBorrowCaps The new borrow cap values in underlying to be set. A value of 0 corresponds to unlimited borrowing. */ function _setMarketBorrowCaps(CToken[] calldata cTokens, uint[] calldata newBorrowCaps) external { - require(msg.sender == admin || msg.sender == borrowCapGuardian, "only admin or borrow cap guardian can set borrow caps"); + require(msg.sender == admin || msg.sender == borrowCapGuardian, "only admin or borrow cap guardian can set borrow caps"); uint numMarkets = cTokens.length; uint numBorrowCaps = newBorrowCaps.length; @@ -1330,4 +1334,4 @@ contract ComptrollerG7 is ComptrollerV5Storage, ComptrollerInterface, Comptrolle function getCompAddress() public view returns (address) { return 0xc00e94Cb662C3520282E6f5717214004A7f26888; } -} \ No newline at end of file +} diff --git a/contracts/ComptrollerInterface.sol b/contracts/ComptrollerInterface.sol index ce63c7849..8d60a336d 100644 --- a/contracts/ComptrollerInterface.sol +++ b/contracts/ComptrollerInterface.sol @@ -1,71 +1,72 @@ -pragma solidity ^0.5.16; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; -contract ComptrollerInterface { +abstract 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 cTokens) external returns (uint[] memory); - function exitMarket(address cToken) external returns (uint); + function enterMarkets(address[] calldata cTokens) virtual external returns (uint[] memory); + function exitMarket(address cToken) virtual external returns (uint); /*** Policy Hooks ***/ - function mintAllowed(address cToken, address minter, uint mintAmount) external returns (uint); - function mintVerify(address cToken, address minter, uint mintAmount, uint mintTokens) external; + function mintAllowed(address cToken, address minter, uint mintAmount) virtual external returns (uint); + function mintVerify(address cToken, address minter, uint mintAmount, uint mintTokens) virtual external; - function redeemAllowed(address cToken, address redeemer, uint redeemTokens) external returns (uint); - function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) external; + function redeemAllowed(address cToken, address redeemer, uint redeemTokens) virtual external returns (uint); + function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) virtual external; - function borrowAllowed(address cToken, address borrower, uint borrowAmount) external returns (uint); - function borrowVerify(address cToken, address borrower, uint borrowAmount) external; + function borrowAllowed(address cToken, address borrower, uint borrowAmount) virtual external returns (uint); + function borrowVerify(address cToken, address borrower, uint borrowAmount) virtual external; function repayBorrowAllowed( address cToken, address payer, address borrower, - uint repayAmount) external returns (uint); + uint repayAmount) virtual external returns (uint); function repayBorrowVerify( address cToken, address payer, address borrower, uint repayAmount, - uint borrowerIndex) external; + uint borrowerIndex) virtual external; function liquidateBorrowAllowed( address cTokenBorrowed, address cTokenCollateral, address liquidator, address borrower, - uint repayAmount) external returns (uint); + uint repayAmount) virtual external returns (uint); function liquidateBorrowVerify( address cTokenBorrowed, address cTokenCollateral, address liquidator, address borrower, uint repayAmount, - uint seizeTokens) external; + uint seizeTokens) virtual external; function seizeAllowed( address cTokenCollateral, address cTokenBorrowed, address liquidator, address borrower, - uint seizeTokens) external returns (uint); + uint seizeTokens) virtual external returns (uint); function seizeVerify( address cTokenCollateral, address cTokenBorrowed, address liquidator, address borrower, - uint seizeTokens) external; + uint seizeTokens) virtual external; - function transferAllowed(address cToken, address src, address dst, uint transferTokens) external returns (uint); - function transferVerify(address cToken, address src, address dst, uint transferTokens) external; + function transferAllowed(address cToken, address src, address dst, uint transferTokens) virtual external returns (uint); + function transferVerify(address cToken, address src, address dst, uint transferTokens) virtual external; /*** Liquidity/Liquidation Calculations ***/ function liquidateCalculateSeizeTokens( address cTokenBorrowed, address cTokenCollateral, - uint repayAmount) external view returns (uint, uint); + uint repayAmount) virtual external view returns (uint, uint); } diff --git a/contracts/ComptrollerStorage.sol b/contracts/ComptrollerStorage.sol index b74db651e..0455598ef 100644 --- a/contracts/ComptrollerStorage.sol +++ b/contracts/ComptrollerStorage.sol @@ -1,4 +1,5 @@ -pragma solidity ^0.5.16; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; import "./CToken.sol"; import "./PriceOracle.sol"; @@ -56,20 +57,18 @@ contract ComptrollerV1Storage is UnitrollerAdminStorage { contract ComptrollerV2Storage is ComptrollerV1Storage { struct Market { - /// @notice Whether or not this market is listed + // Whether or not this market is listed bool isListed; - /** - * @notice Multiplier representing the most one can borrow against their collateral in this market. - * For instance, 0.9 to allow borrowing 90% of collateral value. - * Must be between 0 and 1, and stored as a mantissa. - */ + // Multiplier representing the most one can borrow against their collateral in this market. + // For instance, 0.9 to allow borrowing 90% of collateral value. + // Must be between 0 and 1, and stored as a mantissa. uint collateralFactorMantissa; - /// @notice Per-market mapping of "accounts in this asset" + // Per-market mapping of "accounts in this asset" mapping(address => bool) accountMembership; - /// @notice Whether or not this market receives COMP + // Whether or not this market receives COMP bool isComped; } @@ -96,10 +95,10 @@ contract ComptrollerV2Storage is ComptrollerV1Storage { contract ComptrollerV3Storage is ComptrollerV2Storage { struct CompMarketState { - /// @notice The market's last updated compBorrowIndex or compSupplyIndex + // The market's last updated compBorrowIndex or compSupplyIndex uint224 index; - /// @notice The block number the index was last updated at + // The block number the index was last updated at uint32 block; } diff --git a/contracts/DAIInterestRateModelV3.sol b/contracts/DAIInterestRateModelV3.sol index 96370b3ec..d78f18d1f 100644 --- a/contracts/DAIInterestRateModelV3.sol +++ b/contracts/DAIInterestRateModelV3.sol @@ -1,7 +1,7 @@ -pragma solidity ^0.5.16; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; import "./JumpRateModelV2.sol"; -import "./SafeMath.sol"; /** * @title Compound's DAIInterestRateModel Contract (version 3) @@ -11,7 +11,10 @@ import "./SafeMath.sol"; * the model prior to the "kink" from 2% to 4%, and enabling updateable parameters. */ contract DAIInterestRateModelV3 is JumpRateModelV2 { - using SafeMath for uint; + uint256 private constant BASE = 1e18; + uint256 private constant RAY_BASE = 1e27; + uint256 private constant RAY_TO_BASE_SCALE = 1e9; + uint256 private constant SECONDS_PER_BLOCK = 15; /** * @notice The additional margin per block separating the base borrow rate from the roof. @@ -43,12 +46,12 @@ contract DAIInterestRateModelV3 is JumpRateModelV2 { /** * @notice External function to update the parameters of the interest rate model - * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by 1e18). For DAI, this is calculated from DSR and SF. Input not used. - * @param gapPerYear The Additional margin per year separating the base borrow rate from the roof. (scaled by 1e18) + * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by BASE). For DAI, this is calculated from DSR and SF. Input not used. + * @param gapPerYear The Additional margin per year separating the base borrow rate from the roof. (scaled by BASE) * @param jumpMultiplierPerYear The jumpMultiplierPerYear after hitting a specified utilization point * @param kink_ The utilization point at which the jump multiplier is applied */ - function updateJumpRateModel(uint baseRatePerYear, uint gapPerYear, uint jumpMultiplierPerYear, uint kink_) external { + function updateJumpRateModel(uint baseRatePerYear, uint gapPerYear, uint jumpMultiplierPerYear, uint kink_) override external { require(msg.sender == owner, "only the owner may call this function."); gapPerBlock = gapPerYear / blocksPerYear; updateJumpRateModelInternal(0, 0, jumpMultiplierPerYear, kink_); @@ -61,29 +64,28 @@ contract DAIInterestRateModelV3 is JumpRateModelV2 { * @param borrows The total amount of borrows the market has outstanding * @param reserves The total amnount of reserves the market has * @param reserveFactorMantissa The current reserve factor the market has - * @return The supply rate per block (as a percentage, and scaled by 1e18) + * @return The supply rate per block (as a percentage, and scaled by BASE) */ - function getSupplyRate(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) public view returns (uint) { + function getSupplyRate(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) override public view returns (uint) { uint protocolRate = super.getSupplyRate(cash, borrows, reserves, reserveFactorMantissa); - uint underlying = cash.add(borrows).sub(reserves); + uint underlying = cash + borrows - reserves; if (underlying == 0) { return protocolRate; } else { - uint cashRate = cash.mul(dsrPerBlock()).div(underlying); - return cashRate.add(protocolRate); + uint cashRate = cash * dsrPerBlock() / underlying; + return cashRate + protocolRate; } } /** * @notice Calculates the Dai savings rate per block - * @return The Dai savings rate per block (as a percentage, and scaled by 1e18) + * @return The Dai savings rate per block (as a percentage, and scaled by BASE) */ function dsrPerBlock() public view returns (uint) { - return pot - .dsr().sub(1e27) // scaled 1e27 aka RAY, and includes an extra "ONE" before subraction - .div(1e9) // descale to 1e18 - .mul(15); // 15 seconds per block + return (pot.dsr() - RAY_BASE) // scaled RAY_BASE aka RAY, and includes an extra "ONE" before subtraction + / RAY_TO_BASE_SCALE // descale to BASE + * SECONDS_PER_BLOCK; // seconds per block } /** @@ -91,16 +93,16 @@ contract DAIInterestRateModelV3 is JumpRateModelV2 { */ function poke() public { (uint duty, ) = jug.ilks("ETH-A"); - uint stabilityFeePerBlock = duty.add(jug.base()).sub(1e27).mul(1e18).div(1e27).mul(15); + uint stabilityFeePerBlock = (duty + jug.base() - RAY_BASE) / RAY_TO_BASE_SCALE * SECONDS_PER_BLOCK; // We ensure the minimum borrow rate >= DSR / (1 - reserve factor) - baseRatePerBlock = dsrPerBlock().mul(1e18).div(assumedOneMinusReserveFactorMantissa); + baseRatePerBlock = dsrPerBlock() * BASE / assumedOneMinusReserveFactorMantissa; // The roof borrow rate is max(base rate, stability fee) + gap, from which we derive the slope if (baseRatePerBlock < stabilityFeePerBlock) { - multiplierPerBlock = stabilityFeePerBlock.sub(baseRatePerBlock).add(gapPerBlock).mul(1e18).div(kink); + multiplierPerBlock = (stabilityFeePerBlock - baseRatePerBlock + gapPerBlock) * BASE / kink; } else { - multiplierPerBlock = gapPerBlock.mul(1e18).div(kink); + multiplierPerBlock = gapPerBlock * BASE / kink; } emit NewInterestParams(baseRatePerBlock, multiplierPerBlock, jumpMultiplierPerBlock, kink); @@ -110,7 +112,7 @@ contract DAIInterestRateModelV3 is JumpRateModelV2 { /*** Maker Interfaces ***/ -contract PotLike { +interface PotLike { function chi() external view returns (uint); function dsr() external view returns (uint); function rho() external view returns (uint); @@ -127,6 +129,6 @@ contract JugLike { uint256 rho; } - mapping (bytes32 => Ilk) public ilks; - uint256 public base; + mapping (bytes32 => Ilk) public ilks; + uint256 public base; } diff --git a/contracts/EIP20Interface.sol b/contracts/EIP20Interface.sol index f791e564b..b35fd1e4d 100644 --- a/contracts/EIP20Interface.sol +++ b/contracts/EIP20Interface.sol @@ -1,4 +1,5 @@ -pragma solidity ^0.5.16; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; /** * @title ERC 20 Token Standard Interface @@ -18,7 +19,7 @@ interface EIP20Interface { /** * @notice Gets the balance of the specified address * @param owner The address from which the balance will be retrieved - * @return The balance + * @return balance The balance */ function balanceOf(address owner) external view returns (uint256 balance); @@ -26,7 +27,7 @@ interface EIP20Interface { * @notice Transfer `amount` tokens from `msg.sender` to `dst` * @param dst The address of the destination account * @param amount The number of tokens to transfer - * @return Whether or not the transfer succeeded + * @return success Whether or not the transfer succeeded */ function transfer(address dst, uint256 amount) external returns (bool success); @@ -35,7 +36,7 @@ interface EIP20Interface { * @param src The address of the source account * @param dst The address of the destination account * @param amount The number of tokens to transfer - * @return Whether or not the transfer succeeded + * @return success Whether or not the transfer succeeded */ function transferFrom(address src, address dst, uint256 amount) external returns (bool success); @@ -45,7 +46,7 @@ interface EIP20Interface { * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve) * @param spender The address of the account which may transfer tokens * @param amount The number of tokens that are approved (-1 means infinite) - * @return Whether or not the approval succeeded + * @return success Whether or not the approval succeeded */ function approve(address spender, uint256 amount) external returns (bool success); @@ -53,7 +54,7 @@ interface EIP20Interface { * @notice Get the current allowance from `owner` for `spender` * @param owner The address of the account which owns the tokens to be spent * @param spender The address of the account which may transfer tokens - * @return The number of tokens allowed to be spent (-1 means infinite) + * @return remaining The number of tokens allowed to be spent (-1 means infinite) */ function allowance(address owner, address spender) external view returns (uint256 remaining); diff --git a/contracts/EIP20NonStandardInterface.sol b/contracts/EIP20NonStandardInterface.sol index 0f695703f..54602f966 100644 --- a/contracts/EIP20NonStandardInterface.sol +++ b/contracts/EIP20NonStandardInterface.sol @@ -1,4 +1,5 @@ -pragma solidity ^0.5.16; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; /** * @title EIP20NonStandardInterface @@ -16,7 +17,7 @@ interface EIP20NonStandardInterface { /** * @notice Gets the balance of the specified address * @param owner The address from which the balance will be retrieved - * @return The balance + * @return balance The balance */ function balanceOf(address owner) external view returns (uint256 balance); @@ -53,7 +54,7 @@ interface EIP20NonStandardInterface { * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve) * @param spender The address of the account which may transfer tokens * @param amount The number of tokens that are approved - * @return Whether or not the approval succeeded + * @return success Whether or not the approval succeeded */ function approve(address spender, uint256 amount) external returns (bool success); @@ -61,7 +62,7 @@ interface EIP20NonStandardInterface { * @notice Get the current allowance from `owner` for `spender` * @param owner The address of the account which owns the tokens to be spent * @param spender The address of the account which may transfer tokens - * @return The number of tokens allowed to be spent + * @return remaining The number of tokens allowed to be spent */ function allowance(address owner, address spender) external view returns (uint256 remaining); diff --git a/contracts/ErrorReporter.sol b/contracts/ErrorReporter.sol index 33cc775f5..928ea0ed1 100644 --- a/contracts/ErrorReporter.sol +++ b/contracts/ErrorReporter.sol @@ -1,4 +1,5 @@ -pragma solidity ^0.5.16; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; contract ComptrollerErrorReporter { enum Error { @@ -71,137 +72,56 @@ contract ComptrollerErrorReporter { } contract TokenErrorReporter { - enum Error { - NO_ERROR, - UNAUTHORIZED, - BAD_INPUT, - COMPTROLLER_REJECTION, - COMPTROLLER_CALCULATION_ERROR, - INTEREST_RATE_MODEL_ERROR, - INVALID_ACCOUNT_PAIR, - INVALID_CLOSE_AMOUNT_REQUESTED, - INVALID_COLLATERAL_FACTOR, - MATH_ERROR, - MARKET_NOT_FRESH, - MARKET_NOT_LISTED, - TOKEN_INSUFFICIENT_ALLOWANCE, - TOKEN_INSUFFICIENT_BALANCE, - TOKEN_INSUFFICIENT_CASH, - TOKEN_TRANSFER_IN_FAILED, - TOKEN_TRANSFER_OUT_FAILED - } + uint public constant NO_ERROR = 0; // support legacy return codes - /* - * Note: FailureInfo (but not Error) is kept in alphabetical order - * This is because FailureInfo grows significantly faster, and - * the order of Error has some meaning, while the order of FailureInfo - * is entirely arbitrary. - */ - enum FailureInfo { - ACCEPT_ADMIN_PENDING_ADMIN_CHECK, - ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED, - ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED, - ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED, - ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED, - ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED, - ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED, - BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED, - BORROW_ACCRUE_INTEREST_FAILED, - BORROW_CASH_NOT_AVAILABLE, - BORROW_FRESHNESS_CHECK, - BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED, - BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED, - BORROW_MARKET_NOT_LISTED, - BORROW_COMPTROLLER_REJECTION, - LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED, - LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED, - LIQUIDATE_COLLATERAL_FRESHNESS_CHECK, - LIQUIDATE_COMPTROLLER_REJECTION, - LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED, - LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX, - LIQUIDATE_CLOSE_AMOUNT_IS_ZERO, - LIQUIDATE_FRESHNESS_CHECK, - LIQUIDATE_LIQUIDATOR_IS_BORROWER, - LIQUIDATE_REPAY_BORROW_FRESH_FAILED, - LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, - LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, - LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, - LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER, - LIQUIDATE_SEIZE_TOO_MUCH, - MINT_ACCRUE_INTEREST_FAILED, - MINT_COMPTROLLER_REJECTION, - MINT_EXCHANGE_CALCULATION_FAILED, - MINT_EXCHANGE_RATE_READ_FAILED, - MINT_FRESHNESS_CHECK, - MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED, - MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED, - MINT_TRANSFER_IN_FAILED, - MINT_TRANSFER_IN_NOT_POSSIBLE, - REDEEM_ACCRUE_INTEREST_FAILED, - REDEEM_COMPTROLLER_REJECTION, - REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED, - REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED, - REDEEM_EXCHANGE_RATE_READ_FAILED, - REDEEM_FRESHNESS_CHECK, - REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED, - REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED, - REDEEM_TRANSFER_OUT_NOT_POSSIBLE, - REDUCE_RESERVES_ACCRUE_INTEREST_FAILED, - REDUCE_RESERVES_ADMIN_CHECK, - REDUCE_RESERVES_CASH_NOT_AVAILABLE, - REDUCE_RESERVES_FRESH_CHECK, - REDUCE_RESERVES_VALIDATION, - REPAY_BEHALF_ACCRUE_INTEREST_FAILED, - REPAY_BORROW_ACCRUE_INTEREST_FAILED, - REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED, - REPAY_BORROW_COMPTROLLER_REJECTION, - REPAY_BORROW_FRESHNESS_CHECK, - REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED, - REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED, - REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE, - SET_COLLATERAL_FACTOR_OWNER_CHECK, - SET_COLLATERAL_FACTOR_VALIDATION, - SET_COMPTROLLER_OWNER_CHECK, - SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED, - SET_INTEREST_RATE_MODEL_FRESH_CHECK, - SET_INTEREST_RATE_MODEL_OWNER_CHECK, - SET_MAX_ASSETS_OWNER_CHECK, - SET_ORACLE_MARKET_NOT_LISTED, - SET_PENDING_ADMIN_OWNER_CHECK, - SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED, - SET_RESERVE_FACTOR_ADMIN_CHECK, - SET_RESERVE_FACTOR_FRESH_CHECK, - SET_RESERVE_FACTOR_BOUNDS_CHECK, - TRANSFER_COMPTROLLER_REJECTION, - TRANSFER_NOT_ALLOWED, - TRANSFER_NOT_ENOUGH, - TRANSFER_TOO_MUCH, - ADD_RESERVES_ACCRUE_INTEREST_FAILED, - ADD_RESERVES_FRESH_CHECK, - ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE - } + error TransferComptrollerRejection(uint256 errorCode); + error TransferNotAllowed(); + error TransferNotEnough(); + error TransferTooMuch(); - /** - * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary - * contract-specific code that enables us to report opaque error codes from upgradeable contracts. - **/ - event Failure(uint error, uint info, uint detail); + error MintComptrollerRejection(uint256 errorCode); + error MintFreshnessCheck(); - /** - * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator - */ - function fail(Error err, FailureInfo info) internal returns (uint) { - emit Failure(uint(err), uint(info), 0); + error RedeemComptrollerRejection(uint256 errorCode); + error RedeemFreshnessCheck(); + error RedeemTransferOutNotPossible(); - return uint(err); - } + error BorrowComptrollerRejection(uint256 errorCode); + error BorrowFreshnessCheck(); + error BorrowCashNotAvailable(); - /** - * @dev use this when reporting an opaque error from an upgradeable collaborator contract - */ - function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) { - emit Failure(uint(err), uint(info), opaqueError); + error RepayBorrowComptrollerRejection(uint256 errorCode); + error RepayBorrowFreshnessCheck(); - return uint(err); - } -} \ No newline at end of file + error LiquidateComptrollerRejection(uint256 errorCode); + error LiquidateFreshnessCheck(); + error LiquidateCollateralFreshnessCheck(); + error LiquidateAccrueBorrowInterestFailed(uint256 errorCode); + error LiquidateAccrueCollateralInterestFailed(uint256 errorCode); + error LiquidateLiquidatorIsBorrower(); + error LiquidateCloseAmountIsZero(); + error LiquidateCloseAmountIsUintMax(); + error LiquidateRepayBorrowFreshFailed(uint256 errorCode); + + error LiquidateSeizeComptrollerRejection(uint256 errorCode); + error LiquidateSeizeLiquidatorIsBorrower(); + + error AcceptAdminPendingAdminCheck(); + + error SetComptrollerOwnerCheck(); + error SetPendingAdminOwnerCheck(); + + error SetReserveFactorAdminCheck(); + error SetReserveFactorFreshCheck(); + error SetReserveFactorBoundsCheck(); + + error AddReservesFactorFreshCheck(uint256 actualAddAmount); + + error ReduceReservesAdminCheck(); + error ReduceReservesFreshCheck(); + error ReduceReservesCashNotAvailable(); + error ReduceReservesCashValidation(); + + error SetInterestRateModelOwnerCheck(); + error SetInterestRateModelFreshCheck(); +} diff --git a/contracts/Exponential.sol b/contracts/Exponential.sol deleted file mode 100644 index 5232972e1..000000000 --- a/contracts/Exponential.sol +++ /dev/null @@ -1,183 +0,0 @@ -pragma solidity ^0.5.16; - -import "./CarefulMath.sol"; -import "./ExponentialNoError.sol"; - -/** - * @title Exponential module for storing fixed-precision decimals - * @author Compound - * @dev Legacy contract for compatibility reasons with existing contracts that still use MathError - * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places. - * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is: - * `Exp({mantissa: 5100000000000000000})`. - */ -contract Exponential is CarefulMath, ExponentialNoError { - /** - * @dev Creates an exponential from numerator and denominator values. - * Note: Returns an error if (`num` * 10e18) > MAX_INT, - * or if `denom` is zero. - */ - function getExp(uint num, uint denom) pure internal returns (MathError, Exp memory) { - (MathError err0, uint scaledNumerator) = mulUInt(num, expScale); - if (err0 != MathError.NO_ERROR) { - return (err0, Exp({mantissa: 0})); - } - - (MathError err1, uint rational) = divUInt(scaledNumerator, denom); - if (err1 != MathError.NO_ERROR) { - return (err1, Exp({mantissa: 0})); - } - - return (MathError.NO_ERROR, Exp({mantissa: rational})); - } - - /** - * @dev Adds two exponentials, returning a new exponential. - */ - function addExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) { - (MathError error, uint result) = addUInt(a.mantissa, b.mantissa); - - return (error, Exp({mantissa: result})); - } - - /** - * @dev Subtracts two exponentials, returning a new exponential. - */ - function subExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) { - (MathError error, uint result) = subUInt(a.mantissa, b.mantissa); - - return (error, Exp({mantissa: result})); - } - - /** - * @dev Multiply an Exp by a scalar, returning a new Exp. - */ - function mulScalar(Exp memory a, uint scalar) pure internal returns (MathError, Exp memory) { - (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar); - if (err0 != MathError.NO_ERROR) { - return (err0, Exp({mantissa: 0})); - } - - return (MathError.NO_ERROR, Exp({mantissa: scaledMantissa})); - } - - /** - * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer. - */ - function mulScalarTruncate(Exp memory a, uint scalar) pure internal returns (MathError, uint) { - (MathError err, Exp memory product) = mulScalar(a, scalar); - if (err != MathError.NO_ERROR) { - return (err, 0); - } - - return (MathError.NO_ERROR, truncate(product)); - } - - /** - * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer. - */ - function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) pure internal returns (MathError, uint) { - (MathError err, Exp memory product) = mulScalar(a, scalar); - if (err != MathError.NO_ERROR) { - return (err, 0); - } - - return addUInt(truncate(product), addend); - } - - /** - * @dev Divide an Exp by a scalar, returning a new Exp. - */ - function divScalar(Exp memory a, uint scalar) pure internal returns (MathError, Exp memory) { - (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar); - if (err0 != MathError.NO_ERROR) { - return (err0, Exp({mantissa: 0})); - } - - return (MathError.NO_ERROR, Exp({mantissa: descaledMantissa})); - } - - /** - * @dev Divide a scalar by an Exp, returning a new Exp. - */ - function divScalarByExp(uint scalar, Exp memory divisor) pure internal returns (MathError, Exp memory) { - /* - We are doing this as: - getExp(mulUInt(expScale, scalar), divisor.mantissa) - - How it works: - Exp = a / b; - Scalar = s; - `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale` - */ - (MathError err0, uint numerator) = mulUInt(expScale, scalar); - if (err0 != MathError.NO_ERROR) { - return (err0, Exp({mantissa: 0})); - } - return getExp(numerator, divisor.mantissa); - } - - /** - * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer. - */ - function divScalarByExpTruncate(uint scalar, Exp memory divisor) pure internal returns (MathError, uint) { - (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor); - if (err != MathError.NO_ERROR) { - return (err, 0); - } - - return (MathError.NO_ERROR, truncate(fraction)); - } - - /** - * @dev Multiplies two exponentials, returning a new exponential. - */ - function mulExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) { - - (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa); - if (err0 != MathError.NO_ERROR) { - return (err0, Exp({mantissa: 0})); - } - - // We add half the scale before dividing so that we get rounding instead of truncation. - // See "Listing 6" and text above it at https://accu.org/index.php/journals/1717 - // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18. - (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct); - if (err1 != MathError.NO_ERROR) { - return (err1, Exp({mantissa: 0})); - } - - (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale); - // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero. - assert(err2 == MathError.NO_ERROR); - - return (MathError.NO_ERROR, Exp({mantissa: product})); - } - - /** - * @dev Multiplies two exponentials given their mantissas, returning a new exponential. - */ - function mulExp(uint a, uint b) pure internal returns (MathError, Exp memory) { - return mulExp(Exp({mantissa: a}), Exp({mantissa: b})); - } - - /** - * @dev Multiplies three exponentials, returning a new exponential. - */ - function mulExp3(Exp memory a, Exp memory b, Exp memory c) pure internal returns (MathError, Exp memory) { - (MathError err, Exp memory ab) = mulExp(a, b); - if (err != MathError.NO_ERROR) { - return (err, ab); - } - return mulExp(ab, c); - } - - /** - * @dev Divides two exponentials, returning a new exponential. - * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b, - * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa) - */ - function divExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) { - return getExp(a.mantissa, b.mantissa); - } -} diff --git a/contracts/ExponentialNoError.sol b/contracts/ExponentialNoError.sol index 1e423bc6f..23f833760 100644 --- a/contracts/ExponentialNoError.sol +++ b/contracts/ExponentialNoError.sol @@ -1,4 +1,5 @@ -pragma solidity ^0.5.16; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; /** * @title Exponential module for storing fixed-precision decimals @@ -93,13 +94,7 @@ contract ExponentialNoError { } function add_(uint a, uint b) pure internal returns (uint) { - return add_(a, b, "addition overflow"); - } - - function add_(uint a, uint b, string memory errorMessage) pure internal returns (uint) { - uint c = a + b; - require(c >= a, errorMessage); - return c; + return a + b; } function sub_(Exp memory a, Exp memory b) pure internal returns (Exp memory) { @@ -111,11 +106,6 @@ contract ExponentialNoError { } function sub_(uint a, uint b) pure internal returns (uint) { - return sub_(a, b, "subtraction underflow"); - } - - function sub_(uint a, uint b, string memory errorMessage) pure internal returns (uint) { - require(b <= a, errorMessage); return a - b; } @@ -144,16 +134,7 @@ contract ExponentialNoError { } function mul_(uint a, uint b) pure internal returns (uint) { - return mul_(a, b, "multiplication overflow"); - } - - function mul_(uint a, uint b, string memory errorMessage) pure internal returns (uint) { - if (a == 0 || b == 0) { - return 0; - } - uint c = a * b; - require(c / a == b, errorMessage); - return c; + return a * b; } function div_(Exp memory a, Exp memory b) pure internal returns (Exp memory) { @@ -181,11 +162,6 @@ contract ExponentialNoError { } function div_(uint a, uint b) pure internal returns (uint) { - return div_(a, b, "divide by zero"); - } - - function div_(uint a, uint b, string memory errorMessage) pure internal returns (uint) { - require(b > 0, errorMessage); return a / b; } diff --git a/contracts/Governance/Comp.sol b/contracts/Governance/Comp.sol index 6494bedce..4d3228baf 100644 --- a/contracts/Governance/Comp.sol +++ b/contracts/Governance/Comp.sol @@ -1,5 +1,5 @@ -pragma solidity ^0.5.16; -pragma experimental ABIEncoderV2; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; contract Comp { /// @notice EIP-20 token name for this token @@ -85,8 +85,8 @@ contract Comp { */ function approve(address spender, uint rawAmount) external returns (bool) { uint96 amount; - if (rawAmount == uint(-1)) { - amount = uint96(-1); + if (rawAmount == type(uint).max) { + amount = type(uint96).max; } else { amount = safe96(rawAmount, "Comp::approve: amount exceeds 96 bits"); } @@ -130,7 +130,7 @@ contract Comp { uint96 spenderAllowance = allowances[src][spender]; uint96 amount = safe96(rawAmount, "Comp::approve: amount exceeds 96 bits"); - if (spender != src && spenderAllowance != uint96(-1)) { + if (spender != src && spenderAllowance != type(uint96).max) { uint96 newAllowance = sub96(spenderAllowance, amount, "Comp::transferFrom: transfer amount exceeds spender allowance"); allowances[src][spender] = newAllowance; @@ -165,7 +165,7 @@ contract Comp { address signatory = ecrecover(digest, v, r, s); require(signatory != address(0), "Comp::delegateBySig: invalid signature"); require(nonce == nonces[signatory]++, "Comp::delegateBySig: invalid nonce"); - require(now <= expiry, "Comp::delegateBySig: signature expired"); + require(block.timestamp <= expiry, "Comp::delegateBySig: signature expired"); return _delegate(signatory, delegatee); } @@ -293,7 +293,7 @@ contract Comp { return a - b; } - function getChainId() internal pure returns (uint) { + function getChainId() internal view returns (uint) { uint256 chainId; assembly { chainId := chainid() } return chainId; diff --git a/contracts/Governance/GovernorAlpha.sol b/contracts/Governance/GovernorAlpha.sol index 6073d0c9c..f1436f76e 100644 --- a/contracts/Governance/GovernorAlpha.sol +++ b/contracts/Governance/GovernorAlpha.sol @@ -1,5 +1,5 @@ -pragma solidity ^0.5.16; -pragma experimental ABIEncoderV2; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; contract GovernorAlpha { /// @notice The name of this contract @@ -18,7 +18,7 @@ contract GovernorAlpha { function votingDelay() public pure returns (uint) { return 1; } // 1 block /// @notice The duration of voting on a proposal, in blocks - function votingPeriod() public pure returns (uint) { return 17280; } // ~3 days in blocks (assuming 15s blocks) + function votingPeriod() virtual public pure returns (uint) { return 17280; } // ~3 days in blocks (assuming 15s blocks) /// @notice The address of the Compound Protocol Timelock TimelockInterface public timelock; @@ -150,23 +150,24 @@ contract GovernorAlpha { uint endBlock = add256(startBlock, votingPeriod()); proposalCount++; - Proposal memory newProposal = Proposal({ - id: proposalCount, - proposer: msg.sender, - eta: 0, - targets: targets, - values: values, - signatures: signatures, - calldatas: calldatas, - startBlock: startBlock, - endBlock: endBlock, - forVotes: 0, - againstVotes: 0, - canceled: false, - executed: false - }); - - proposals[newProposal.id] = newProposal; + uint proposalId = proposalCount; + Proposal storage newProposal = proposals[proposalId]; + // This should never happen but add a check in case. + require(newProposal.id == 0, "GovernorAlpha::propose: ProposalID collsion"); + newProposal.id = proposalId; + newProposal.proposer = msg.sender; + newProposal.eta = 0; + newProposal.targets = targets; + newProposal.values = values; + newProposal.signatures = signatures; + newProposal.calldatas = calldatas; + newProposal.startBlock = startBlock; + newProposal.endBlock = endBlock; + newProposal.forVotes = 0; + newProposal.againstVotes = 0; + newProposal.canceled = false; + newProposal.executed = false; + latestProposalIds[newProposal.proposer] = newProposal.id; emit ProposalCreated(newProposal.id, msg.sender, targets, values, signatures, calldatas, startBlock, endBlock, description); @@ -194,7 +195,7 @@ contract GovernorAlpha { Proposal storage proposal = proposals[proposalId]; proposal.executed = true; for (uint i = 0; i < proposal.targets.length; i++) { - timelock.executeTransaction.value(proposal.values[i])(proposal.targets[i], proposal.values[i], proposal.signatures[i], proposal.calldatas[i], proposal.eta); + timelock.executeTransaction{value: proposal.values[i]}(proposal.targets[i], proposal.values[i], proposal.signatures[i], proposal.calldatas[i], proposal.eta); } emit ProposalExecuted(proposalId); } @@ -309,7 +310,7 @@ contract GovernorAlpha { return a - b; } - function getChainId() internal pure returns (uint) { + function getChainId() internal view returns (uint) { uint chainId; assembly { chainId := chainid() } return chainId; diff --git a/contracts/Governance/GovernorBravoDelegate.sol b/contracts/Governance/GovernorBravoDelegate.sol index 600ae8065..e2496310f 100644 --- a/contracts/Governance/GovernorBravoDelegate.sol +++ b/contracts/Governance/GovernorBravoDelegate.sol @@ -1,5 +1,5 @@ -pragma solidity ^0.5.16; -pragma experimental ABIEncoderV2; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; import "./GovernorBravoInterfaces.sol"; @@ -39,14 +39,14 @@ contract GovernorBravoDelegate is GovernorBravoDelegateStorageV2, GovernorBravoE bytes32 public constant BALLOT_TYPEHASH = keccak256("Ballot(uint256 proposalId,uint8 support)"); /** - * @notice Used to initialize the contract during delegator contructor + * @notice Used to initialize the contract during delegator constructor * @param timelock_ The address of the Timelock * @param comp_ The address of the COMP token * @param votingPeriod_ The initial voting period * @param votingDelay_ The initial voting delay * @param proposalThreshold_ The initial proposal threshold */ - function initialize(address timelock_, address comp_, uint votingPeriod_, uint votingDelay_, uint proposalThreshold_) public { + function initialize(address timelock_, address comp_, uint votingPeriod_, uint votingDelay_, uint proposalThreshold_) virtual public { require(address(timelock) == address(0), "GovernorBravo::initialize: can only initialize once"); require(msg.sender == admin, "GovernorBravo::initialize: admin only"); require(timelock_ != address(0), "GovernorBravo::initialize: invalid timelock address"); @@ -91,24 +91,25 @@ contract GovernorBravoDelegate is GovernorBravoDelegateStorageV2, GovernorBravoE uint endBlock = add256(startBlock, votingPeriod); proposalCount++; - Proposal memory newProposal = Proposal({ - id: proposalCount, - proposer: msg.sender, - eta: 0, - targets: targets, - values: values, - signatures: signatures, - calldatas: calldatas, - startBlock: startBlock, - endBlock: endBlock, - forVotes: 0, - againstVotes: 0, - abstainVotes: 0, - canceled: false, - executed: false - }); - - proposals[newProposal.id] = newProposal; + uint newProposalID = proposalCount; + Proposal storage newProposal = proposals[newProposalID]; + // This should never happen but add a check in case. + require(newProposal.id == 0, "GovernorBravo::propose: ProposalID collsion"); + newProposal.id = newProposalID; + newProposal.proposer = msg.sender; + newProposal.eta = 0; + newProposal.targets = targets; + newProposal.values = values; + newProposal.signatures = signatures; + newProposal.calldatas = calldatas; + newProposal.startBlock = startBlock; + newProposal.endBlock = endBlock; + newProposal.forVotes = 0; + newProposal.againstVotes = 0; + newProposal.abstainVotes = 0; + newProposal.canceled = false; + newProposal.executed = false; + latestProposalIds[newProposal.proposer] = newProposal.id; emit ProposalCreated(newProposal.id, msg.sender, targets, values, signatures, calldatas, startBlock, endBlock, description); @@ -144,7 +145,7 @@ contract GovernorBravoDelegate is GovernorBravoDelegateStorageV2, GovernorBravoE Proposal storage proposal = proposals[proposalId]; proposal.executed = true; for (uint i = 0; i < proposal.targets.length; i++) { - timelock.executeTransaction.value(proposal.values[i])(proposal.targets[i], proposal.values[i], proposal.signatures[i], proposal.calldatas[i], proposal.eta); + timelock.executeTransaction{value: proposal.values[i]}(proposal.targets[i], proposal.values[i], proposal.signatures[i], proposal.calldatas[i], proposal.eta); } emit ProposalExecuted(proposalId); } @@ -168,7 +169,7 @@ contract GovernorBravoDelegate is GovernorBravoDelegateStorageV2, GovernorBravoE require((comp.getPriorVotes(proposal.proposer, sub256(block.number, 1)) < proposalThreshold), "GovernorBravo::cancel: proposer above threshold"); } } - + proposal.canceled = true; for (uint i = 0; i < proposal.targets.length; i++) { timelock.cancelTransaction(proposal.targets[i], proposal.values[i], proposal.signatures[i], proposal.calldatas[i], proposal.eta); @@ -180,7 +181,10 @@ contract GovernorBravoDelegate is GovernorBravoDelegateStorageV2, GovernorBravoE /** * @notice Gets actions of a proposal * @param proposalId the id of the proposal - * @return Targets, values, signatures, and calldatas of the proposal actions + * @return targets of the proposal actions + * @return values of the proposal actions + * @return signatures of the proposal actions + * @return calldatas of the proposal actions */ function getActions(uint proposalId) external view returns (address[] memory targets, uint[] memory values, string[] memory signatures, bytes[] memory calldatas) { Proposal storage p = proposals[proposalId]; @@ -292,7 +296,7 @@ contract GovernorBravoDelegate is GovernorBravoDelegateStorageV2, GovernorBravoE * @return If the account is whitelisted */ function isWhitelisted(address account) public view returns (bool) { - return (whitelistAccountExpirations[account] > now); + return (whitelistAccountExpirations[account] > block.timestamp); } /** @@ -424,9 +428,9 @@ contract GovernorBravoDelegate is GovernorBravoDelegateStorageV2, GovernorBravoE return a - b; } - function getChainIdInternal() internal pure returns (uint) { + function getChainIdInternal() internal view returns (uint) { uint chainId; assembly { chainId := chainid() } return chainId; } -} \ No newline at end of file +} diff --git a/contracts/Governance/GovernorBravoDelegateG1.sol b/contracts/Governance/GovernorBravoDelegateG1.sol index 3b06db622..63aebfb5b 100644 --- a/contracts/Governance/GovernorBravoDelegateG1.sol +++ b/contracts/Governance/GovernorBravoDelegateG1.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.16; +pragma solidity ^0.8.10; pragma experimental ABIEncoderV2; import "./GovernorBravoInterfaces.sol"; @@ -39,7 +39,7 @@ contract GovernorBravoDelegate is GovernorBravoDelegateStorageV1, GovernorBravoE bytes32 public constant BALLOT_TYPEHASH = keccak256("Ballot(uint256 proposalId,uint8 support)"); /** - * @notice Used to initialize the contract during delegator contructor + * @notice Used to initialize the contract during delegator constructor * @param timelock_ The address of the Timelock * @param comp_ The address of the COMP token * @param votingPeriod_ The initial voting period @@ -90,24 +90,24 @@ contract GovernorBravoDelegate is GovernorBravoDelegateStorageV1, GovernorBravoE uint endBlock = add256(startBlock, votingPeriod); proposalCount++; - Proposal memory newProposal = Proposal({ - id: proposalCount, - proposer: msg.sender, - eta: 0, - targets: targets, - values: values, - signatures: signatures, - calldatas: calldatas, - startBlock: startBlock, - endBlock: endBlock, - forVotes: 0, - againstVotes: 0, - abstainVotes: 0, - canceled: false, - executed: false - }); - - proposals[newProposal.id] = newProposal; + Proposal storage newProposal = proposals[proposalCount]; + // This should never happen but add a check in case. + require(newProposal.id == 0, "GovernorBravo::propose: ProposalID collsion"); + newProposal.id = proposalCount; + newProposal.proposer = msg.sender; + newProposal.eta = 0; + newProposal.targets = targets; + newProposal.values = values; + newProposal.signatures = signatures; + newProposal.calldatas = calldatas; + newProposal.startBlock = startBlock; + newProposal.endBlock = endBlock; + newProposal.forVotes = 0; + newProposal.againstVotes = 0; + newProposal.abstainVotes = 0; + newProposal.canceled = false; + newProposal.executed = false; + latestProposalIds[newProposal.proposer] = newProposal.id; emit ProposalCreated(newProposal.id, msg.sender, targets, values, signatures, calldatas, startBlock, endBlock, description); @@ -143,7 +143,7 @@ contract GovernorBravoDelegate is GovernorBravoDelegateStorageV1, GovernorBravoE Proposal storage proposal = proposals[proposalId]; proposal.executed = true; for (uint i = 0; i < proposal.targets.length; i++) { - timelock.executeTransaction.value(proposal.values[i])(proposal.targets[i], proposal.values[i], proposal.signatures[i], proposal.calldatas[i], proposal.eta); + timelock.executeTransaction{value: proposal.values[i]}(proposal.targets[i], proposal.values[i], proposal.signatures[i], proposal.calldatas[i], proposal.eta); } emit ProposalExecuted(proposalId); } @@ -169,7 +169,10 @@ contract GovernorBravoDelegate is GovernorBravoDelegateStorageV1, GovernorBravoE /** * @notice Gets actions of a proposal * @param proposalId the id of the proposal - * @return Targets, values, signatures, and calldatas of the proposal actions + * @return targets of the proposal actions + * @return values of the proposal actions + * @return signatures of the proposal actions + * @return calldatas of the proposal actions */ function getActions(uint proposalId) external view returns (address[] memory targets, uint[] memory values, string[] memory signatures, bytes[] memory calldatas) { Proposal storage p = proposals[proposalId]; @@ -380,9 +383,9 @@ contract GovernorBravoDelegate is GovernorBravoDelegateStorageV1, GovernorBravoE return a - b; } - function getChainIdInternal() internal pure returns (uint) { + function getChainIdInternal() internal view returns (uint) { uint chainId; assembly { chainId := chainid() } return chainId; } -} \ No newline at end of file +} diff --git a/contracts/Governance/GovernorBravoDelegator.sol b/contracts/Governance/GovernorBravoDelegator.sol index a3f123776..e18f817b9 100644 --- a/contracts/Governance/GovernorBravoDelegator.sol +++ b/contracts/Governance/GovernorBravoDelegator.sol @@ -1,5 +1,5 @@ -pragma solidity ^0.5.16; -pragma experimental ABIEncoderV2; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; import "./GovernorBravoInterfaces.sol"; @@ -53,7 +53,7 @@ contract GovernorBravoDelegator is GovernorBravoDelegatorStorage, GovernorBravoE (bool success, bytes memory returnData) = callee.delegatecall(data); assembly { if eq(success, 0) { - revert(add(returnData, 0x20), returndatasize) + revert(add(returnData, 0x20), returndatasize()) } } } @@ -63,17 +63,17 @@ contract GovernorBravoDelegator is GovernorBravoDelegatorStorage, GovernorBravoE * It returns to the external caller whatever the implementation returns * or forwards reverts. */ - function () external payable { + fallback () external payable { // delegate all other functions to current implementation (bool success, ) = implementation.delegatecall(msg.data); assembly { let free_mem_ptr := mload(0x40) - returndatacopy(free_mem_ptr, 0, returndatasize) + returndatacopy(free_mem_ptr, 0, returndatasize()) switch success - case 0 { revert(free_mem_ptr, returndatasize) } - default { return(free_mem_ptr, returndatasize) } + case 0 { revert(free_mem_ptr, returndatasize()) } + default { return(free_mem_ptr, returndatasize()) } } } -} \ No newline at end of file +} diff --git a/contracts/Governance/GovernorBravoInterfaces.sol b/contracts/Governance/GovernorBravoInterfaces.sol index 100fd72dd..0ea3f3cb7 100644 --- a/contracts/Governance/GovernorBravoInterfaces.sol +++ b/contracts/Governance/GovernorBravoInterfaces.sol @@ -1,5 +1,5 @@ -pragma solidity ^0.5.16; -pragma experimental ABIEncoderV2; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; contract GovernorBravoEvents { @@ -193,4 +193,4 @@ interface CompInterface { interface GovernorAlpha { /// @notice The total number of proposals function proposalCount() external returns (uint); -} \ No newline at end of file +} diff --git a/contracts/InterestRateModel.sol b/contracts/InterestRateModel.sol index 72005e6cc..e8319fc99 100644 --- a/contracts/InterestRateModel.sol +++ b/contracts/InterestRateModel.sol @@ -1,10 +1,11 @@ -pragma solidity ^0.5.16; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; /** * @title Compound's InterestRateModel Interface * @author Compound */ -contract InterestRateModel { +abstract contract InterestRateModel { /// @notice Indicator that this is an InterestRateModel contract (for inspection) bool public constant isInterestRateModel = true; @@ -15,7 +16,7 @@ contract InterestRateModel { * @param reserves The total amount of reserves the market has * @return The borrow rate per block (as a percentage, and scaled by 1e18) */ - function getBorrowRate(uint cash, uint borrows, uint reserves) external view returns (uint); + function getBorrowRate(uint cash, uint borrows, uint reserves) virtual external view returns (uint); /** * @notice Calculates the current supply interest rate per block @@ -25,6 +26,5 @@ contract InterestRateModel { * @param reserveFactorMantissa The current reserve factor the market has * @return The supply rate per block (as a percentage, and scaled by 1e18) */ - function getSupplyRate(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) external view returns (uint); - + function getSupplyRate(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) virtual external view returns (uint); } diff --git a/contracts/JumpRateModel.sol b/contracts/JumpRateModel.sol index 7548aef7c..214447582 100644 --- a/contracts/JumpRateModel.sol +++ b/contracts/JumpRateModel.sol @@ -1,17 +1,17 @@ -pragma solidity ^0.5.16; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; import "./InterestRateModel.sol"; -import "./SafeMath.sol"; /** * @title Compound's JumpRateModel Contract * @author Compound */ contract JumpRateModel is InterestRateModel { - using SafeMath for uint; - event NewInterestParams(uint baseRatePerBlock, uint multiplierPerBlock, uint jumpMultiplierPerBlock, uint kink); + uint256 private constant BASE = 1e18; + /** * @notice The approximate number of blocks per year that is assumed by the interest rate model */ @@ -39,15 +39,15 @@ contract JumpRateModel is InterestRateModel { /** * @notice Construct an interest rate model - * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by 1e18) - * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by 1e18) + * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by BASE) + * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by BASE) * @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point * @param kink_ The utilization point at which the jump multiplier is applied */ constructor(uint baseRatePerYear, uint multiplierPerYear, uint jumpMultiplierPerYear, uint kink_) public { - baseRatePerBlock = baseRatePerYear.div(blocksPerYear); - multiplierPerBlock = multiplierPerYear.div(blocksPerYear); - jumpMultiplierPerBlock = jumpMultiplierPerYear.div(blocksPerYear); + baseRatePerBlock = baseRatePerYear / blocksPerYear; + multiplierPerBlock = multiplierPerYear / blocksPerYear; + jumpMultiplierPerBlock = jumpMultiplierPerYear / blocksPerYear; kink = kink_; emit NewInterestParams(baseRatePerBlock, multiplierPerBlock, jumpMultiplierPerBlock, kink); @@ -58,7 +58,7 @@ contract JumpRateModel is InterestRateModel { * @param cash The amount of cash in the market * @param borrows The amount of borrows in the market * @param reserves The amount of reserves in the market (currently unused) - * @return The utilization rate as a mantissa between [0, 1e18] + * @return The utilization rate as a mantissa between [0, BASE] */ function utilizationRate(uint cash, uint borrows, uint reserves) public pure returns (uint) { // Utilization rate is 0 when there are no borrows @@ -66,7 +66,7 @@ contract JumpRateModel is InterestRateModel { return 0; } - return borrows.mul(1e18).div(cash.add(borrows).sub(reserves)); + return borrows * BASE / (cash + borrows - reserves); } /** @@ -74,17 +74,17 @@ contract JumpRateModel is InterestRateModel { * @param cash The amount of cash in the market * @param borrows The amount of borrows in the market * @param reserves The amount of reserves in the market - * @return The borrow rate percentage per block as a mantissa (scaled by 1e18) + * @return The borrow rate percentage per block as a mantissa (scaled by BASE) */ - function getBorrowRate(uint cash, uint borrows, uint reserves) public view returns (uint) { + function getBorrowRate(uint cash, uint borrows, uint reserves) override public view returns (uint) { uint util = utilizationRate(cash, borrows, reserves); if (util <= kink) { - return util.mul(multiplierPerBlock).div(1e18).add(baseRatePerBlock); + return (util * multiplierPerBlock / BASE) + baseRatePerBlock; } else { - uint normalRate = kink.mul(multiplierPerBlock).div(1e18).add(baseRatePerBlock); - uint excessUtil = util.sub(kink); - return excessUtil.mul(jumpMultiplierPerBlock).div(1e18).add(normalRate); + uint normalRate = (kink * multiplierPerBlock / BASE) + baseRatePerBlock; + uint excessUtil = util - kink; + return (excessUtil * jumpMultiplierPerBlock/ BASE) + normalRate; } } @@ -94,12 +94,12 @@ contract JumpRateModel is InterestRateModel { * @param borrows The amount of borrows in the market * @param reserves The amount of reserves in the market * @param reserveFactorMantissa The current reserve factor for the market - * @return The supply rate percentage per block as a mantissa (scaled by 1e18) + * @return The supply rate percentage per block as a mantissa (scaled by BASE) */ - function getSupplyRate(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) public view returns (uint) { - uint oneMinusReserveFactor = uint(1e18).sub(reserveFactorMantissa); + function getSupplyRate(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) override public view returns (uint) { + uint oneMinusReserveFactor = BASE - reserveFactorMantissa; uint borrowRate = getBorrowRate(cash, borrows, reserves); - uint rateToPool = borrowRate.mul(oneMinusReserveFactor).div(1e18); - return utilizationRate(cash, borrows, reserves).mul(rateToPool).div(1e18); + uint rateToPool = borrowRate * oneMinusReserveFactor / BASE; + return utilizationRate(cash, borrows, reserves) * rateToPool / BASE; } } diff --git a/contracts/JumpRateModelV2.sol b/contracts/JumpRateModelV2.sol index 20c62ead7..6a99c0e9a 100644 --- a/contracts/JumpRateModelV2.sol +++ b/contracts/JumpRateModelV2.sol @@ -1,4 +1,5 @@ -pragma solidity ^0.5.16; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; import "./BaseJumpRateModelV2.sol"; import "./InterestRateModel.sol"; @@ -18,10 +19,11 @@ contract JumpRateModelV2 is InterestRateModel, BaseJumpRateModelV2 { * @param reserves The amount of reserves in the market * @return The borrow rate percentage per block as a mantissa (scaled by 1e18) */ - function getBorrowRate(uint cash, uint borrows, uint reserves) external view returns (uint) { + function getBorrowRate(uint cash, uint borrows, uint reserves) override external view returns (uint) { return getBorrowRateInternal(cash, borrows, reserves); } - constructor(uint baseRatePerYear, uint multiplierPerYear, uint jumpMultiplierPerYear, uint kink_, address owner_) - BaseJumpRateModelV2(baseRatePerYear,multiplierPerYear,jumpMultiplierPerYear,kink_,owner_) public {} + constructor(uint baseRatePerYear, uint multiplierPerYear, uint jumpMultiplierPerYear, uint kink_, address owner_) + + BaseJumpRateModelV2(baseRatePerYear,multiplierPerYear,jumpMultiplierPerYear,kink_,owner_) public {} } diff --git a/contracts/LegacyInterestRateModel.sol b/contracts/LegacyInterestRateModel.sol deleted file mode 100644 index e64046607..000000000 --- a/contracts/LegacyInterestRateModel.sol +++ /dev/null @@ -1,30 +0,0 @@ -pragma solidity ^0.5.16; - -/** - * @title Compound's Legacy InterestRateModel Interface - * @author Compound (modified by Arr00) - */ -contract LegacyInterestRateModel { - /// @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 error code (0 = no error), The borrow rate per block (as a percentage, and scaled by 1e18) - */ - function getBorrowRate(uint cash, uint borrows, uint reserves) external view returns (uint,uint); - - /** - * @notice Calculates the current supply 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 - * @param reserveFactorMantissa The current reserve factor the market has - * @return The supply rate per block (as a percentage, and scaled by 1e18) - */ - function getSupplyRate(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) external view returns (uint); - -} diff --git a/contracts/LegacyJumpRateModelV2.sol b/contracts/LegacyJumpRateModelV2.sol deleted file mode 100644 index 8c20e7bfd..000000000 --- a/contracts/LegacyJumpRateModelV2.sol +++ /dev/null @@ -1,27 +0,0 @@ -pragma solidity ^0.5.16; - -import "./BaseJumpRateModelV2.sol"; -import "./LegacyInterestRateModel.sol"; - - -/** - * @title Compound's JumpRateModel Contract V2 for legacy cTokens - * @author Arr00 - * @notice Supports only legacy cTokens - */ -contract LegacyJumpRateModelV2 is LegacyInterestRateModel, BaseJumpRateModelV2 { - - /** - * @notice Calculates the current borrow rate per block, with the error code expected by the market - * @param cash The amount of cash in the market - * @param borrows The amount of borrows in the market - * @param reserves The amount of reserves in the market - * @return (Error, The borrow rate percentage per block as a mantissa (scaled by 1e18)) - */ - function getBorrowRate(uint cash, uint borrows, uint reserves) external view returns (uint, uint) { - return (0,getBorrowRateInternal(cash, borrows, reserves)); - } - - constructor(uint baseRatePerYear, uint multiplierPerYear, uint jumpMultiplierPerYear, uint kink_, address owner_) - BaseJumpRateModelV2(baseRatePerYear,multiplierPerYear,jumpMultiplierPerYear,kink_,owner_) public {} -} diff --git a/contracts/Lens/CompoundLens.sol b/contracts/Lens/CompoundLens.sol index feda52478..f7030948e 100644 --- a/contracts/Lens/CompoundLens.sol +++ b/contracts/Lens/CompoundLens.sol @@ -1,5 +1,5 @@ -pragma solidity ^0.5.16; -pragma experimental ABIEncoderV2; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; import "../CErc20.sol"; import "../CToken.sol"; diff --git a/contracts/Maximillion.sol b/contracts/Maximillion.sol index a511c97a9..6819e8fa4 100644 --- a/contracts/Maximillion.sol +++ b/contracts/Maximillion.sol @@ -1,4 +1,5 @@ -pragma solidity ^0.5.16; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; import "./CEther.sol"; @@ -38,10 +39,10 @@ contract Maximillion { uint received = msg.value; uint borrows = cEther_.borrowBalanceCurrent(borrower); if (received > borrows) { - cEther_.repayBorrowBehalf.value(borrows)(borrower); - msg.sender.transfer(received - borrows); + cEther_.repayBorrowBehalf{value: borrows}(borrower); + payable(msg.sender).transfer(received - borrows); } else { - cEther_.repayBorrowBehalf.value(received)(borrower); + cEther_.repayBorrowBehalf{value: received}(borrower); } } } diff --git a/contracts/PriceOracle.sol b/contracts/PriceOracle.sol index 27bcc99e6..f58518061 100644 --- a/contracts/PriceOracle.sol +++ b/contracts/PriceOracle.sol @@ -1,8 +1,9 @@ -pragma solidity ^0.5.16; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; import "./CToken.sol"; -contract PriceOracle { +abstract contract PriceOracle { /// @notice Indicator that this is a PriceOracle contract (for inspection) bool public constant isPriceOracle = true; @@ -12,5 +13,5 @@ contract PriceOracle { * @return The underlying asset price mantissa (scaled by 1e18). * Zero means the price is unavailable. */ - function getUnderlyingPrice(CToken cToken) external view returns (uint); + function getUnderlyingPrice(CToken cToken) virtual external view returns (uint); } diff --git a/contracts/Reservoir.sol b/contracts/Reservoir.sol index 6c7cd2d62..9bf7784d3 100644 --- a/contracts/Reservoir.sol +++ b/contracts/Reservoir.sol @@ -1,4 +1,5 @@ -pragma solidity ^0.5.16; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; /** * @title Reservoir Contract @@ -68,7 +69,8 @@ contract Reservoir { /* Internal helper functions for safe math */ function add(uint a, uint b, string memory errorMessage) internal pure returns (uint) { - uint c = a + b; + uint c; + unchecked { c = a + b; } require(c >= a, errorMessage); return c; } @@ -83,7 +85,8 @@ contract Reservoir { if (a == 0) { return 0; } - uint c = a * b; + uint c; + unchecked { c = a * b; } require(c / a == b, errorMessage); return c; } diff --git a/contracts/SafeMath.sol b/contracts/SafeMath.sol index b27c9962d..ed474c7c3 100644 --- a/contracts/SafeMath.sol +++ b/contracts/SafeMath.sol @@ -1,4 +1,5 @@ -pragma solidity ^0.5.16; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; // From https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/math/Math.sol // Subject to the MIT license. @@ -26,7 +27,8 @@ library SafeMath { * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; + uint256 c; + unchecked { c = a + b; } require(c >= a, "SafeMath: addition overflow"); return c; @@ -41,7 +43,8 @@ library SafeMath { * - Addition cannot overflow. */ function add(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { - uint256 c = a + b; + uint256 c; + unchecked { c = a + b; } require(c >= a, errorMessage); return c; @@ -90,7 +93,8 @@ library SafeMath { return 0; } - uint256 c = a * b; + uint256 c; + unchecked { c = a * b; } require(c / a == b, "SafeMath: multiplication overflow"); return c; @@ -112,7 +116,8 @@ library SafeMath { return 0; } - uint256 c = a * b; + uint256 c; + unchecked { c = a * b; } require(c / a == b, errorMessage); return c; diff --git a/contracts/SimplePriceOracle.sol b/contracts/SimplePriceOracle.sol index db9658f37..10b1d576f 100644 --- a/contracts/SimplePriceOracle.sol +++ b/contracts/SimplePriceOracle.sol @@ -1,4 +1,5 @@ -pragma solidity ^0.5.16; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; import "./PriceOracle.sol"; import "./CErc20.sol"; @@ -17,7 +18,7 @@ contract SimplePriceOracle is PriceOracle { return asset; } - function getUnderlyingPrice(CToken cToken) public view returns (uint) { + function getUnderlyingPrice(CToken cToken) public override view returns (uint) { return prices[_getUnderlyingAddress(cToken)]; } diff --git a/contracts/Timelock.sol b/contracts/Timelock.sol index 5cda36d2b..69dcf3c1c 100644 --- a/contracts/Timelock.sol +++ b/contracts/Timelock.sol @@ -1,4 +1,5 @@ -pragma solidity ^0.5.16; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; import "./SafeMath.sol"; @@ -31,7 +32,7 @@ contract Timelock { delay = delay_; } - function() external payable { } + fallback() external payable { } function setDelay(uint delay_) public { require(msg.sender == address(this), "Timelock::setDelay: Call must come from Timelock."); @@ -96,7 +97,7 @@ contract Timelock { } // solium-disable-next-line security/no-call-value - (bool success, bytes memory returnData) = target.call.value(value)(callData); + (bool success, bytes memory returnData) = target.call{value: value}(callData); require(success, "Timelock::executeTransaction: Transaction execution reverted."); emit ExecuteTransaction(txHash, target, value, signature, data, eta); @@ -108,4 +109,4 @@ contract Timelock { // solium-disable-next-line security/no-block-members return block.timestamp; } -} \ No newline at end of file +} diff --git a/contracts/Unitroller.sol b/contracts/Unitroller.sol index 94765861c..0ecd22cec 100644 --- a/contracts/Unitroller.sol +++ b/contracts/Unitroller.sol @@ -1,4 +1,5 @@ -pragma solidity ^0.5.16; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; import "./ErrorReporter.sol"; import "./ComptrollerStorage.sol"; @@ -132,17 +133,17 @@ contract Unitroller is UnitrollerAdminStorage, ComptrollerErrorReporter { * It returns to the external caller whatever the implementation returns * or forwards reverts. */ - function () payable external { + fallback() payable external { // delegate all other functions to current implementation (bool success, ) = comptrollerImplementation.delegatecall(msg.data); assembly { let free_mem_ptr := mload(0x40) - returndatacopy(free_mem_ptr, 0, returndatasize) + returndatacopy(free_mem_ptr, 0, returndatasize()) switch success - case 0 { revert(free_mem_ptr, returndatasize) } - default { return(free_mem_ptr, returndatasize) } + case 0 { revert(free_mem_ptr, returndatasize()) } + default { return(free_mem_ptr, returndatasize()) } } } } diff --git a/contracts/WhitePaperInterestRateModel.sol b/contracts/WhitePaperInterestRateModel.sol index 6fb197778..59721b5b8 100644 --- a/contracts/WhitePaperInterestRateModel.sol +++ b/contracts/WhitePaperInterestRateModel.sol @@ -1,7 +1,7 @@ -pragma solidity ^0.5.16; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; import "./InterestRateModel.sol"; -import "./SafeMath.sol"; /** * @title Compound's WhitePaperInterestRateModel Contract @@ -9,10 +9,10 @@ import "./SafeMath.sol"; * @notice The parameterized model described in section 2.4 of the original Compound Protocol whitepaper */ contract WhitePaperInterestRateModel is InterestRateModel { - using SafeMath for uint; - event NewInterestParams(uint baseRatePerBlock, uint multiplierPerBlock); + uint256 private constant BASE = 1e18; + /** * @notice The approximate number of blocks per year that is assumed by the interest rate model */ @@ -30,12 +30,12 @@ contract WhitePaperInterestRateModel is InterestRateModel { /** * @notice Construct an interest rate model - * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by 1e18) - * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by 1e18) + * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by BASE) + * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by BASE) */ constructor(uint baseRatePerYear, uint multiplierPerYear) public { - baseRatePerBlock = baseRatePerYear.div(blocksPerYear); - multiplierPerBlock = multiplierPerYear.div(blocksPerYear); + baseRatePerBlock = baseRatePerYear / blocksPerYear; + multiplierPerBlock = multiplierPerYear / blocksPerYear; emit NewInterestParams(baseRatePerBlock, multiplierPerBlock); } @@ -45,7 +45,7 @@ contract WhitePaperInterestRateModel is InterestRateModel { * @param cash The amount of cash in the market * @param borrows The amount of borrows in the market * @param reserves The amount of reserves in the market (currently unused) - * @return The utilization rate as a mantissa between [0, 1e18] + * @return The utilization rate as a mantissa between [0, BASE] */ function utilizationRate(uint cash, uint borrows, uint reserves) public pure returns (uint) { // Utilization rate is 0 when there are no borrows @@ -53,7 +53,7 @@ contract WhitePaperInterestRateModel is InterestRateModel { return 0; } - return borrows.mul(1e18).div(cash.add(borrows).sub(reserves)); + return borrows * BASE / (cash + borrows - reserves); } /** @@ -61,11 +61,11 @@ contract WhitePaperInterestRateModel is InterestRateModel { * @param cash The amount of cash in the market * @param borrows The amount of borrows in the market * @param reserves The amount of reserves in the market - * @return The borrow rate percentage per block as a mantissa (scaled by 1e18) + * @return The borrow rate percentage per block as a mantissa (scaled by BASE) */ - function getBorrowRate(uint cash, uint borrows, uint reserves) public view returns (uint) { + function getBorrowRate(uint cash, uint borrows, uint reserves) override public view returns (uint) { uint ur = utilizationRate(cash, borrows, reserves); - return ur.mul(multiplierPerBlock).div(1e18).add(baseRatePerBlock); + return (ur * multiplierPerBlock / BASE) + baseRatePerBlock; } /** @@ -74,12 +74,12 @@ contract WhitePaperInterestRateModel is InterestRateModel { * @param borrows The amount of borrows in the market * @param reserves The amount of reserves in the market * @param reserveFactorMantissa The current reserve factor for the market - * @return The supply rate percentage per block as a mantissa (scaled by 1e18) + * @return The supply rate percentage per block as a mantissa (scaled by BASE) */ - function getSupplyRate(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) public view returns (uint) { - uint oneMinusReserveFactor = uint(1e18).sub(reserveFactorMantissa); + function getSupplyRate(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) override public view returns (uint) { + uint oneMinusReserveFactor = BASE - reserveFactorMantissa; uint borrowRate = getBorrowRate(cash, borrows, reserves); - uint rateToPool = borrowRate.mul(oneMinusReserveFactor).div(1e18); - return utilizationRate(cash, borrows, reserves).mul(rateToPool).div(1e18); + uint rateToPool = borrowRate * oneMinusReserveFactor / BASE; + return utilizationRate(cash, borrows, reserves) * rateToPool / BASE; } } diff --git a/gasCosts.json b/gasCosts.json index ba5e9ab82..23b73a0a6 100644 --- a/gasCosts.json +++ b/gasCosts.json @@ -1,217 +1,204 @@ { "first mint": { - "fee": 126183, + "fee": 124570, "opcodes": {} }, "second mint": { - "fee": 86711, + "fee": 84516, "opcodes": { - "PUSH1 @ 3": 351, - "MSTORE @ 3": 159, + "PUSH1 @ 3": 287, + "MSTORE @ 3": 126, "PUSH1 @ 12": 1, "CALLDATASIZE @ 3": 18, "LT @ 2": 9, - "PUSH2 @ 3": 321, - "JUMPI @ 3": 196, - "PUSH1 @ 10": 17, - "CALLDATALOAD @ 3": 18, + "PUSH2 @ 3": 302, + "JUMPI @ 3": 137, + "PUSH1 @ 10": 12, + "CALLDATALOAD @ 3": 22, "SHR @ 3": 9, - "DUP1 @ 3": 172, - "PUSH4 @ 3": 58, - "GT @ 3": 61, - "DUP1 @ 10": 17, - "JUMPDEST @ 10": 154, - "DUP1 @ 1": 12, - "EQ @ 3": 20, + "DUP1 @ 3": 107, + "PUSH4 @ 3": 48, + "GT @ 3": 40, + "DUP1 @ 10": 12, + "JUMPDEST @ 10": 110, + "DUP1 @ 1": 23, + "EQ @ 3": 24, "CALLVALUE @ 1": 1, - "DUP1 @ 2": 20, - "ISZERO @ 3": 87, - "POP @ 1": 47, - "PUSH2 @ 2": 13, - "SUB @ 2": 9, - "DUP2 @ 3": 197, - "LT @ 3": 27, - "CALLDATALOAD @ 2": 6, - "JUMP @ 3": 126, - "JUMPDEST @ 8": 172, - "PUSH1 @ 1": 135, - "MLOAD @ 3": 97, - "DUP3 @ 3": 87, - "ADD @ 3": 134, - "DUP5 @ 3": 26, - "SWAP1 @ 3": 199, - "DUP3 @ 15": 1, - "DUP4 @ 3": 79, - "SUB @ 3": 52, - "SWAP2 @ 3": 99, - "SHL @ 3": 35, - "AND @ 3": 44, - "OR @ 3": 3, + "DUP1 @ 2": 16, + "ISZERO @ 3": 88, + "POP @ 1": 66, + "PUSH2 @ 2": 7, + "PUSH1 @ 2": 58, + "JUMP @ 3": 145, + "JUMPDEST @ 8": 203, + "PUSH1 @ 1": 128, + "DUP3 @ 3": 105, + "DUP5 @ 3": 53, + "SUB @ 3": 67, + "SLT @ 3": 16, + "CALLDATALOAD @ 2": 2, + "SWAP2 @ 3": 86, + "SWAP1 @ 3": 195, + "POP @ 3": 106, + "JUMP @ 2": 57, + "PUSH2 @ 1": 25, + "DUP4 @ 3": 30, + "MLOAD @ 3": 82, + "ADD @ 3": 102, + "DUP2 @ 3": 118, + "PUSH1 @ 15": 1, + "NOT @ 3": 24, + "SHL @ 3": 40, + "AND @ 3": 53, + "OR @ 3": 2, "SLOAD @ 3": 27, - "PUSH1 @ 800": 21, - "JUMPDEST @ 3": 2, - "PUSH1 @ 6": 13, - "NOT @ 3": 5, - "SWAP3 @ 3": 58, - "EXP @ 3": 1, - "SUB @ 60": 1, - "AND @ 6": 1, - "DUP6 @ 3": 23, - "POP @ 3": 207, - "POP @ 2": 122, - "SWAP1 @ 2": 48, - "ADD @ 2": 2, - "PUSH1 @ 2": 71, + "PUSH1 @ 800": 22, + "DUP8 @ 3": 10, + "JUMPDEST @ 3": 4, + "DUP4 @ 1": 5, + "LT @ 3": 9, + "DUP2 @ 10": 2, + "PUSH1 @ 6": 17, + "POP @ 2": 133, + "SWAP2 @ 1": 14, + "SWAP3 @ 3": 26, + "DUP6 @ 3": 33, "GAS @ 3": 1, "DELEGATECALL @ 2": 1, - "PUSH1 @ 312832": 1, + "PUSH1 @ 312831": 1, "CALLVALUE @ 12": 8, - "PUSH2 @ 1": 29, - "DUP2 @ 800": 6, "SSTORE @ 3": 11, "PUSH2 @ 5000": 1, - "SWAP1 @ 800": 4, + "SWAP1 @ 800": 2, "ADDRESS @ 9": 1, - "SWAP1 @ 6": 6, - "DUP7 @ 3": 32, + "DUP7 @ 3": 17, "EXTCODESIZE @ 3": 7, "ISZERO @ 700": 7, "GAS @ 2": 7, "STATICCALL @ 2": 5, - "PUSH1 @ 307781": 1, + "PUSH1 @ 307782": 1, + "SWAP4 @ 1": 17, "SHA3 @ 3": 15, "SLOAD @ 42": 9, - "MLOAD @ 9": 5, + "DUP2 @ 800": 5, + "PUSH1 @ 9": 6, "RETURN @ 3": 9, - "ISZERO @ -307081": 1, + "ISZERO @ -307082": 1, "RETURNDATASIZE @ 3": 10, - "MLOAD @ 2": 8, - "DUP8 @ 3": 18, - "SWAP6 @ 3": 9, - "SWAP7 @ 3": 6, - "SWAP4 @ 2": 17, - "SWAP5 @ 3": 6, + "DUP2 @ 2": 7, + "MLOAD @ 2": 7, + "SWAP1 @ 2": 7, + "SWAP5 @ 6": 1, + "SWAP6 @ 3": 3, + "SWAP3 @ 2": 7, "SWAP4 @ 3": 13, - "PUSH1 @ 307686": 1, - "POP @ 10": 8, - "SWAP4 @ 1": 13, - "JUMP @ 2": 46, - "SWAP1 @ 1": 34, - "PUSH2 @ 800": 5, - "PUSH8 @ 3": 8, - "DUP7 @ 800": 1, - "SWAP3 @ 1": 24, - "PUSH1 @ 9": 1, - "PUSH32 @ 3": 4, - "POP @ 6": 9, - "DIV @ 1": 6, - "SWAP6 @ 5": 1, - "JUMPDEST @ 2": 13, - "SWAP2 @ 1": 4, - "MLOAD @ 6": 3, - "ISZERO @ -306986": 1, + "PUSH1 @ 307684": 1, + "POP @ 10": 1, + "SWAP1 @ 1": 25, + "PUSH8 @ 800": 1, + "DUP4 @ 800": 2, + "DIV @ 3": 7, + "DUP4 @ 5": 7, + "MUL @ 2": 7, + "SWAP1 @ 5": 13, + "DIV @ 2": 6, + "ADD @ 2": 8, + "JUMPDEST @ 2": 2, + "ISZERO @ -306984": 1, "PUSH6 @ 2": 1, - "DUP10 @ 3": 2, - "DUP2 @ 2": 6, - "SWAP3 @ 2": 24, - "EQ @ 1": 26, + "DUP10 @ 3": 3, + "SUB @ 2": 5, + "DUP4 @ 2": 2, + "DUP9 @ 3": 5, + "SWAP4 @ 6": 4, + "PUSH8 @ 3": 5, + "SWAP3 @ 1": 6, + "SWAP5 @ 1": 3, + "POP @ 6": 1, + "DUP5 @ 2": 2, "DUP11 @ 3": 2, - "DUP8 @ 2": 1, - "SWAP8 @ 3": 7, - "SWAP5 @ 2": 2, - "DUP13 @ 3": 3, - "MLOAD @ 1": 4, - "DIV @ 3": 4, - "SWAP1 @ 5": 4, - "DUP6 @ 2": 2, - "DUP7 @ 1": 2, - "SWAP2 @ 2": 8, - "DUP12 @ 3": 1, + "DUP5 @ 1": 2, + "SWAP6 @ 1": 4, + "SWAP5 @ 3": 6, "DUP15 @ 3": 1, - "PUSH1 @ 5000": 3, + "PUSH1 @ 5000": 2, "DUP14 @ 3": 1, - "DUP1 @ 6": 1, + "SWAP1 @ 6": 2, + "PUSH32 @ 2": 1, "LOG1 @ 3": 2, "PUSH1 @ 1774": 1, - "SWAP15 @ 3": 1, + "SWAP14 @ 3": 1, "CALLER @ 3": 1, - "ADDRESS @ 3": 4, + "ADDRESS @ 3": 5, "CALL @ 2": 2, - "PUSH1 @ 307404": 1, + "PUSH1 @ 307417": 1, "JUMPDEST @ 800": 1, - "SWAP5 @ 1": 2, - "ISZERO @ -306704": 1, + "ISZERO @ -306717": 1, "EQ @ 800": 1, - "PUSH1 @ 7": 1, - "ADDRESS @ 6": 2, - "PUSH1 @ 307278": 1, - "ISZERO @ -306578": 1, - "DUP4 @ 1": 3, - "MUL @ 3": 3, - "DUP4 @ 5": 3, - "EQ @ 5": 3, - "DUP9 @ 3": 7, - "SWAP2 @ 5": 2, - "SWAP9 @ 3": 2, - "SWAP6 @ 2": 2, - "PUSH1 @ 307176": 1, - "ISZERO @ -306476": 1, + "PUSH1 @ 307290": 1, + "ISZERO @ -306590": 1, + "ADDRESS @ 6": 1, + "PUSH1 @ 307200": 1, + "ISZERO @ -306500": 1, "SWAP2 @ 7": 1, - "PUSH1 @ 307132": 1, + "PUSH1 @ 307152": 1, "PUSH22 @ 9": 1, "CALLER @ 42": 2, - "DUP3 @ 2": 3, - "DUP5 @ 2": 1, - "SWAP5 @ 42": 2, + "DUP3 @ 2": 2, + "PUSH2 @ 800": 5, + "SWAP5 @ 42": 1, "DUP4 @ 5000": 1, "PUSH20 @ 6": 1, "SWAP3 @ 6": 1, "SWAP6 @ 42": 1, "DUP5 @ 5000": 1, "PUSH16 @ 6": 1, - "SWAP4 @ 6": 1, - "DUP1 @ 5000": 1, + "SWAP5 @ 2": 1, + "SWAP4 @ 42": 1, + "SWAP2 @ 5000": 1, + "PUSH32 @ 3": 2, "LOG3 @ 3": 2, - "POP @ 1756": 1, - "ISZERO @ -306432": 1, + "POP @ 1756": 2, + "ISZERO @ -306452": 1, "RETURNDATACOPY @ 3": 2, - "PUSH1 @ 306755": 1, - "ISZERO @ -306055": 1, - "DUP3 @ 800": 1, - "SWAP4 @ 42": 1, - "SWAP5 @ 6": 1, - "DUP3 @ 6": 1, + "PUSH1 @ 306770": 1, + "ISZERO @ -306070": 1, + "SWAP8 @ 1": 1, + "SWAP7 @ 3": 1, + "SWAP2 @ 42": 1, + "MLOAD @ 5000": 1, "PUSH1 @ 1518": 1, "CODECOPY @ 3": 1, "DUP2 @ 6": 1, - "PUSH1 @ 1756": 1, - "SWAP2 @ -312132": 1, + "JUMP @ 800": 1, + "SWAP2 @ -312131": 1, "RETURNDATASIZE @ 2": 1, - "PUSH2 @ 6": 1 + "PUSH2 @ 6": 1, + "SWAP2 @ 2": 2 } }, "second mint, no interest accrued": { - "fee": 62679, + "fee": 61306, "opcodes": {} }, "redeem": { - "fee": 96782, + "fee": 95058, "opcodes": {} }, "unitroller-g6 second mint with comp accrued": { - "fee": 140079, + "fee": 138680, "opcodes": {} }, "unitroller-g6 claim comp": { - "fee": 142304, + "fee": 142459, "opcodes": {} }, "unitroller second mint with comp accrued": { - "fee": 118632, + "fee": 116271, "opcodes": {} }, "unitroller claim comp": { - "fee": 157456, + "fee": 155422, "opcodes": {} } } \ No newline at end of file diff --git a/package.json b/package.json index d8c7b6f74..0dc2c0f62 100644 --- a/package.json +++ b/package.json @@ -23,11 +23,13 @@ "bignumber.js": "9.0.0", "jest-diff": "^26.4.2", "jest-junit": "^11.1.0", - "solium": "^1.2.5", + "prettier": "^1.19.0", + "solhint": "^3.3.7", "solparse": "^2.2.8" }, "dependencies": { - "eth-saddle": "^0.1.21" + "@solidity-parser/parser": "^0.13.2", + "eth-saddle": "^0.1.25" }, "resolutions": { "scrypt.js": "https://registry.npmjs.org/@compound-finance/ethereumjs-wallet/-/ethereumjs-wallet-0.6.3.tgz", diff --git a/saddle.config.js b/saddle.config.js index 8fcc3df37..5eac9058a 100644 --- a/saddle.config.js +++ b/saddle.config.js @@ -10,7 +10,7 @@ module.exports = { shell: process.env['SADDLE_SHELL'] || '/bin/bash' }, // build_dir: ".build", // Directory to place built contracts - extra_build_files: [process.env['EXTRA_BUILD_FILES'] || 'remote/*.json'], // Additional build files to deep merge + extra_build_files: [process.env['EXTRA_BUILD_FILES'] || 'remote/*.json', 'tests/LegacyBuilds/*.json'], // Additional build files to deep merge // coverage_dir: "coverage", // Directory to place coverage files // coverage_ignore: [], // List of files to ignore for coverage contracts: process.env['SADDLE_CONTRACTS'] || "{contracts,contracts/**,tests/Contracts}/*.sol", diff --git a/scenario/package.json b/scenario/package.json index 295929df2..dbd88aa8d 100644 --- a/scenario/package.json +++ b/scenario/package.json @@ -21,7 +21,7 @@ }, "dependencies": { "bignumber.js": "9.0.0", - "eth-saddle": "^0.1.21", + "eth-saddle": "^0.1.25", "ethers": "^5.0.8", "immutable": "^4.0.0-rc.12", "truffle-flattener": "^1.4.4", diff --git a/scenario/script/tsc b/scenario/script/tsc index 638fcab11..cdf02b20e 100755 --- a/scenario/script/tsc +++ b/scenario/script/tsc @@ -9,7 +9,7 @@ cache_file="$scenario_dir/.tscache" shasumVersion="$(shasum -v)" inflectionVersion="6.01" -if [ "$(printf '%s\n' "$inflectionVersion" "$shasumVersion" | sort -V | head -n1)" = "$inflectionVersion" ]; then +if [ "$(printf '%s\n' "$inflectionVersion" "$shasumVersion" | sort -V | head -n1)" = "$inflectionVersion" ]; then checksum="$(echo $scenario_dir/src/{*,**/}*.* | xargs shasum -U | shasum -U | cut -d' ' -f 1)" else checksum="$(echo $scenario_dir/src/{*,**/}*.* | xargs shasum -p | shasum -p | cut -d' ' -f 1)" diff --git a/scenario/src/ErrorReporter.ts b/scenario/src/ErrorReporter.ts index 820b30aa1..8fd7367a6 100644 --- a/scenario/src/ErrorReporter.ts +++ b/scenario/src/ErrorReporter.ts @@ -1,9 +1,12 @@ + +import { utils } from 'ethers'; import {ComptrollerErr, TokenErr} from './ErrorReporterConstants'; export interface ErrorReporter { getError(error: any): string | null getInfo(info: any): string | null getDetail(error: any, detail: number): string + getEncodedCustomError(errorName: string, args: unknown[]): string | null } class NoErrorReporterType implements ErrorReporter { @@ -18,6 +21,10 @@ class NoErrorReporterType implements ErrorReporter { getDetail(error: any, detail: number): string { return detail.toString(); } + + getEncodedCustomError(errorName: string, args: unknown[]): string | null { + return null + } } class CTokenErrorReporterType implements ErrorReporter { @@ -49,6 +56,14 @@ class CTokenErrorReporterType implements ErrorReporter { return detail.toString(); } + + getEncodedCustomError(errorName: string, args: unknown[]): string | null { + try { + return TokenErr.CustomErrors.encodeErrorResult(errorName, args) + } catch (err) { + return null + } + } } class ComptrollerErrorReporterType implements ErrorReporter { @@ -81,6 +96,14 @@ class ComptrollerErrorReporterType implements ErrorReporter { return detail.toString(); } + + getEncodedCustomError(errorName: string, args: unknown[]): string | null { + try { + return ComptrollerErr.CustomErrors.encodeErrorResult(errorName, args) + } catch (err) { + return null + } + } } export function formatResult(errorReporter: ErrorReporter, result: any): string { diff --git a/scenario/src/ErrorReporterConstants.ts b/scenario/src/ErrorReporterConstants.ts index ebfe7ce3a..fa4e13d7e 100644 --- a/scenario/src/ErrorReporterConstants.ts +++ b/scenario/src/ErrorReporterConstants.ts @@ -1,7 +1,8 @@ - +import * as ethers from 'ethers' interface ErrorReporterEnum { Error: string[] FailureInfo: string[] + CustomErrors?: string[] } interface ErrorTypes { @@ -9,6 +10,7 @@ interface ErrorTypes { FailureInfo: {[name: string]: number} ErrorInv: {[code: number]: string} FailureInfoInv: {[code: number]: string} + CustomErrors: ethers.utils.Interface } const ComptrollerErrorReporter = { @@ -160,6 +162,59 @@ const TokenErrorReporter = { 'ADD_RESERVES_ACCRUE_INTEREST_FAILED', 'ADD_RESERVES_FRESH_CHECK', 'ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE' + ], + + CustomErrors: [ + "error TransferComptrollerRejection(uint256 errorCode)", + "error TransferNotAllowed()", + "error TransferNotEnough()", + "error TransferTooMuch()", + + "error MintComptrollerRejection(uint256 errorCode)", + "error MintFreshnessCheck()", + + "error RedeemComptrollerRejection(uint256 errorCode)", + "error RedeemFreshnessCheck()", + "error RedeemTransferOutNotPossible()", + + "error BorrowComptrollerRejection(uint256 errorCode)", + "error BorrowFreshnessCheck()", + "error BorrowCashNotAvailable()", + + "error RepayBorrowComptrollerRejection(uint256 errorCode)", + "error RepayBorrowFreshnessCheck()", + + "error LiquidateComptrollerRejection(uint256 errorCode)", + "error LiquidateFreshnessCheck()", + "error LiquidateCollateralFreshnessCheck()", + "error LiquidateAccrueBorrowInterestFailed(uint256 errorCode)", + "error LiquidateAccrueCollateralInterestFailed(uint256 errorCode)", + "error LiquidateLiquidatorIsBorrower()", + "error LiquidateCloseAmountIsZero()", + "error LiquidateCloseAmountIsUintMax()", + "error LiquidateRepayBorrowFreshFailed(uint256 errorCode)", + + "error LiquidateSeizeComptrollerRejection(uint256 errorCode)", + "error LiquidateSeizeLiquidatorIsBorrower()", + + "error AcceptAdminPendingAdminCheck()", + + "error SetComptrollerOwnerCheck()", + "error SetPendingAdminOwnerCheck()", + + "error SetReserveFactorAdminCheck()", + "error SetReserveFactorFreshCheck()", + "error SetReserveFactorBoundsCheck()", + + "error AddReservesFactorFreshCheck(uint256 actualAddAmount)", + + "error ReduceReservesAdminCheck()", + "error ReduceReservesFreshCheck()", + "error ReduceReservesCashNotAvailable()", + "error ReduceReservesCashValidation()", + + "error SetInterestRateModelOwnerCheck()", + "error SetInterestRateModelFreshCheck();", ] }; @@ -179,7 +234,9 @@ function parseEnum(reporterEnum: ErrorReporterEnum): ErrorTypes { FailureInfoInv[i] = entry; }); - return {Error, ErrorInv, FailureInfo, FailureInfoInv}; + const CustomErrors = new ethers.utils.Interface(reporterEnum.CustomErrors || []) + + return {Error, ErrorInv, FailureInfo, FailureInfoInv, CustomErrors}; } export const ComptrollerErr = parseEnum(ComptrollerErrorReporter); diff --git a/scenario/src/Event/AssertionEvent.ts b/scenario/src/Event/AssertionEvent.ts index 4934a900f..c660ec7f3 100644 --- a/scenario/src/Event/AssertionEvent.ts +++ b/scenario/src/Event/AssertionEvent.ts @@ -1,7 +1,7 @@ import { Event } from '../Event'; import { fail, World } from '../World'; import { getCoreValue } from '../CoreValue'; -import { Failure, InvokationRevertFailure } from '../Invokation'; +import { Failure, InvokationRevertCustomError, InvokationRevertFailure } from '../Invokation'; import { getEventV, getMapV, @@ -20,6 +20,7 @@ import { Value } from '../Value'; import { Arg, View, processCommandEvent } from '../Command'; +import { rawValues } from '../Utils'; async function assertApprox(world: World, given: NumberV, expected: NumberV, tolerance: NumberV): Promise { if (Math.abs(Number(expected.sub(given).div(expected).val)) > Number(tolerance.val)) { @@ -120,6 +121,44 @@ async function assertRevertFailure(world: World, err: string, message: string): return world; } +async function assertRevertCustomError(world: World, err: string, args: unknown[]): Promise { + if (world.network === 'coverage') { // coverage doesn't have detailed message, thus no revert failures + return await assertRevert(world, "revert"); + } + + if (!world.lastInvokation) { + return fail(world, `Expected revert failure, but missing any invokations.`); + } + + if (world.lastInvokation.success()) { + return fail(world, `Expected revert failure, but last invokation was successful with result ${JSON.stringify(world.lastInvokation.value)}.`); + } + + if (world.lastInvokation.failures.length > 0) { + return fail(world, `Expected revert failure, but got ${world.lastInvokation.failures.toString()}.`); + } + + if (!world.lastInvokation.error) { + throw new Error(`Invokation requires success, failure or error, got: ${world.lastInvokation.toString()}`); + } + + if (!(world.lastInvokation.error instanceof InvokationRevertCustomError)) { + throw new Error(`Invokation error mismatch, expected revert custom error: "${err}", got: "${world.lastInvokation.error.toString()}"`); + } + + const expectedResult = world.lastInvokation.errorReporter.getEncodedCustomError(err, args); + + if (!expectedResult) { + throw new Error(`Expected revert with custom error, but custom error ${err} not found`) + } + + if (Object.values(world.lastInvokation.error.errorResults).findIndex(v => v.error === 'revert' && v.return === expectedResult) < 0) { + throw new Error(`Invokation error mismatch, expected revert custom error: err=${err}, args="${args.join(',')}", got: "${world.lastInvokation.error.toString()}"`); + } + + return world; +} + async function assertError(world: World, message: string): Promise { if (!world.lastInvokation) { return fail(world, `Expected revert, but missing any invokations.`); @@ -401,6 +440,20 @@ export function assertionCommands() { (world, { error, message }) => assertRevertFailure(world, error.val, message.val) ), + new View<{ error: StringV, args: StringV[] }>(` + #### RevertCustomError + + * "RevertCustomError error: args:<[]Value>" - Assert last transaction reverted with a message beginning with an error code + * E.g. "Assert RevertFailure UNAUTHORIZED \"set reserves failed\"" + `, + "RevertCustomError", + [ + new Arg("error", getStringV), + new Arg("args", getCoreValue, {variadic: true, mapped: true, default: []}), + ], + (world, { error, args }) => assertRevertCustomError(world, error.val, rawValues(args)) + ), + new View<{ message: StringV }>(` #### Revert diff --git a/scenario/src/Invokation.ts b/scenario/src/Invokation.ts index 0cf5b9cc6..0c7dd6ff8 100644 --- a/scenario/src/Invokation.ts +++ b/scenario/src/Invokation.ts @@ -55,6 +55,26 @@ export class InvokationRevertFailure extends InvokationError { } } +interface CustomErrorResult { + return: string + error: string +} + +export class InvokationRevertCustomError extends InvokationError { + errCode: number + errorResults: {[address: string]: CustomErrorResult} + + constructor(err: Error, errorResults: {[address: string]: CustomErrorResult}) { + super(err); + + this.errorResults = errorResults; + } + + toString() { + return `InvokationRevertCustomError`; + } +} + interface Argument { name: string type: string @@ -290,6 +310,9 @@ export async function invoke(world: World, fn: Sendable, from: string, err return new Invokation(value, result, new InvokationRevertFailure(err, errMessage, errCode, errorReporter.getError(errCode)), fn, errorReporter); } + if (err.results) { + return new Invokation(value, result, new InvokationRevertCustomError(err, err.results), fn, errorReporter); + } } return new Invokation(value, result, new InvokationError(err), fn, errorReporter); diff --git a/scenario/yarn.lock b/scenario/yarn.lock index eda12cdc4..405b4491a 100644 --- a/scenario/yarn.lock +++ b/scenario/yarn.lock @@ -99,7 +99,7 @@ "@0x/typescript-typings" "^5.1.1" lodash "^4.17.11" -"@0x/subproviders@^6.0.0": +"@0x/subproviders@=6.0.0": version "6.0.0" resolved "https://registry.yarnpkg.com/@0x/subproviders/-/subproviders-6.0.0.tgz#9d4b32e22c9e71f450b0f6d00978ca6b1129c0b3" integrity sha512-5u0JpSGz6RtU0YKckV9FQeJAWkuESG6oR94GQujvkdxg1i1b/QGe9Njq+9VdPq6jhFwl7Hzr8K0JJYTXPlIo5A== @@ -421,7 +421,7 @@ exec-sh "^0.3.2" minimist "^1.2.0" -"@compound-finance/sol-coverage@^4.0.10-alpha.7": +"@compound-finance/sol-coverage@=4.0.10-alpha.7": version "4.0.10-alpha.7" resolved "https://registry.yarnpkg.com/@compound-finance/sol-coverage/-/sol-coverage-4.0.10-alpha.7.tgz#7459f23a9934f987e865bc1717a33da137dae696" integrity sha512-UtBAc50sdv2KEnG3y5d2Vm/WvN5UvnhhZZ73BSYut67DNu4l22kOvlgivgO+Gd4cfTHRNhoy7cy0mZuUBomDfQ== @@ -435,7 +435,7 @@ minimatch "^3.0.4" web3-provider-engine "14.0.6" -"@compound-finance/sol-tracing-utils@7.1.0-alpha.7", "@compound-finance/sol-tracing-utils@^7.1.0-alpha.7": +"@compound-finance/sol-tracing-utils@=7.1.0-alpha.7", "@compound-finance/sol-tracing-utils@^7.1.0-alpha.7": version "7.1.0-alpha.7" resolved "https://registry.yarnpkg.com/@compound-finance/sol-tracing-utils/-/sol-tracing-utils-7.1.0-alpha.7.tgz#ad4b06320fb2db115d3266ca8fdfdd68e6d57080" integrity sha512-7yrJsjg7U6zwrDu09FTRN2ziQAv140dBZnQEasiXGy2UPhv17hToKow/bXtrR233ULQ3xHNR9hlpm2jatE5xVQ== @@ -477,46 +477,57 @@ "@ethersproject/properties" ">=5.0.0-beta.131" "@ethersproject/strings" ">=5.0.0-beta.130" -"@ethersproject/abi@^5.0.0": - version "5.0.2" - resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.0.2.tgz#7fe8f080aa1483fe32cd27bb5b8f2019266af1e2" - integrity sha512-Z+5f7xOgtRLu/W2l9Ry5xF7ehh9QVQ0m1vhynmTcS7DMfHgqTd1/PDFC62aw91ZPRCRZsYdZJu8ymokC5e1JSw== - dependencies: - "@ethersproject/address" "^5.0.0" - "@ethersproject/bignumber" "^5.0.0" - "@ethersproject/bytes" "^5.0.0" - "@ethersproject/constants" "^5.0.0" - "@ethersproject/hash" "^5.0.0" - "@ethersproject/keccak256" "^5.0.0" - "@ethersproject/logger" "^5.0.0" - "@ethersproject/properties" "^5.0.0" - "@ethersproject/strings" "^5.0.0" - -"@ethersproject/abstract-provider@^5.0.0": - version "5.0.2" - resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.0.2.tgz#9b4e8f4870f0691463e8d5b092c95dd5275c635d" - integrity sha512-U1s60+nG02x8FKNMoVNI6MG8SguWCoG9HJtwOqWZ38LBRMsDV4c0w4izKx98kcsN3wXw4U2/YAyJ9LlH7+/hkg== - dependencies: - "@ethersproject/bignumber" "^5.0.0" - "@ethersproject/bytes" "^5.0.0" - "@ethersproject/logger" "^5.0.0" - "@ethersproject/networks" "^5.0.0" - "@ethersproject/properties" "^5.0.0" - "@ethersproject/transactions" "^5.0.0" - "@ethersproject/web" "^5.0.0" - -"@ethersproject/abstract-signer@^5.0.0": - version "5.0.2" - resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.0.2.tgz#5776f888fda816de1d08ddb0e74778ecb9590f69" - integrity sha512-CzzXbeqKlgayE4YTnvvreGBG3n+HxakGXrxaGM6LjBZnOOIVSYi6HMFG8ZXls7UspRY4hvMrtnKEJKDCOngSBw== - dependencies: - "@ethersproject/abstract-provider" "^5.0.0" - "@ethersproject/bignumber" "^5.0.0" - "@ethersproject/bytes" "^5.0.0" - "@ethersproject/logger" "^5.0.0" - "@ethersproject/properties" "^5.0.0" - -"@ethersproject/address@>=5.0.0-beta.128", "@ethersproject/address@^5.0.0": +"@ethersproject/abi@5.4.1", "@ethersproject/abi@^5.4.0": + version "5.4.1" + resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.4.1.tgz#6ac28fafc9ef6f5a7a37e30356a2eb31fa05d39b" + integrity sha512-9mhbjUk76BiSluiiW4BaYyI58KSbDMMQpCLdsAR+RsT2GyATiNYxVv+pGWRrekmsIdY3I+hOqsYQSTkc8L/mcg== + dependencies: + "@ethersproject/address" "^5.4.0" + "@ethersproject/bignumber" "^5.4.0" + "@ethersproject/bytes" "^5.4.0" + "@ethersproject/constants" "^5.4.0" + "@ethersproject/hash" "^5.4.0" + "@ethersproject/keccak256" "^5.4.0" + "@ethersproject/logger" "^5.4.0" + "@ethersproject/properties" "^5.4.0" + "@ethersproject/strings" "^5.4.0" + +"@ethersproject/abstract-provider@5.4.1", "@ethersproject/abstract-provider@^5.4.0": + version "5.4.1" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.4.1.tgz#e404309a29f771bd4d28dbafadcaa184668c2a6e" + integrity sha512-3EedfKI3LVpjSKgAxoUaI+gB27frKsxzm+r21w9G60Ugk+3wVLQwhi1LsEJAKNV7WoZc8CIpNrATlL1QFABjtQ== + dependencies: + "@ethersproject/bignumber" "^5.4.0" + "@ethersproject/bytes" "^5.4.0" + "@ethersproject/logger" "^5.4.0" + "@ethersproject/networks" "^5.4.0" + "@ethersproject/properties" "^5.4.0" + "@ethersproject/transactions" "^5.4.0" + "@ethersproject/web" "^5.4.0" + +"@ethersproject/abstract-signer@5.4.1", "@ethersproject/abstract-signer@^5.4.0": + version "5.4.1" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.4.1.tgz#e4e9abcf4dd4f1ba0db7dff9746a5f78f355ea81" + integrity sha512-SkkFL5HVq1k4/25dM+NWP9MILgohJCgGv5xT5AcRruGz4ILpfHeBtO/y6j+Z3UN/PAjDeb4P7E51Yh8wcGNLGA== + dependencies: + "@ethersproject/abstract-provider" "^5.4.0" + "@ethersproject/bignumber" "^5.4.0" + "@ethersproject/bytes" "^5.4.0" + "@ethersproject/logger" "^5.4.0" + "@ethersproject/properties" "^5.4.0" + +"@ethersproject/address@5.4.0", "@ethersproject/address@^5.0.0", "@ethersproject/address@^5.4.0": + version "5.4.0" + resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.4.0.tgz#ba2d00a0f8c4c0854933b963b9a3a9f6eb4a37a3" + integrity sha512-SD0VgOEkcACEG/C6xavlU1Hy3m5DGSXW3CUHkaaEHbAPPsgi0coP5oNPsxau8eTlZOk/bpa/hKeCNoK5IzVI2Q== + dependencies: + "@ethersproject/bignumber" "^5.4.0" + "@ethersproject/bytes" "^5.4.0" + "@ethersproject/keccak256" "^5.4.0" + "@ethersproject/logger" "^5.4.0" + "@ethersproject/rlp" "^5.4.0" + +"@ethersproject/address@>=5.0.0-beta.128": version "5.0.2" resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.0.2.tgz#80d0ddfb7d4bd0d32657747fa4bdd2defef2e00a" integrity sha512-+rz26RKj7ujGfQynys4V9VJRbR+wpC6eL8F22q3raWMH3152Ha31GwJPWzxE/bEA+43M/zTNVwY0R53gn53L2Q== @@ -528,22 +539,31 @@ "@ethersproject/rlp" "^5.0.0" bn.js "^4.4.0" -"@ethersproject/base64@^5.0.0": - version "5.0.2" - resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.0.2.tgz#48b3bb8d640a963bd8ee196cfeacd592155a0ca8" - integrity sha512-0FE5RH5cUDddOiQEDpWtyHjkSW4D5/rdJzA3KTZo8Fk5ab/Y8vdzqbamsXPyPsXU3gS+zCE5Qq4EKVOWlWLLTA== +"@ethersproject/base64@5.4.0", "@ethersproject/base64@^5.4.0": + version "5.4.0" + resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.4.0.tgz#7252bf65295954c9048c7ca5f43e5c86441b2a9a" + integrity sha512-CjQw6E17QDSSC5jiM9YpF7N1aSCHmYGMt9bWD8PWv6YPMxjsys2/Q8xLrROKI3IWJ7sFfZ8B3flKDTM5wlWuZQ== dependencies: - "@ethersproject/bytes" "^5.0.0" + "@ethersproject/bytes" "^5.4.0" -"@ethersproject/basex@^5.0.0": - version "5.0.2" - resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.0.2.tgz#13029ce0ad63674f4d4dbebf6763181fb22f0e6d" - integrity sha512-p4m2CeQqI9vma3XipRbP2iDf6zTsbroE0MEXBAYXidsoJQSvePKrC6MVRKfTzfcHej1b9wfmjVBzqhqn3FRhIA== +"@ethersproject/basex@5.4.0", "@ethersproject/basex@^5.4.0": + version "5.4.0" + resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.4.0.tgz#0a2da0f4e76c504a94f2b21d3161ed9438c7f8a6" + integrity sha512-J07+QCVJ7np2bcpxydFVf/CuYo9mZ7T73Pe7KQY4c1lRlrixMeblauMxHXD0MPwFmUHZIILDNViVkykFBZylbg== dependencies: - "@ethersproject/bytes" "^5.0.0" - "@ethersproject/properties" "^5.0.0" + "@ethersproject/bytes" "^5.4.0" + "@ethersproject/properties" "^5.4.0" -"@ethersproject/bignumber@>=5.0.0-beta.130", "@ethersproject/bignumber@^5.0.0": +"@ethersproject/bignumber@5.4.1", "@ethersproject/bignumber@^5.0.0", "@ethersproject/bignumber@^5.4.0": + version "5.4.1" + resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.4.1.tgz#64399d3b9ae80aa83d483e550ba57ea062c1042d" + integrity sha512-fJhdxqoQNuDOk6epfM7yD6J8Pol4NUCy1vkaGAkuujZm0+lNow//MKu1hLhRiYV4BsOHyBv5/lsTjF+7hWwhJg== + dependencies: + "@ethersproject/bytes" "^5.4.0" + "@ethersproject/logger" "^5.4.0" + bn.js "^4.11.9" + +"@ethersproject/bignumber@>=5.0.0-beta.130": version "5.0.5" resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.0.5.tgz#31bd7e75aad46ace345fae69b1f5bb120906af1b" integrity sha512-24ln7PV0g8ZzjcVZiLW9Wod0i+XCmK6zKkAaxw5enraTIT1p7gVOcSXFSzNQ9WYAwtiFQPvvA+TIO2oEITZNJA== @@ -552,36 +572,65 @@ "@ethersproject/logger" "^5.0.0" bn.js "^4.4.0" -"@ethersproject/bytes@>=5.0.0-beta.129", "@ethersproject/bytes@^5.0.0": +"@ethersproject/bytes@5.4.0", "@ethersproject/bytes@^5.0.0", "@ethersproject/bytes@^5.4.0": + version "5.4.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.4.0.tgz#56fa32ce3bf67153756dbaefda921d1d4774404e" + integrity sha512-H60ceqgTHbhzOj4uRc/83SCN9d+BSUnOkrr2intevqdtEMO1JFVZ1XL84OEZV+QjV36OaZYxtnt4lGmxcGsPfA== + dependencies: + "@ethersproject/logger" "^5.4.0" + +"@ethersproject/bytes@>=5.0.0-beta.129": version "5.0.3" resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.0.3.tgz#b3769963ae0188a35713d343890a903bda20af9c" integrity sha512-AyPMAlY+Amaw4Zfp8OAivm1xYPI8mqiUYmEnSUk1CnS2NrQGHEMmFJFiOJdS3gDDpgSOFhWIjZwxKq2VZpqNTA== dependencies: "@ethersproject/logger" "^5.0.0" -"@ethersproject/constants@>=5.0.0-beta.128", "@ethersproject/constants@^5.0.0": - version "5.0.2" - resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.0.2.tgz#f7ac0b320e2bbec1a5950da075015f8bc4e8fed1" - integrity sha512-nNoVlNP6bgpog7pQ2EyD1xjlaXcy1Cl4kK5v1KoskHj58EtB6TK8M8AFGi3GgHTdMldfT4eN3OsoQ/CdOTVNFA== +"@ethersproject/constants@5.4.0", "@ethersproject/constants@^5.0.0", "@ethersproject/constants@^5.4.0": + version "5.4.0" + resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.4.0.tgz#ee0bdcb30bf1b532d2353c977bf2ef1ee117958a" + integrity sha512-tzjn6S7sj9+DIIeKTJLjK9WGN2Tj0P++Z8ONEIlZjyoTkBuODN+0VfhAyYksKi43l1Sx9tX2VlFfzjfmr5Wl3Q== dependencies: - "@ethersproject/bignumber" "^5.0.0" + "@ethersproject/bignumber" "^5.4.0" -"@ethersproject/contracts@^5.0.0": +"@ethersproject/constants@>=5.0.0-beta.128": version "5.0.2" - resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.0.2.tgz#f19ed8335ceeb6abb60f5d45641f0a2a62b6fbc5" - integrity sha512-Ud3oW8mBNIWE+WHRjvwVEwfvshn7lfYWSSKG0fPSb6baRN9mLOoNguX+VIv3W5Sne9w2utnBmxLF2ESXitw64A== + resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.0.2.tgz#f7ac0b320e2bbec1a5950da075015f8bc4e8fed1" + integrity sha512-nNoVlNP6bgpog7pQ2EyD1xjlaXcy1Cl4kK5v1KoskHj58EtB6TK8M8AFGi3GgHTdMldfT4eN3OsoQ/CdOTVNFA== dependencies: - "@ethersproject/abi" "^5.0.0" - "@ethersproject/abstract-provider" "^5.0.0" - "@ethersproject/abstract-signer" "^5.0.0" - "@ethersproject/address" "^5.0.0" "@ethersproject/bignumber" "^5.0.0" - "@ethersproject/bytes" "^5.0.0" - "@ethersproject/constants" "^5.0.0" - "@ethersproject/logger" "^5.0.0" - "@ethersproject/properties" "^5.0.0" -"@ethersproject/hash@>=5.0.0-beta.128", "@ethersproject/hash@^5.0.0": +"@ethersproject/contracts@5.4.1": + version "5.4.1" + resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.4.1.tgz#3eb4f35b7fe60a962a75804ada2746494df3e470" + integrity sha512-m+z2ZgPy4pyR15Je//dUaymRUZq5MtDajF6GwFbGAVmKz/RF+DNIPwF0k5qEcL3wPGVqUjFg2/krlCRVTU4T5w== + dependencies: + "@ethersproject/abi" "^5.4.0" + "@ethersproject/abstract-provider" "^5.4.0" + "@ethersproject/abstract-signer" "^5.4.0" + "@ethersproject/address" "^5.4.0" + "@ethersproject/bignumber" "^5.4.0" + "@ethersproject/bytes" "^5.4.0" + "@ethersproject/constants" "^5.4.0" + "@ethersproject/logger" "^5.4.0" + "@ethersproject/properties" "^5.4.0" + "@ethersproject/transactions" "^5.4.0" + +"@ethersproject/hash@5.4.0", "@ethersproject/hash@^5.4.0": + version "5.4.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.4.0.tgz#d18a8e927e828e22860a011f39e429d388344ae0" + integrity sha512-xymAM9tmikKgbktOCjW60Z5sdouiIIurkZUr9oW5NOex5uwxrbsYG09kb5bMcNjlVeJD3yPivTNzViIs1GCbqA== + dependencies: + "@ethersproject/abstract-signer" "^5.4.0" + "@ethersproject/address" "^5.4.0" + "@ethersproject/bignumber" "^5.4.0" + "@ethersproject/bytes" "^5.4.0" + "@ethersproject/keccak256" "^5.4.0" + "@ethersproject/logger" "^5.4.0" + "@ethersproject/properties" "^5.4.0" + "@ethersproject/strings" "^5.4.0" + +"@ethersproject/hash@>=5.0.0-beta.128": version "5.0.2" resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.0.2.tgz#6d69558786961836d530b8b4a8714eac5388aec7" integrity sha512-dWGvNwmVRX2bxoQQ3ciMw46Vzl1nqfL+5R8+2ZxsRXD3Cjgw1dL2mdjJF7xMMWPvPdrlhKXWSK0gb8VLwHZ8Cw== @@ -591,44 +640,52 @@ "@ethersproject/logger" "^5.0.0" "@ethersproject/strings" "^5.0.0" -"@ethersproject/hdnode@^5.0.0": - version "5.0.2" - resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.0.2.tgz#c4f2152590a64822d0c0feb90f09cc247af657e0" - integrity sha512-QAUI5tfseTFqv00Vnbwzofqse81wN9TaL+x5GufTHIHJXgVdguxU+l39E3VYDCmO+eVAA6RCn5dJgeyra+PU2g== - dependencies: - "@ethersproject/abstract-signer" "^5.0.0" - "@ethersproject/basex" "^5.0.0" - "@ethersproject/bignumber" "^5.0.0" - "@ethersproject/bytes" "^5.0.0" - "@ethersproject/logger" "^5.0.0" - "@ethersproject/pbkdf2" "^5.0.0" - "@ethersproject/properties" "^5.0.0" - "@ethersproject/sha2" "^5.0.0" - "@ethersproject/signing-key" "^5.0.0" - "@ethersproject/strings" "^5.0.0" - "@ethersproject/transactions" "^5.0.0" - "@ethersproject/wordlists" "^5.0.0" - -"@ethersproject/json-wallets@^5.0.0": - version "5.0.4" - resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.0.4.tgz#e09bf2d34279c6dd2b4a4d4c44db65471bacc68b" - integrity sha512-jqtb+X3rJXWG/w+Qyr7vq1V+fdc5jiLlyc6akwI3SQIHTfcuuyF+eZRd9u2/455urNwV3nuCsnrgxs2NrtHHIw== - dependencies: - "@ethersproject/abstract-signer" "^5.0.0" - "@ethersproject/address" "^5.0.0" - "@ethersproject/bytes" "^5.0.0" - "@ethersproject/hdnode" "^5.0.0" - "@ethersproject/keccak256" "^5.0.0" - "@ethersproject/logger" "^5.0.0" - "@ethersproject/pbkdf2" "^5.0.0" - "@ethersproject/properties" "^5.0.0" - "@ethersproject/random" "^5.0.0" - "@ethersproject/strings" "^5.0.0" - "@ethersproject/transactions" "^5.0.0" +"@ethersproject/hdnode@5.4.0", "@ethersproject/hdnode@^5.4.0": + version "5.4.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.4.0.tgz#4bc9999b9a12eb5ce80c5faa83114a57e4107cac" + integrity sha512-pKxdS0KAaeVGfZPp1KOiDLB0jba11tG6OP1u11QnYfb7pXn6IZx0xceqWRr6ygke8+Kw74IpOoSi7/DwANhy8Q== + dependencies: + "@ethersproject/abstract-signer" "^5.4.0" + "@ethersproject/basex" "^5.4.0" + "@ethersproject/bignumber" "^5.4.0" + "@ethersproject/bytes" "^5.4.0" + "@ethersproject/logger" "^5.4.0" + "@ethersproject/pbkdf2" "^5.4.0" + "@ethersproject/properties" "^5.4.0" + "@ethersproject/sha2" "^5.4.0" + "@ethersproject/signing-key" "^5.4.0" + "@ethersproject/strings" "^5.4.0" + "@ethersproject/transactions" "^5.4.0" + "@ethersproject/wordlists" "^5.4.0" + +"@ethersproject/json-wallets@5.4.0", "@ethersproject/json-wallets@^5.4.0": + version "5.4.0" + resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.4.0.tgz#2583341cfe313fc9856642e8ace3080154145e95" + integrity sha512-igWcu3fx4aiczrzEHwG1xJZo9l1cFfQOWzTqwRw/xcvxTk58q4f9M7cjh51EKphMHvrJtcezJ1gf1q1AUOfEQQ== + dependencies: + "@ethersproject/abstract-signer" "^5.4.0" + "@ethersproject/address" "^5.4.0" + "@ethersproject/bytes" "^5.4.0" + "@ethersproject/hdnode" "^5.4.0" + "@ethersproject/keccak256" "^5.4.0" + "@ethersproject/logger" "^5.4.0" + "@ethersproject/pbkdf2" "^5.4.0" + "@ethersproject/properties" "^5.4.0" + "@ethersproject/random" "^5.4.0" + "@ethersproject/strings" "^5.4.0" + "@ethersproject/transactions" "^5.4.0" aes-js "3.0.0" scrypt-js "3.0.1" -"@ethersproject/keccak256@>=5.0.0-beta.127", "@ethersproject/keccak256@^5.0.0": +"@ethersproject/keccak256@5.4.0", "@ethersproject/keccak256@^5.0.0", "@ethersproject/keccak256@^5.4.0": + version "5.4.0" + resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.4.0.tgz#7143b8eea4976080241d2bd92e3b1f1bf7025318" + integrity sha512-FBI1plWet+dPUvAzPAeHzRKiPpETQzqSUWR1wXJGHVWi4i8bOSrpC3NwpkPjgeXG7MnugVc1B42VbfnQikyC/A== + dependencies: + "@ethersproject/bytes" "^5.4.0" + js-sha3 "0.5.7" + +"@ethersproject/keccak256@>=5.0.0-beta.127": version "5.0.2" resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.0.2.tgz#7ed4a95bb45ee502cf4532223833740a83602797" integrity sha512-MbroXutc0gPNYIrUjS4Aw0lDuXabdzI7+l7elRWr1G6G+W0v00e/3gbikWkCReGtt2Jnt4lQSgnflhDwQGcIhA== @@ -636,102 +693,128 @@ "@ethersproject/bytes" "^5.0.0" js-sha3 "0.5.7" -"@ethersproject/logger@>=5.0.0-beta.129", "@ethersproject/logger@^5.0.0": +"@ethersproject/logger@5.4.1", "@ethersproject/logger@^5.0.0", "@ethersproject/logger@^5.4.0": + version "5.4.1" + resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.4.1.tgz#503bd33683538b923c578c07d1c2c0dd18672054" + integrity sha512-DZ+bRinnYLPw1yAC64oRl0QyVZj43QeHIhVKfD/+YwSz4wsv1pfwb5SOFjz+r710YEWzU6LrhuSjpSO+6PeE4A== + +"@ethersproject/logger@>=5.0.0-beta.129": version "5.0.4" resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.0.4.tgz#09fa4765b5691233e3afb6617cb38a700f9dd2e4" integrity sha512-alA2LiAy1LdQ/L1SA9ajUC7MvGAEQLsICEfKK4erX5qhkXE1LwLSPIzobtOWFsMHf2yrXGKBLnnpuVHprI3sAw== -"@ethersproject/networks@^5.0.0": - version "5.0.2" - resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.0.2.tgz#a49e82cf071e3618e87e3c5d69fdbcf54dc6766c" - integrity sha512-T7HVd62D4izNU2tDHf6xUDo7k4JOGX4Lk7vDmVcDKrepSWwL2OmGWrqSlkRe2a1Dnz4+1VPE6fb6+KsmSRe82g== - dependencies: - "@ethersproject/logger" "^5.0.0" - -"@ethersproject/pbkdf2@^5.0.0": - version "5.0.2" - resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.0.2.tgz#d12c5f434bbdf6f52401eddb7d753a713dd9e4ea" - integrity sha512-OJFxdX/VtGI5M04lAzXKEOb76XBzjCOzGyko3/bMWat3ePAw7RveBOLyhm79SBs2fh21MSYgdG6JScEMHoSImw== - dependencies: - "@ethersproject/bytes" "^5.0.0" - "@ethersproject/sha2" "^5.0.0" - -"@ethersproject/properties@>=5.0.0-beta.131", "@ethersproject/properties@^5.0.0": - version "5.0.2" - resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.0.2.tgz#2facb62d2f2d968c7b3d0befa5bcc884cc565d3b" - integrity sha512-FxAisPGAOACQjMJzewl9OJG6lsGCPTm5vpUMtfeoxzAlAb2lv+kHzQPUh9h4jfAILzE8AR1jgXMzRmlhwyra1Q== - dependencies: - "@ethersproject/logger" "^5.0.0" - -"@ethersproject/providers@^5.0.0": - version "5.0.5" - resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.0.5.tgz#fa28498ce9683d1d99f6cb11e1a7fe8d4886e0ce" - integrity sha512-ZR3yFg/m8qDl7317yXOHE7tKeGfoyZIZ/imhVC4JqAH+SX1rb6bdZcSjhJfet7rLmnJSsnYLTgIiVIT85aVLgg== +"@ethersproject/networks@5.4.2", "@ethersproject/networks@^5.4.0": + version "5.4.2" + resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.4.2.tgz#2247d977626e97e2c3b8ee73cd2457babde0ce35" + integrity sha512-eekOhvJyBnuibfJnhtK46b8HimBc5+4gqpvd1/H9LEl7Q7/qhsIhM81dI9Fcnjpk3jB1aTy6bj0hz3cifhNeYw== dependencies: - "@ethersproject/abstract-provider" "^5.0.0" - "@ethersproject/abstract-signer" "^5.0.0" - "@ethersproject/address" "^5.0.0" - "@ethersproject/bignumber" "^5.0.0" - "@ethersproject/bytes" "^5.0.0" - "@ethersproject/constants" "^5.0.0" - "@ethersproject/hash" "^5.0.0" - "@ethersproject/logger" "^5.0.0" - "@ethersproject/networks" "^5.0.0" - "@ethersproject/properties" "^5.0.0" - "@ethersproject/random" "^5.0.0" - "@ethersproject/rlp" "^5.0.0" - "@ethersproject/strings" "^5.0.0" - "@ethersproject/transactions" "^5.0.0" - "@ethersproject/web" "^5.0.0" - ws "7.2.3" + "@ethersproject/logger" "^5.4.0" -"@ethersproject/random@^5.0.0": - version "5.0.2" - resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.0.2.tgz#bb58aca69a85e8de506686117f050d03dac69023" - integrity sha512-kLeS+6bwz37WR2zbe69gudyoGVoUzljQO0LhifnATsZ7rW0JZ9Zgt0h5aXY7tqFDo9TvdqeCwUFdp1t3T5Fkhg== +"@ethersproject/pbkdf2@5.4.0", "@ethersproject/pbkdf2@^5.4.0": + version "5.4.0" + resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.4.0.tgz#ed88782a67fda1594c22d60d0ca911a9d669641c" + integrity sha512-x94aIv6tiA04g6BnazZSLoRXqyusawRyZWlUhKip2jvoLpzJuLb//KtMM6PEovE47pMbW+Qe1uw+68ameJjB7g== dependencies: - "@ethersproject/bytes" "^5.0.0" - "@ethersproject/logger" "^5.0.0" + "@ethersproject/bytes" "^5.4.0" + "@ethersproject/sha2" "^5.4.0" -"@ethersproject/rlp@^5.0.0": - version "5.0.2" - resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.0.2.tgz#d6b550a2ac5e484f15f0f63337e522004d2e78cd" - integrity sha512-oE0M5jqQ67fi2SuMcrpoewOpEuoXaD8M9JeR9md1bXRMvDYgKXUtDHs22oevpEOdnO2DPIRabp6MVHa4aDuWmw== +"@ethersproject/properties@5.4.1", "@ethersproject/properties@^5.0.0", "@ethersproject/properties@^5.4.0": + version "5.4.1" + resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.4.1.tgz#9f051f976ce790142c6261ccb7b826eaae1f2f36" + integrity sha512-cyCGlF8wWlIZyizsj2PpbJ9I7rIlUAfnHYwy/T90pdkSn/NFTa5YWZx2wTJBe9V7dD65dcrrEMisCRUJiq6n3w== dependencies: - "@ethersproject/bytes" "^5.0.0" - "@ethersproject/logger" "^5.0.0" + "@ethersproject/logger" "^5.4.0" -"@ethersproject/sha2@^5.0.0": +"@ethersproject/properties@>=5.0.0-beta.131": version "5.0.2" - resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.0.2.tgz#baefc78c071be8729b180759eb29267129314252" - integrity sha512-VFl4qSStjQZaygpqoAHswaCY59qBm1Sm0rf8iv0tmgVsRf0pBg2nJaNf9NXXvcuJ9AYPyXl57dN8kozdC4z5Cg== - dependencies: - "@ethersproject/bytes" "^5.0.0" - "@ethersproject/logger" "^5.0.0" - hash.js "1.1.3" - -"@ethersproject/signing-key@^5.0.0": - version "5.0.3" - resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.0.3.tgz#adb84360e147bfd336cb2fe114100120732dc10a" - integrity sha512-5QPZaBRGCLzfVMbFb3LcVjNR0UbTXnwDHASnQYfbzwUOnFYHKxHsrcbl/5ONGoppgi8yXgOocKqlPCFycJJVWQ== + resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.0.2.tgz#2facb62d2f2d968c7b3d0befa5bcc884cc565d3b" + integrity sha512-FxAisPGAOACQjMJzewl9OJG6lsGCPTm5vpUMtfeoxzAlAb2lv+kHzQPUh9h4jfAILzE8AR1jgXMzRmlhwyra1Q== dependencies: - "@ethersproject/bytes" "^5.0.0" "@ethersproject/logger" "^5.0.0" - "@ethersproject/properties" "^5.0.0" - elliptic "6.5.3" -"@ethersproject/solidity@^5.0.0": - version "5.0.2" - resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.0.2.tgz#431cee341ec51e022bd897b93fef04521f414756" - integrity sha512-RygurUe1hPW1LDYAPXy4471AklGWNnxgFWc3YUE6H11gzkit26jr6AyZH4Yyjw38eBBL6j0AOfQzMWm+NhxZ9g== - dependencies: - "@ethersproject/bignumber" "^5.0.0" - "@ethersproject/bytes" "^5.0.0" - "@ethersproject/keccak256" "^5.0.0" - "@ethersproject/sha2" "^5.0.0" - "@ethersproject/strings" "^5.0.0" - -"@ethersproject/strings@>=5.0.0-beta.130", "@ethersproject/strings@^5.0.0": +"@ethersproject/providers@5.4.5": + version "5.4.5" + resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.4.5.tgz#eb2ea2a743a8115f79604a8157233a3a2c832928" + integrity sha512-1GkrvkiAw3Fj28cwi1Sqm8ED1RtERtpdXmRfwIBGmqBSN5MoeRUHuwHPppMtbPayPgpFcvD7/Gdc9doO5fGYgw== + dependencies: + "@ethersproject/abstract-provider" "^5.4.0" + "@ethersproject/abstract-signer" "^5.4.0" + "@ethersproject/address" "^5.4.0" + "@ethersproject/basex" "^5.4.0" + "@ethersproject/bignumber" "^5.4.0" + "@ethersproject/bytes" "^5.4.0" + "@ethersproject/constants" "^5.4.0" + "@ethersproject/hash" "^5.4.0" + "@ethersproject/logger" "^5.4.0" + "@ethersproject/networks" "^5.4.0" + "@ethersproject/properties" "^5.4.0" + "@ethersproject/random" "^5.4.0" + "@ethersproject/rlp" "^5.4.0" + "@ethersproject/sha2" "^5.4.0" + "@ethersproject/strings" "^5.4.0" + "@ethersproject/transactions" "^5.4.0" + "@ethersproject/web" "^5.4.0" + bech32 "1.1.4" + ws "7.4.6" + +"@ethersproject/random@5.4.0", "@ethersproject/random@^5.4.0": + version "5.4.0" + resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.4.0.tgz#9cdde60e160d024be39cc16f8de3b9ce39191e16" + integrity sha512-pnpWNQlf0VAZDEOVp1rsYQosmv2o0ITS/PecNw+mS2/btF8eYdspkN0vIXrCMtkX09EAh9bdk8GoXmFXM1eAKw== + dependencies: + "@ethersproject/bytes" "^5.4.0" + "@ethersproject/logger" "^5.4.0" + +"@ethersproject/rlp@5.4.0", "@ethersproject/rlp@^5.0.0", "@ethersproject/rlp@^5.4.0": + version "5.4.0" + resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.4.0.tgz#de61afda5ff979454e76d3b3310a6c32ad060931" + integrity sha512-0I7MZKfi+T5+G8atId9QaQKHRvvasM/kqLyAH4XxBCBchAooH2EX5rL9kYZWwcm3awYV+XC7VF6nLhfeQFKVPg== + dependencies: + "@ethersproject/bytes" "^5.4.0" + "@ethersproject/logger" "^5.4.0" + +"@ethersproject/sha2@5.4.0", "@ethersproject/sha2@^5.4.0": + version "5.4.0" + resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.4.0.tgz#c9a8db1037014cbc4e9482bd662f86c090440371" + integrity sha512-siheo36r1WD7Cy+bDdE1BJ8y0bDtqXCOxRMzPa4bV1TGt/eTUUt03BHoJNB6reWJD8A30E/pdJ8WFkq+/uz4Gg== + dependencies: + "@ethersproject/bytes" "^5.4.0" + "@ethersproject/logger" "^5.4.0" + hash.js "1.1.7" + +"@ethersproject/signing-key@5.4.0", "@ethersproject/signing-key@^5.0.0", "@ethersproject/signing-key@^5.4.0": + version "5.4.0" + resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.4.0.tgz#2f05120984e81cf89a3d5f6dec5c68ee0894fbec" + integrity sha512-q8POUeywx6AKg2/jX9qBYZIAmKSB4ubGXdQ88l40hmATj29JnG5pp331nAWwwxPn2Qao4JpWHNZsQN+bPiSW9A== + dependencies: + "@ethersproject/bytes" "^5.4.0" + "@ethersproject/logger" "^5.4.0" + "@ethersproject/properties" "^5.4.0" + bn.js "^4.11.9" + elliptic "6.5.4" + hash.js "1.1.7" + +"@ethersproject/solidity@5.4.0": + version "5.4.0" + resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.4.0.tgz#1305e058ea02dc4891df18b33232b11a14ece9ec" + integrity sha512-XFQTZ7wFSHOhHcV1DpcWj7VXECEiSrBuv7JErJvB9Uo+KfCdc3QtUZV+Vjh/AAaYgezUEKbCtE6Khjm44seevQ== + dependencies: + "@ethersproject/bignumber" "^5.4.0" + "@ethersproject/bytes" "^5.4.0" + "@ethersproject/keccak256" "^5.4.0" + "@ethersproject/sha2" "^5.4.0" + "@ethersproject/strings" "^5.4.0" + +"@ethersproject/strings@5.4.0", "@ethersproject/strings@^5.0.0", "@ethersproject/strings@^5.4.0": + version "5.4.0" + resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.4.0.tgz#fb12270132dd84b02906a8d895ae7e7fa3d07d9a" + integrity sha512-k/9DkH5UGDhv7aReXLluFG5ExurwtIpUfnDNhQA29w896Dw3i4uDTz01Quaptbks1Uj9kI8wo9tmW73wcIEaWA== + dependencies: + "@ethersproject/bytes" "^5.4.0" + "@ethersproject/constants" "^5.4.0" + "@ethersproject/logger" "^5.4.0" + +"@ethersproject/strings@>=5.0.0-beta.130": version "5.0.2" resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.0.2.tgz#1753408c3c889813fd0992abd76393e3e47a2619" integrity sha512-oNa+xvSqsFU96ndzog0IBTtsRFGOqGpzrXJ7shXLBT7juVeSEyZA/sYs0DMZB5mJ9FEjHdZKxR/rTyBY91vuXg== @@ -740,7 +823,22 @@ "@ethersproject/constants" "^5.0.0" "@ethersproject/logger" "^5.0.0" -"@ethersproject/transactions@^5.0.0", "@ethersproject/transactions@^5.0.0-beta.135": +"@ethersproject/transactions@5.4.0", "@ethersproject/transactions@^5.4.0": + version "5.4.0" + resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.4.0.tgz#a159d035179334bd92f340ce0f77e83e9e1522e0" + integrity sha512-s3EjZZt7xa4BkLknJZ98QGoIza94rVjaEed0rzZ/jB9WrIuu/1+tjvYCWzVrystXtDswy7TPBeIepyXwSYa4WQ== + dependencies: + "@ethersproject/address" "^5.4.0" + "@ethersproject/bignumber" "^5.4.0" + "@ethersproject/bytes" "^5.4.0" + "@ethersproject/constants" "^5.4.0" + "@ethersproject/keccak256" "^5.4.0" + "@ethersproject/logger" "^5.4.0" + "@ethersproject/properties" "^5.4.0" + "@ethersproject/rlp" "^5.4.0" + "@ethersproject/signing-key" "^5.4.0" + +"@ethersproject/transactions@^5.0.0-beta.135": version "5.0.2" resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.0.2.tgz#590ede71fc87b45be7bd46002e18ae52246a2347" integrity sha512-jZp0ZbbJlq4JLZY6qoMzNtp2HQsX6USQposi3ns0MPUdn3OdZJBDtrcO15r/2VS5t/K1e1GE5MI1HmMKlcTbbQ== @@ -755,57 +853,57 @@ "@ethersproject/rlp" "^5.0.0" "@ethersproject/signing-key" "^5.0.0" -"@ethersproject/units@^5.0.0": - version "5.0.2" - resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.0.2.tgz#de1461ff3ad2587e57bf367d056b6b72cfceda78" - integrity sha512-PSuzycBA1zmRysTtKtp+XYZ3HIJfbmfRdZchOUxdyeGo5siUi9H6mYQcxdJHv82oKp/FniMj8qS8qtLQThhOEg== - dependencies: - "@ethersproject/bignumber" "^5.0.0" - "@ethersproject/constants" "^5.0.0" - "@ethersproject/logger" "^5.0.0" - -"@ethersproject/wallet@^5.0.0": - version "5.0.2" - resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.0.2.tgz#714ca8324c1b3b66e51b9b4e0358c882e88caf1d" - integrity sha512-gg86ynLV5k5caNnYpJoYc6WyIUHKMTjOITCk5zXGyVbbkXE07y/fGql4A51W0C6mWkeb5Mzz8AKqzHZECdH30w== - dependencies: - "@ethersproject/abstract-provider" "^5.0.0" - "@ethersproject/abstract-signer" "^5.0.0" - "@ethersproject/address" "^5.0.0" - "@ethersproject/bignumber" "^5.0.0" - "@ethersproject/bytes" "^5.0.0" - "@ethersproject/hash" "^5.0.0" - "@ethersproject/hdnode" "^5.0.0" - "@ethersproject/json-wallets" "^5.0.0" - "@ethersproject/keccak256" "^5.0.0" - "@ethersproject/logger" "^5.0.0" - "@ethersproject/properties" "^5.0.0" - "@ethersproject/random" "^5.0.0" - "@ethersproject/signing-key" "^5.0.0" - "@ethersproject/transactions" "^5.0.0" - "@ethersproject/wordlists" "^5.0.0" - -"@ethersproject/web@^5.0.0": - version "5.0.3" - resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.0.3.tgz#f5673923009bb855302f0296ddb932da8e42f0a1" - integrity sha512-9WoIWNxbFOk+8TiWqQMQbYJUIFeC1Z7zNr7oCHpVyhxF0EY54ZVXlP/Y7VJ7KzK++A/iMGOuTIGeL5sMqa2QMg== - dependencies: - "@ethersproject/base64" "^5.0.0" - "@ethersproject/bytes" "^5.0.0" - "@ethersproject/logger" "^5.0.0" - "@ethersproject/properties" "^5.0.0" - "@ethersproject/strings" "^5.0.0" - -"@ethersproject/wordlists@^5.0.0": - version "5.0.2" - resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.0.2.tgz#eded47314509c8608373fc2b22879ee2b71b7c7c" - integrity sha512-6vKDQcjjpnfdSCr0+jNxpFH3ieKxUPkm29tQX2US7a3zT/sJU/BGlKBR7D8oOpwdE0hpkHhJyMlypRBK+A2avA== - dependencies: - "@ethersproject/bytes" "^5.0.0" - "@ethersproject/hash" "^5.0.0" - "@ethersproject/logger" "^5.0.0" - "@ethersproject/properties" "^5.0.0" - "@ethersproject/strings" "^5.0.0" +"@ethersproject/units@5.4.0": + version "5.4.0" + resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.4.0.tgz#d57477a4498b14b88b10396062c8cbbaf20c79fe" + integrity sha512-Z88krX40KCp+JqPCP5oPv5p750g+uU6gopDYRTBGcDvOASh6qhiEYCRatuM/suC4S2XW9Zz90QI35MfSrTIaFg== + dependencies: + "@ethersproject/bignumber" "^5.4.0" + "@ethersproject/constants" "^5.4.0" + "@ethersproject/logger" "^5.4.0" + +"@ethersproject/wallet@5.4.0": + version "5.4.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.4.0.tgz#fa5b59830b42e9be56eadd45a16a2e0933ad9353" + integrity sha512-wU29majLjM6AjCjpat21mPPviG+EpK7wY1+jzKD0fg3ui5fgedf2zEu1RDgpfIMsfn8fJHJuzM4zXZ2+hSHaSQ== + dependencies: + "@ethersproject/abstract-provider" "^5.4.0" + "@ethersproject/abstract-signer" "^5.4.0" + "@ethersproject/address" "^5.4.0" + "@ethersproject/bignumber" "^5.4.0" + "@ethersproject/bytes" "^5.4.0" + "@ethersproject/hash" "^5.4.0" + "@ethersproject/hdnode" "^5.4.0" + "@ethersproject/json-wallets" "^5.4.0" + "@ethersproject/keccak256" "^5.4.0" + "@ethersproject/logger" "^5.4.0" + "@ethersproject/properties" "^5.4.0" + "@ethersproject/random" "^5.4.0" + "@ethersproject/signing-key" "^5.4.0" + "@ethersproject/transactions" "^5.4.0" + "@ethersproject/wordlists" "^5.4.0" + +"@ethersproject/web@5.4.0", "@ethersproject/web@^5.4.0": + version "5.4.0" + resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.4.0.tgz#49fac173b96992334ed36a175538ba07a7413d1f" + integrity sha512-1bUusGmcoRLYgMn6c1BLk1tOKUIFuTg8j+6N8lYlbMpDesnle+i3pGSagGNvwjaiLo4Y5gBibwctpPRmjrh4Og== + dependencies: + "@ethersproject/base64" "^5.4.0" + "@ethersproject/bytes" "^5.4.0" + "@ethersproject/logger" "^5.4.0" + "@ethersproject/properties" "^5.4.0" + "@ethersproject/strings" "^5.4.0" + +"@ethersproject/wordlists@5.4.0", "@ethersproject/wordlists@^5.4.0": + version "5.4.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.4.0.tgz#f34205ec3bbc9e2c49cadaee774cf0b07e7573d7" + integrity sha512-FemEkf6a+EBKEPxlzeVgUaVSodU7G0Na89jqKjmWMlDB0tomoU8RlEMgUvXyqtrg8N4cwpLh8nyRnm1Nay1isA== + dependencies: + "@ethersproject/bytes" "^5.4.0" + "@ethersproject/hash" "^5.4.0" + "@ethersproject/logger" "^5.4.0" + "@ethersproject/properties" "^5.4.0" + "@ethersproject/strings" "^5.4.0" "@jest/console@^24.7.1", "@jest/console@^24.9.0": version "24.9.0" @@ -2543,6 +2641,11 @@ bcrypt-pbkdf@^1.0.0: dependencies: tweetnacl "^0.14.3" +bech32@1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" + integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== + bfj@^6.1.1: version "6.1.2" resolved "https://registry.yarnpkg.com/bfj/-/bfj-6.1.2.tgz#325c861a822bcb358a41c78a33b8e6e2086dde7f" @@ -2639,7 +2742,7 @@ bn.js@4.11.6: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" integrity sha1-UzRK2xRhehP26N0s4okF0cC6MhU= -bn.js@4.11.8, bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.10.0, bn.js@^4.11.0, bn.js@^4.11.1, bn.js@^4.11.6, bn.js@^4.11.8, bn.js@^4.4.0, bn.js@^4.8.0: +bn.js@4.11.8, bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.10.0, bn.js@^4.11.0, bn.js@^4.11.1, bn.js@^4.11.6, bn.js@^4.11.8, bn.js@^4.8.0: version "4.11.8" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA== @@ -2649,6 +2752,11 @@ bn.js@^4.11.9: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.9.tgz#26d556829458f9d1e81fc48952493d0ba3507828" integrity sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw== +bn.js@^4.4.0: + version "4.12.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" + integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== + body-parser@1.19.0, body-parser@^1.16.0: version "1.19.0" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" @@ -2696,7 +2804,7 @@ braces@^3.0.1, braces@~3.0.2: dependencies: fill-range "^7.0.1" -brorand@^1.0.1: +brorand@^1.0.1, brorand@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= @@ -3975,18 +4083,18 @@ elliptic@6.5.2, elliptic@^6.0.0, elliptic@^6.4.0, elliptic@^6.4.1: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.0" -elliptic@6.5.3: - version "6.5.3" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.3.tgz#cb59eb2efdaf73a0bd78ccd7015a62ad6e0f93d6" - integrity sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw== +elliptic@6.5.4: + version "6.5.4" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" + integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== dependencies: - bn.js "^4.4.0" - brorand "^1.0.1" + bn.js "^4.11.9" + brorand "^1.1.0" hash.js "^1.0.0" - hmac-drbg "^1.0.0" - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - minimalistic-crypto-utils "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" emoji-regex@^7.0.1: version "7.0.3" @@ -4383,19 +4491,19 @@ eth-query@^2.0.2, eth-query@^2.1.0, eth-query@^2.1.2: json-rpc-random-id "^1.0.0" xtend "^4.0.1" -eth-saddle@^0.1.21: - version "0.1.21" - resolved "https://registry.yarnpkg.com/eth-saddle/-/eth-saddle-0.1.21.tgz#692ac403f6f68c71f3e81336869e2259ab77d97e" - integrity sha512-XsswjrWJaQnixrQk7ycL8fOUoqqyRbkSo9TkGJrgxNNcYjtF6/wFOjxgfwxxd3FIQWLCuAF4jcO6RpFRiEAh4Q== +eth-saddle@^0.1.25: + version "0.1.25" + resolved "https://registry.yarnpkg.com/eth-saddle/-/eth-saddle-0.1.25.tgz#8bbfefa6eabcdaca0c88e838fa60213e9fff9d8b" + integrity sha512-BUames0/ap3Cm7bJVjp0sFfTxKUv+xK+zbwZLYQghky9KrfowlURqBZgJHPxF3w9HyCh95UQBY5QsIeed1Ppqw== dependencies: - "@0x/subproviders" "^6.0.0" - "@compound-finance/sol-coverage" "^4.0.10-alpha.7" - "@compound-finance/sol-tracing-utils" "7.1.0-alpha.7" + "@0x/subproviders" "=6.0.0" + "@compound-finance/sol-coverage" "=4.0.10-alpha.7" + "@compound-finance/sol-tracing-utils" "=7.1.0-alpha.7" "@types/jest" "^24.0.15" ethereumjs-tx "2.1.2" ethereumjs-util "5.2.0" fast-glob "^3.2.2" - ganache-core "^2.10.2" + ganache-core "^2.13.2" jest "^24.9.0" jest-cli "^24.9.0" jest-diff "^25.3.0" @@ -4729,40 +4837,40 @@ ethers@4.0.0-beta.3: xmlhttprequest "1.8.0" ethers@^5.0.8: - version "5.0.8" - resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.0.8.tgz#c13d0fdf5e66db8085e2036d3309ed2f8a17ed89" - integrity sha512-of/rPgJ7E3yyBADUv5A7Gtkd7EB8ta/T9NS5CCG9tj9cifnXcI3KIdYQ7d8AS+9vm38pR1g6S5I+Q/mRnlQZlg== - dependencies: - "@ethersproject/abi" "^5.0.0" - "@ethersproject/abstract-provider" "^5.0.0" - "@ethersproject/abstract-signer" "^5.0.0" - "@ethersproject/address" "^5.0.0" - "@ethersproject/base64" "^5.0.0" - "@ethersproject/basex" "^5.0.0" - "@ethersproject/bignumber" "^5.0.0" - "@ethersproject/bytes" "^5.0.0" - "@ethersproject/constants" "^5.0.0" - "@ethersproject/contracts" "^5.0.0" - "@ethersproject/hash" "^5.0.0" - "@ethersproject/hdnode" "^5.0.0" - "@ethersproject/json-wallets" "^5.0.0" - "@ethersproject/keccak256" "^5.0.0" - "@ethersproject/logger" "^5.0.0" - "@ethersproject/networks" "^5.0.0" - "@ethersproject/pbkdf2" "^5.0.0" - "@ethersproject/properties" "^5.0.0" - "@ethersproject/providers" "^5.0.0" - "@ethersproject/random" "^5.0.0" - "@ethersproject/rlp" "^5.0.0" - "@ethersproject/sha2" "^5.0.0" - "@ethersproject/signing-key" "^5.0.0" - "@ethersproject/solidity" "^5.0.0" - "@ethersproject/strings" "^5.0.0" - "@ethersproject/transactions" "^5.0.0" - "@ethersproject/units" "^5.0.0" - "@ethersproject/wallet" "^5.0.0" - "@ethersproject/web" "^5.0.0" - "@ethersproject/wordlists" "^5.0.0" + version "5.4.6" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.4.6.tgz#fe0a023956b5502c947f58e82fbcf9a73e5e75b6" + integrity sha512-F7LXARyB/Px3AQC6/QKedWZ8eqCkgOLORqL4B/F0Mag/K+qJSFGqsR36EaOZ6fKg3ZonI+pdbhb4A8Knt/43jQ== + dependencies: + "@ethersproject/abi" "5.4.1" + "@ethersproject/abstract-provider" "5.4.1" + "@ethersproject/abstract-signer" "5.4.1" + "@ethersproject/address" "5.4.0" + "@ethersproject/base64" "5.4.0" + "@ethersproject/basex" "5.4.0" + "@ethersproject/bignumber" "5.4.1" + "@ethersproject/bytes" "5.4.0" + "@ethersproject/constants" "5.4.0" + "@ethersproject/contracts" "5.4.1" + "@ethersproject/hash" "5.4.0" + "@ethersproject/hdnode" "5.4.0" + "@ethersproject/json-wallets" "5.4.0" + "@ethersproject/keccak256" "5.4.0" + "@ethersproject/logger" "5.4.1" + "@ethersproject/networks" "5.4.2" + "@ethersproject/pbkdf2" "5.4.0" + "@ethersproject/properties" "5.4.1" + "@ethersproject/providers" "5.4.5" + "@ethersproject/random" "5.4.0" + "@ethersproject/rlp" "5.4.0" + "@ethersproject/sha2" "5.4.0" + "@ethersproject/signing-key" "5.4.0" + "@ethersproject/solidity" "5.4.0" + "@ethersproject/strings" "5.4.0" + "@ethersproject/transactions" "5.4.0" + "@ethersproject/units" "5.4.0" + "@ethersproject/wallet" "5.4.0" + "@ethersproject/web" "5.4.0" + "@ethersproject/wordlists" "5.4.0" ethers@~4.0.4: version "4.0.40" @@ -5346,7 +5454,7 @@ functional-red-black-tree@^1.0.1, functional-red-black-tree@~1.0.1: resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= -ganache-core@^2.10.2, ganache-core@^2.6.0, "ganache-core@github:compound-finance/ganache-core.git#jflatow/unbreak-fork": +ganache-core@^2.10.2, ganache-core@^2.13.2, ganache-core@^2.6.0, "ganache-core@github:compound-finance/ganache-core.git#jflatow/unbreak-fork": version "2.10.2" resolved "https://codeload.github.com/compound-finance/ganache-core/tar.gz/4c7e063f6d423e1b3850f4cb328029e819670a64" dependencies: @@ -5839,7 +5947,7 @@ hash.js@1.1.3: inherits "^2.0.3" minimalistic-assert "^1.0.0" -hash.js@^1.0.0, hash.js@^1.0.3: +hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3: version "1.1.7" resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== @@ -5874,7 +5982,7 @@ heap@0.2.6: resolved "https://registry.yarnpkg.com/heap/-/heap-0.2.6.tgz#087e1f10b046932fc8594dd9e6d378afc9d1e5ac" integrity sha1-CH4fELBGky/IWU3Z5tN4r8nR5aw= -hmac-drbg@^1.0.0: +hmac-drbg@^1.0.0, hmac-drbg@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= @@ -11814,10 +11922,10 @@ write-file-atomic@2.4.1: imurmurhash "^0.1.4" signal-exit "^3.0.2" -ws@7.2.3: - version "7.2.3" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.2.3.tgz#a5411e1fb04d5ed0efee76d26d5c46d830c39b46" - integrity sha512-HTDl9G9hbkNDk98naoR/cHDws7+EyYMOdL1BmjsZXRUjf7d+MficC4B7HLUPlSiho0vg+CWKrGIt/VJBd1xunQ== +ws@7.4.6: + version "7.4.6" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" + integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== ws@^3.0.0: version "3.3.3" diff --git a/script/build_scenarios b/script/build_scenarios index 2956f2a8c..282716974 100755 --- a/script/build_scenarios +++ b/script/build_scenarios @@ -10,7 +10,7 @@ cache_file="$root_dir/.scencache" shasumVersion="$(shasum -v)" inflectionVersion="6.01" -if [ "$(printf '%s\n' "$inflectionVersion" "$shasumVersion" | sort -V | head -n1)" = "$inflectionVersion" ]; then +if [ "$(printf '%s\n' "$inflectionVersion" "$shasumVersion" | sort -V | head -n1)" = "$inflectionVersion" ]; then checksum="$(echo $root_dir/spec/scenario{,/**}/*.scen | xargs shasum -U | shasum -U | cut -d' ' -f 1)" else checksum="$(echo $root_dir/spec/scenario{,/**}/*.scen | xargs shasum -p | shasum -p | cut -d' ' -f 1)" diff --git a/script/compile b/script/compile index 9c75c076a..ec489f438 100755 --- a/script/compile +++ b/script/compile @@ -11,7 +11,7 @@ config_trace=`node -e "console.log(require(\"$saddle_config_file\").trace)"` shasumVersion="$(shasum -v)" inflectionVersion="6.01" -if [ "$(printf '%s\n' "$inflectionVersion" "$shasumVersion" | sort -V | head -n1)" = "$inflectionVersion" ]; then +if [ "$(printf '%s\n' "$inflectionVersion" "$shasumVersion" | sort -V | head -n1)" = "$inflectionVersion" ]; then checksum="$(ls $root_dir/{contracts,contracts/**,tests/Contracts}/*.sol | xargs shasum -U | shasum -U | cut -d' ' -f 1)" else checksum="$(ls $root_dir/{contracts,contracts/**,tests/Contracts}/*.sol | xargs shasum -p | shasum -p | cut -d' ' -f 1)" diff --git a/script/lint b/script/lint index 743b7f4b8..8ae8d66d4 100755 --- a/script/lint +++ b/script/lint @@ -5,5 +5,4 @@ set -eo pipefail DIR=`dirname $0` PROJ_ROOT="$DIR/.." -"$PROJ_ROOT/node_modules/.bin/solium" -d "$PROJ_ROOT/tests" -"$PROJ_ROOT/node_modules/.bin/solium" -d "$PROJ_ROOT/contracts" +"$PROJ_ROOT/node_modules/.bin/solhint" "$PROJ_ROOT/{tests,contracts}/**/*.sol" diff --git a/spec/certora/contracts/CDaiDelegateCertora.sol b/spec/certora/contracts/CDaiDelegateCertora.sol index 6a8c2b977..b93c362c1 100644 --- a/spec/certora/contracts/CDaiDelegateCertora.sol +++ b/spec/certora/contracts/CDaiDelegateCertora.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.16; +pragma solidity ^0.8.10; import "../../../contracts/CDaiDelegate.sol"; diff --git a/spec/certora/contracts/CErc20DelegateCertora.sol b/spec/certora/contracts/CErc20DelegateCertora.sol index ee3ec3ec9..5ea2a980e 100644 --- a/spec/certora/contracts/CErc20DelegateCertora.sol +++ b/spec/certora/contracts/CErc20DelegateCertora.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.16; +pragma solidity ^0.8.10; import "../../../contracts/CErc20Delegate.sol"; import "../../../contracts/EIP20Interface.sol"; diff --git a/spec/certora/contracts/CErc20DelegatorCertora.sol b/spec/certora/contracts/CErc20DelegatorCertora.sol index 87394538c..f6870bca3 100644 --- a/spec/certora/contracts/CErc20DelegatorCertora.sol +++ b/spec/certora/contracts/CErc20DelegatorCertora.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.16; +pragma solidity ^0.8.10; import "../../../contracts/CErc20Delegator.sol"; import "../../../contracts/EIP20Interface.sol"; diff --git a/spec/certora/contracts/CErc20ImmutableCertora.sol b/spec/certora/contracts/CErc20ImmutableCertora.sol index 1b345086f..83ec98422 100644 --- a/spec/certora/contracts/CErc20ImmutableCertora.sol +++ b/spec/certora/contracts/CErc20ImmutableCertora.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.16; +pragma solidity ^0.8.10; import "../../../contracts/CErc20Immutable.sol"; import "../../../contracts/EIP20Interface.sol"; diff --git a/spec/certora/contracts/CEtherCertora.sol b/spec/certora/contracts/CEtherCertora.sol index 6ac66c429..259efc277 100644 --- a/spec/certora/contracts/CEtherCertora.sol +++ b/spec/certora/contracts/CEtherCertora.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.16; +pragma solidity ^0.8.10; import "../../../contracts/CEther.sol"; diff --git a/spec/certora/contracts/CTokenCollateral.sol b/spec/certora/contracts/CTokenCollateral.sol index c36105432..5862c2458 100644 --- a/spec/certora/contracts/CTokenCollateral.sol +++ b/spec/certora/contracts/CTokenCollateral.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.16; +pragma solidity ^0.8.10; import "../../../contracts/CErc20Immutable.sol"; import "../../../contracts/EIP20Interface.sol"; diff --git a/spec/certora/contracts/CompCertora.sol b/spec/certora/contracts/CompCertora.sol index 487647607..0569d2cbc 100644 --- a/spec/certora/contracts/CompCertora.sol +++ b/spec/certora/contracts/CompCertora.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.16; +pragma solidity ^0.8.10; import "../../../contracts/Governance/Comp.sol"; diff --git a/spec/certora/contracts/ComptrollerCertora.sol b/spec/certora/contracts/ComptrollerCertora.sol index 5f78d1691..3c7316b09 100644 --- a/spec/certora/contracts/ComptrollerCertora.sol +++ b/spec/certora/contracts/ComptrollerCertora.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.16; +pragma solidity ^0.8.10; import "../../../contracts/Comptroller.sol"; @@ -10,7 +10,7 @@ contract ComptrollerCertora is Comptroller { address account, CToken cTokenModify, uint redeemTokens, - uint borrowAmount) internal view returns (Error, uint, uint) { + uint borrowAmount) override internal view returns (Error, uint, uint) { if (switcher == 0) return (Error.NO_ERROR, liquidityOrShortfall, 0); if (switcher == 1) diff --git a/spec/certora/contracts/GovernorAlphaCertora.sol b/spec/certora/contracts/GovernorAlphaCertora.sol index 27e59c686..4b4a327eb 100644 --- a/spec/certora/contracts/GovernorAlphaCertora.sol +++ b/spec/certora/contracts/GovernorAlphaCertora.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.16; +pragma solidity ^0.8.10; pragma experimental ABIEncoderV2; import "../../../contracts/Governance/GovernorAlpha.sol"; diff --git a/spec/certora/contracts/InterestRateModelModel.sol b/spec/certora/contracts/InterestRateModelModel.sol index 85b044961..c7ab9478d 100644 --- a/spec/certora/contracts/InterestRateModelModel.sol +++ b/spec/certora/contracts/InterestRateModelModel.sol @@ -1,21 +1,20 @@ -pragma solidity ^0.5.16; +pragma solidity ^0.8.10; -import "../../../contracts/Exponential.sol"; import "../../../contracts/InterestRateModel.sol"; contract InterestRateModelModel is InterestRateModel { uint borrowDummy; uint supplyDummy; - function isInterestRateModel() external pure returns (bool) { + function isInterestRateModel() override external pure returns (bool) { return true; } - function getBorrowRate(uint _cash, uint _borrows, uint _reserves) external view returns (uint) { + function getBorrowRate(uint _cash, uint _borrows, uint _reserves) override external view returns (uint) { return borrowDummy; } - function getSupplyRate(uint _cash, uint _borrows, uint _reserves, uint _reserveFactorMantissa) external view returns (uint) { + function getSupplyRate(uint _cash, uint _borrows, uint _reserves, uint _reserveFactorMantissa) override external view returns (uint) { return supplyDummy; } } diff --git a/spec/certora/contracts/MathCertora.sol b/spec/certora/contracts/MathCertora.sol index 5e853739e..4a7911a60 100644 --- a/spec/certora/contracts/MathCertora.sol +++ b/spec/certora/contracts/MathCertora.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.16; +pragma solidity ^0.8.10; contract MathCertora { diff --git a/spec/certora/contracts/MaximillionCertora.sol b/spec/certora/contracts/MaximillionCertora.sol index c178836b0..924412081 100644 --- a/spec/certora/contracts/MaximillionCertora.sol +++ b/spec/certora/contracts/MaximillionCertora.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.16; +pragma solidity ^0.8.10; import "../../../contracts/Maximillion.sol"; @@ -13,7 +13,7 @@ contract MaximillionCertora is Maximillion { return account.balance; } - function repayBehalf(address borrower) public payable { + function repayBehalf(address borrower) override public payable { return super.repayBehalf(borrower); } -} \ No newline at end of file +} diff --git a/spec/certora/contracts/PriceOracleModel.sol b/spec/certora/contracts/PriceOracleModel.sol index 030c73e69..9d4bce24b 100644 --- a/spec/certora/contracts/PriceOracleModel.sol +++ b/spec/certora/contracts/PriceOracleModel.sol @@ -1,15 +1,15 @@ -pragma solidity ^0.5.16; +pragma solidity ^0.8.10; import "../../../contracts/PriceOracle.sol"; contract PriceOracleModel is PriceOracle { uint dummy; - function isPriceOracle() external pure returns (bool) { + function isPriceOracle() override external pure returns (bool) { return true; } - function getUnderlyingPrice(CToken cToken) external view returns (uint) { + function getUnderlyingPrice(CToken cToken) override external view returns (uint) { return dummy; } -} \ No newline at end of file +} diff --git a/spec/certora/contracts/SimulationInterface.sol b/spec/certora/contracts/SimulationInterface.sol index 3a7f61b4a..034ea2e55 100644 --- a/spec/certora/contracts/SimulationInterface.sol +++ b/spec/certora/contracts/SimulationInterface.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.16; +pragma solidity ^0.8.10; interface SimulationInterface { function dummy() external; diff --git a/spec/certora/contracts/TimelockCertora.sol b/spec/certora/contracts/TimelockCertora.sol index f434717bf..2e6c60b83 100644 --- a/spec/certora/contracts/TimelockCertora.sol +++ b/spec/certora/contracts/TimelockCertora.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.16; +pragma solidity ^0.8.10; import "../../../contracts/Timelock.sol"; diff --git a/spec/certora/contracts/UnderlyingModelNonStandard.sol b/spec/certora/contracts/UnderlyingModelNonStandard.sol index 4711d9ba6..4419904d0 100644 --- a/spec/certora/contracts/UnderlyingModelNonStandard.sol +++ b/spec/certora/contracts/UnderlyingModelNonStandard.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.16; +pragma solidity ^0.8.10; import "../../../contracts/EIP20NonStandardInterface.sol"; @@ -9,15 +9,15 @@ contract UnderlyingModelNonStandard is EIP20NonStandardInterface, SimulationInte mapping (address => uint256) balances; mapping (address => mapping (address => uint256)) allowances; - function totalSupply() external view returns (uint256) { + function totalSupply() override external view returns (uint256) { return _totalSupply; } - function balanceOf(address owner) external view returns (uint256 balance) { + function balanceOf(address owner) override external view returns (uint256 balance) { balance = balances[owner]; } - function transfer(address dst, uint256 amount) external { + function transfer(address dst, uint256 amount) override external { address src = msg.sender; require(balances[src] >= amount); require(balances[dst] + amount >= balances[dst]); @@ -26,7 +26,7 @@ contract UnderlyingModelNonStandard is EIP20NonStandardInterface, SimulationInte balances[dst] += amount; } - function transferFrom(address src, address dst, uint256 amount) external { + function transferFrom(address src, address dst, uint256 amount) override external { require(allowances[src][msg.sender] >= amount); require(balances[src] >= amount); require(balances[dst] + amount >= balances[dst]); @@ -36,15 +36,15 @@ contract UnderlyingModelNonStandard is EIP20NonStandardInterface, SimulationInte balances[dst] += amount; } - function approve(address spender, uint256 amount) external returns (bool success) { + function approve(address spender, uint256 amount) override external returns (bool success) { allowances[msg.sender][spender] = amount; } - function allowance(address owner, address spender) external view returns (uint256 remaining) { + function allowance(address owner, address spender) override external view returns (uint256 remaining) { remaining = allowances[owner][spender]; } - function dummy() external { + function dummy() override external { return; } -} \ No newline at end of file +} diff --git a/spec/certora/contracts/UnderlyingModelWithFee.sol b/spec/certora/contracts/UnderlyingModelWithFee.sol index 8c09dd758..63a813eb4 100644 --- a/spec/certora/contracts/UnderlyingModelWithFee.sol +++ b/spec/certora/contracts/UnderlyingModelWithFee.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.16; +pragma solidity ^0.8.10; import "../../../contracts/EIP20NonStandardInterface.sol"; @@ -10,15 +10,15 @@ contract UnderlyingModelWithFee is EIP20NonStandardInterface, SimulationInterfac mapping (address => uint256) balances; mapping (address => mapping (address => uint256)) allowances; - function totalSupply() external view returns (uint256) { + function totalSupply() override external view returns (uint256) { return _totalSupply; } - function balanceOf(address owner) external view returns (uint256 balance) { + function balanceOf(address owner) override external view returns (uint256 balance) { balance = balances[owner]; } - function transfer(address dst, uint256 amount) external { + function transfer(address dst, uint256 amount) override external { address src = msg.sender; uint256 actualAmount = amount + fee; require(actualAmount >= amount); @@ -29,9 +29,9 @@ contract UnderlyingModelWithFee is EIP20NonStandardInterface, SimulationInterfac balances[dst] += actualAmount; } - function transferFrom(address src, address dst, uint256 amount) external { + function transferFrom(address src, address dst, uint256 amount) override external { uint256 actualAmount = amount + fee; - require(actualAmount > fee) + require(actualAmount > fee); require(allowances[src][msg.sender] >= actualAmount); require(balances[src] >= actualAmount); require(balances[dst] + actualAmount >= balances[dst]); @@ -41,15 +41,15 @@ contract UnderlyingModelWithFee is EIP20NonStandardInterface, SimulationInterfac balances[dst] += actualAmount; } - function approve(address spender, uint256 amount) external returns (bool success) { + function approve(address spender, uint256 amount) override external returns (bool success) { allowances[msg.sender][spender] = amount; } - function allowance(address owner, address spender) external view returns (uint256 remaining) { + function allowance(address owner, address spender) override external view returns (uint256 remaining) { remaining = allowances[owner][spender]; } - function dummy() external { + function dummy() override external { return; } -} \ No newline at end of file +} diff --git a/spec/certora/contracts/mcd/Dai.sol b/spec/certora/contracts/mcd/Dai.sol index 522aaaf2a..1ed588ad3 100644 --- a/spec/certora/contracts/mcd/Dai.sol +++ b/spec/certora/contracts/mcd/Dai.sol @@ -13,7 +13,7 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -pragma solidity ^0.5.16; +pragma solidity ^0.8.10; import "./lib.sol"; diff --git a/spec/certora/contracts/mcd/Lib.sol b/spec/certora/contracts/mcd/Lib.sol index afa8bd069..a3072e9c7 100644 --- a/spec/certora/contracts/mcd/Lib.sol +++ b/spec/certora/contracts/mcd/Lib.sol @@ -11,7 +11,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pragma solidity ^0.5.16; +pragma solidity ^0.8.10; contract LibNote { event LogNote( diff --git a/spec/certora/contracts/mcd/Pot.sol b/spec/certora/contracts/mcd/Pot.sol index d5ac37417..58aa1e849 100644 --- a/spec/certora/contracts/mcd/Pot.sol +++ b/spec/certora/contracts/mcd/Pot.sol @@ -15,7 +15,7 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -pragma solidity ^0.5.16; +pragma solidity ^0.8.10; import "./lib.sol"; diff --git a/spec/certora/contracts/mcd/Vat.sol b/spec/certora/contracts/mcd/Vat.sol index ce379dbcd..8a802b3af 100644 --- a/spec/certora/contracts/mcd/Vat.sol +++ b/spec/certora/contracts/mcd/Vat.sol @@ -15,7 +15,7 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -pragma solidity ^0.5.16; +pragma solidity ^0.8.10; contract Vat { // --- Auth --- diff --git a/spec/certora/contracts/mcd/join.sol b/spec/certora/contracts/mcd/join.sol index 7d008d5b6..362e19be4 100644 --- a/spec/certora/contracts/mcd/join.sol +++ b/spec/certora/contracts/mcd/join.sol @@ -15,7 +15,7 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -pragma solidity ^0.5.16; +pragma solidity ^0.8.10; import "./lib.sol"; diff --git a/spec/scenario/Borrow.scen b/spec/scenario/Borrow.scen index 203135c19..ad5c77a13 100644 --- a/spec/scenario/Borrow.scen +++ b/spec/scenario/Borrow.scen @@ -17,7 +17,8 @@ Test "Borrow some BAT and enters BAT if BAT not entered" Assert True (Comptroller CheckMembership Geoff cZRX) Assert True (Comptroller CheckMembership Geoff cBAT) -Test "Borrow some BAT fails, but user still entered" +-- Now that we revert instead of returning failures, the user does not get marked as entered +Test "Borrow some BAT fails, user not entered" NewComptroller price:1.0 NewCToken ZRX cZRX NewCToken BAT cBAT @@ -30,10 +31,10 @@ Test "Borrow some BAT fails, but user still entered" Invariant Static (Erc20 BAT TokenBalance cBAT) AllowFailures Borrow Geoff 1e18 cBAT - Assert Failure TOKEN_INSUFFICIENT_CASH BORROW_CASH_NOT_AVAILABLE - Assert Equal (Comptroller MembershipLength Geoff) (Exactly 2) + Assert RevertCustomError BorrowCashNotAvailable + Assert Equal (Comptroller MembershipLength Geoff) (Exactly 1) Assert True (Comptroller CheckMembership Geoff cZRX) - Assert True (Comptroller CheckMembership Geoff cBAT) + Assert False (Comptroller CheckMembership Geoff cBAT) Test "Borrow some BAT fails when no BAT available" NewComptroller price:1.0 @@ -47,7 +48,7 @@ Test "Borrow some BAT fails when no BAT available" Invariant Static (CToken cZRX ExchangeRateStored) AllowFailures Borrow Geoff 1e18 cBAT - Assert Failure TOKEN_INSUFFICIENT_CASH BORROW_CASH_NOT_AVAILABLE + Assert RevertCustomError BorrowCashNotAvailable Test "Borrow fails if market not listed" NewComptroller price:1.0 @@ -60,7 +61,7 @@ Test "Borrow fails if market not listed" EnterMarkets Geoff cZRX AllowFailures Borrow Geoff 1e18 cBAT - Assert Failure COMPTROLLER_REJECTION BORROW_COMPTROLLER_REJECTION MARKET_NOT_LISTED + Assert RevertCustomError BorrowComptrollerRejection 9 Test "Borrow some BAT from Excess Cash" Invariant Success diff --git a/spec/scenario/BorrowEth.scen b/spec/scenario/BorrowEth.scen index 5b95182f7..19896870f 100644 --- a/spec/scenario/BorrowEth.scen +++ b/spec/scenario/BorrowEth.scen @@ -31,7 +31,7 @@ Test "Borrow some ETH fails when no ETH available" Invariant Static (Comptroller Liquidity Geoff) Invariant Static (EtherBalance Geoff) BorrowEth Geoff 1e18 cETH - Assert Failure TOKEN_INSUFFICIENT_CASH BORROW_CASH_NOT_AVAILABLE + Assert RevertCustomError BorrowCashNotAvailable Test "Borrow some ETH from excess cash" NewComptroller price:1.0 diff --git a/spec/scenario/BorrowWBTC.scen b/spec/scenario/BorrowWBTC.scen index ae7d79df4..5a99d0b6d 100644 --- a/spec/scenario/BorrowWBTC.scen +++ b/spec/scenario/BorrowWBTC.scen @@ -27,7 +27,7 @@ Test "Borrow some WBTC fails when no WBTC available" Invariant Static (CToken cZRX ExchangeRateStored) AllowFailures Borrow Geoff 1e8 cWBTC - Assert Failure TOKEN_INSUFFICIENT_CASH BORROW_CASH_NOT_AVAILABLE + Assert RevertCustomError BorrowCashNotAvailable Test "Borrow some WBTC fails when WBTC paused" NewComptroller price:1.0 diff --git a/spec/scenario/CTokenAdmin.scen b/spec/scenario/CTokenAdmin.scen index e658ae1dd..807725a97 100644 --- a/spec/scenario/CTokenAdmin.scen +++ b/spec/scenario/CTokenAdmin.scen @@ -31,7 +31,7 @@ Test "Fail to set pending admin" Invariant Remains (CToken cZRX PendingAdmin) (Address Zero) AllowFailures From Geoff (CToken cZRX SetPendingAdmin Geoff) - Assert Failure UNAUTHORIZED SET_PENDING_ADMIN_OWNER_CHECK + Assert RevertCustomError SetPendingAdminOwnerCheck Test "Fail to accept admin" NewComptroller @@ -40,4 +40,4 @@ Test "Fail to accept admin" Invariant Remains (CToken cZRX PendingAdmin) (Address Zero) AllowFailures From Geoff (CToken cZRX AcceptAdmin) - Assert Failure UNAUTHORIZED ACCEPT_ADMIN_PENDING_ADMIN_CHECK + Assert RevertCustomError AcceptAdminPendingAdminCheck diff --git a/spec/scenario/EnterExitMarkets.scen b/spec/scenario/EnterExitMarkets.scen index 43671f0c0..6c77fd15b 100644 --- a/spec/scenario/EnterExitMarkets.scen +++ b/spec/scenario/EnterExitMarkets.scen @@ -107,7 +107,7 @@ Test "Realistic Market Scenario" HoldInvariants Borrow Geoff 1000e18 cBAT -- 1000e18 * 0.0015 = 1.5e18 required liquidity -- But since we're only in ZRX, we only have 1.0e18 liquidity - Assert Failure COMPTROLLER_REJECTION BORROW_COMPTROLLER_REJECTION INSUFFICIENT_LIQUIDITY + Assert RevertCustomError BorrowComptrollerRejection 4 -- Enter cETH and check liquidity EnterMarkets Geoff cETH Assert Equal (Comptroller Liquidity Geoff) 3.0e18 -- Sum of cETH and cZRX liquidity from above @@ -118,7 +118,7 @@ Test "Realistic Market Scenario" HoldInvariants ExitMarket Geoff cETH Assert Failure REJECTION EXIT_MARKET_REJECTION INSUFFICIENT_LIQUIDITY -- Liquidity check fails - Assert Equal (Comptroller AssetsIn Geoff) [(Address cZRX) (Address cBAT) (Address cETH)] + Assert Equal (Comptroller AssetsIn Geoff) [(Address cZRX) (Address cETH) (Address cBAT)] -- Repay some borrow and exit market OMG Allow Geoff cBAT RepayBorrow Geoff 500e18 cBAT diff --git a/spec/scenario/InKindLiquidation.scen b/spec/scenario/InKindLiquidation.scen index 8db271a5b..f3221b979 100644 --- a/spec/scenario/InKindLiquidation.scen +++ b/spec/scenario/InKindLiquidation.scen @@ -38,7 +38,7 @@ Test "Insufficient in-kind shortfall" Prep Torrey 10e18 BAT cBAT AllowFailures Liquidate Torrey "->" Geoff 10e18 cBAT "Seizing" cBAT - Assert Failure COMPTROLLER_REJECTION LIQUIDATE_COMPTROLLER_REJECTION INSUFFICIENT_SHORTFALL + Assert RevertCustomError LiquidateComptrollerRejection 3 Test "Cannot self-in-kind-liquidate" InKindBorrow borrowAmount:1e18 borrowRate:0.000005 @@ -67,7 +67,7 @@ Test "Cannot self-in-kind-liquidate" Prep Geoff 10e18 BAT cBAT AllowFailures Liquidate Geoff "->" Geoff 2e18 cBAT "Seizing" cBAT - Assert Failure INVALID_ACCOUNT_PAIR LIQUIDATE_LIQUIDATOR_IS_BORROWER + Assert RevertCustomError LiquidateLiquidatorIsBorrower Test "Liqidate in-kind beyond max close" InKindBorrow borrowAmount:1e18 borrowRate:0.000005 @@ -96,7 +96,7 @@ Test "Liqidate in-kind beyond max close" Prep Torrey 20e18 BAT cBAT AllowFailures Liquidate Torrey "->" Geoff 20e18 cBAT "Seizing" cBAT - Assert Failure COMPTROLLER_REJECTION LIQUIDATE_COMPTROLLER_REJECTION TOO_MUCH_REPAY + Assert RevertCustomError LiquidateComptrollerRejection 17 Test "Proper In-Kind Liquidation" InKindBorrow borrowAmount:1e18 borrowRate:0.000005 @@ -181,7 +181,7 @@ Test "Liquidate exactly zero" Prep Torrey 10e18 BAT cBAT AllowFailures Liquidate Torrey "->" Geoff 0e18 cBAT "Seizing" cBAT - Assert Failure INVALID_CLOSE_AMOUNT_REQUESTED LIQUIDATE_CLOSE_AMOUNT_IS_ZERO + Assert RevertCustomError LiquidateCloseAmountIsZero Test "When price oracle for collateral token is zero" InKindBorrow borrowAmount:1e18 borrowRate:0.000005 @@ -211,7 +211,7 @@ Test "When price oracle for collateral token is zero" PriceOracle SetPrice cBAT 0 AllowFailures Liquidate Torrey "->" Geoff 2e18 cBAT "Seizing" cBAT - Assert Failure COMPTROLLER_REJECTION LIQUIDATE_COMPTROLLER_REJECTION PRICE_ERROR + Assert RevertCustomError LiquidateComptrollerRejection 13 Test "When price oracle for collateral token is whack" InKindBorrow borrowAmount:1e18 borrowRate:0.000005 @@ -241,7 +241,7 @@ Test "When price oracle for collateral token is whack" PriceOracle SetPrice cBAT 1.15792e59 AllowFailures Liquidate Torrey "->" Geoff 2e18 cBAT "Seizing" cBAT - Assert Revert "revert multiplication overflow" + Assert Revert -- Multiplication Overflow Test "When repay borrow fails" InKindBorrow borrowAmount:1e18 borrowRate:0.000005 @@ -343,7 +343,7 @@ Test "When seize not allowed due to unlisted collateral" Comptroller UnList cBAT -- Mock unlist collateral AllowFailures Liquidate Torrey "->" Geoff 2e18 cBAT "Seizing" cBAT - Assert Failure COMPTROLLER_REJECTION LIQUIDATE_COMPTROLLER_REJECTION MARKET_NOT_LISTED + Assert RevertCustomError LiquidateComptrollerRejection 9 Test "When seize not allowed due to unlisted borrow" InKindBorrow borrowAmount:1e18 borrowRate:0.000005 @@ -371,7 +371,7 @@ Test "When seize not allowed due to unlisted borrow" Comptroller UnList cBAT -- Mock unlist borrow AllowFailures Liquidate Torrey "->" Geoff 2e18 cBAT "Seizing" cBAT - Assert Failure COMPTROLLER_REJECTION LIQUIDATE_COMPTROLLER_REJECTION MARKET_NOT_LISTED + Assert RevertCustomError LiquidateComptrollerRejection 9 Test "When there's insufficient collateral" InKindBorrow borrowAmount:1e18 borrowRate:0.000005 diff --git a/spec/scenario/Mint.scen b/spec/scenario/Mint.scen index 4d31f0758..4a23ad7eb 100644 --- a/spec/scenario/Mint.scen +++ b/spec/scenario/Mint.scen @@ -87,7 +87,7 @@ Test "Denied by comptroller because unlisted" Invariant Static (Erc20 ZRX TotalSupply) AllowFailures Mint Geoff 2e18 cZRX - Assert Failure COMPTROLLER_REJECTION MINT_COMPTROLLER_REJECTION MARKET_NOT_LISTED + Assert RevertCustomError MintComptrollerRejection 9 Test "mint reverts if mint is paused" NewComptroller diff --git a/spec/scenario/MintWBTC.scen b/spec/scenario/MintWBTC.scen index 70fae947e..919a1cc7a 100644 --- a/spec/scenario/MintWBTC.scen +++ b/spec/scenario/MintWBTC.scen @@ -90,4 +90,4 @@ Test "Denied by comptroller because WBTC unlisted" Invariant Static (Erc20 WBTC TotalSupply) AllowFailures Mint Geoff 2e8 cWBTC - Assert Failure COMPTROLLER_REJECTION MINT_COMPTROLLER_REJECTION MARKET_NOT_LISTED + Assert RevertCustomError MintComptrollerRejection 9 diff --git a/spec/scenario/Redeem.scen b/spec/scenario/Redeem.scen index df6d6d061..7b0b97bc4 100644 --- a/spec/scenario/Redeem.scen +++ b/spec/scenario/Redeem.scen @@ -62,7 +62,7 @@ Test "Mint then Redeem Too Much" FastForward 2 Blocks AllowFailures Redeem Geoff 501e8 cZRX - Assert Failure MATH_ERROR REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED "3" + Assert Revert Test "Mint then Redeem Zero" NewComptroller @@ -207,7 +207,7 @@ Test "Mint, Enter, then Redeem Too Much (collateral factor: 0)" EnterMarkets Geoff cZRX AllowFailures Redeem Geoff 501e8 cZRX - Assert Failure MATH_ERROR REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED "3" + Assert Revert Test "Mint, Enter, then Redeem Too Much (collateral factor: 0.1)" NewComptroller @@ -224,4 +224,4 @@ Test "Mint, Enter, then Redeem Too Much (collateral factor: 0.1)" EnterMarkets Geoff cZRX AllowFailures Redeem Geoff 501e8 cZRX - Assert Failure COMPTROLLER_REJECTION REDEEM_COMPTROLLER_REJECTION INSUFFICIENT_LIQUIDITY + Assert RevertCustomError RedeemComptrollerRejection 4 diff --git a/spec/scenario/RedeemEth.scen b/spec/scenario/RedeemEth.scen index 3985fb686..7a6740a5d 100644 --- a/spec/scenario/RedeemEth.scen +++ b/spec/scenario/RedeemEth.scen @@ -44,7 +44,7 @@ Test "Mint then Redeem Too Much" RedeemEth Geoff 11e8 cETH -- TODO: This should really be REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED, but based on -- the order of subtractions, total supply comes before account supply. - Assert Failure MATH_ERROR REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED "3" -- TODO: This error is wrong + Assert Revert Test "Mint then Redeem Zero" NewComptroller diff --git a/spec/scenario/RedeemUnderlying.scen b/spec/scenario/RedeemUnderlying.scen index afea3436e..0615dbf64 100644 --- a/spec/scenario/RedeemUnderlying.scen +++ b/spec/scenario/RedeemUnderlying.scen @@ -45,7 +45,7 @@ Test "Mint then Redeem Too Much" FastForward 2 Blocks AllowFailures RedeemUnderlying Geoff 50.1e18 cZRX - Assert Failure MATH_ERROR REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED "3" + Assert Revert Test "Mint then Redeem Zero" NewComptroller diff --git a/spec/scenario/RedeemUnderlyingEth.scen b/spec/scenario/RedeemUnderlyingEth.scen index c03ab5a8b..abd0794b3 100644 --- a/spec/scenario/RedeemUnderlyingEth.scen +++ b/spec/scenario/RedeemUnderlyingEth.scen @@ -44,7 +44,7 @@ Test "Mint then Redeem Too Much" RedeemUnderlyingEth Geoff 0.0055e18 cETH -- TODO: This should really be REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED, but based on -- the order of subtractions, total supply comes before account supply. - Assert Failure MATH_ERROR REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED "3" -- TODO: This error is wrong + Assert Revert Test "Mint then Redeem Zero" NewComptroller diff --git a/spec/scenario/RedeemUnderlyingWBTC.scen b/spec/scenario/RedeemUnderlyingWBTC.scen index d3c058a5e..19f848d7c 100644 --- a/spec/scenario/RedeemUnderlyingWBTC.scen +++ b/spec/scenario/RedeemUnderlyingWBTC.scen @@ -45,7 +45,7 @@ Test "Mint then Redeem Too Much" FastForward 2 Blocks AllowFailures RedeemUnderlying Geoff 50.1e8 cWBTC - Assert Failure MATH_ERROR REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED "3" + Assert Revert Test "Mint then Redeem Zero" NewComptroller diff --git a/spec/scenario/RedeemWBTC.scen b/spec/scenario/RedeemWBTC.scen index b95ea0da2..562438ae8 100644 --- a/spec/scenario/RedeemWBTC.scen +++ b/spec/scenario/RedeemWBTC.scen @@ -62,7 +62,7 @@ Test "Mint WBTC then Redeem Too Much" FastForward 2 Blocks AllowFailures Redeem Geoff 501e8 cWBTC - Assert Failure MATH_ERROR REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED "3" + Assert Revert Test "Mint WBTC then Redeem Zero" NewComptroller @@ -206,7 +206,7 @@ Test "Mint WBTC, Enter, then Redeem Too Much (collateral factor: 0)" EnterMarkets Geoff cWBTC AllowFailures Redeem Geoff 501e8 cWBTC - Assert Failure MATH_ERROR REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED "3" + Assert Revert Test "Mint WBTC, Enter, then Redeem Too Much (collateral factor: 0.1)" NewComptroller @@ -223,4 +223,4 @@ Test "Mint WBTC, Enter, then Redeem Too Much (collateral factor: 0.1)" EnterMarkets Geoff cWBTC AllowFailures Redeem Geoff 501e8 cWBTC - Assert Failure COMPTROLLER_REJECTION REDEEM_COMPTROLLER_REJECTION INSUFFICIENT_LIQUIDITY + Assert RevertCustomError RedeemComptrollerRejection 4 diff --git a/spec/scenario/RepayBorrow.scen b/spec/scenario/RepayBorrow.scen index ffdadf878..ca3c11412 100644 --- a/spec/scenario/RepayBorrow.scen +++ b/spec/scenario/RepayBorrow.scen @@ -68,7 +68,7 @@ Test "Borrow, hold a few blocks, and repay too much" Expect Changes (Erc20 BAT TokenBalance Geoff) Zero Expect Changes (Erc20 BAT TokenBalance cBAT) Zero RepayBorrow Geoff 10e18 cBAT - Assert Revert "revert REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED" + Assert Revert -- Let's check the overall numbers Assert Equal (CToken cBAT BorrowBalance Geoff) 2.5e18 Assert Equal (CToken cBAT TotalBorrowsCurrent) 2.5e18 @@ -131,7 +131,7 @@ Test "Prohibit repay by comptroller rejection due to mock unlist" Expect Changes (Erc20 BAT TokenBalance cBAT) Zero Comptroller UnList cZRX -- Mock unlist ZRX RepayBorrow Geoff 2.5e18 cZRX - Assert Failure COMPTROLLER_REJECTION REPAY_BORROW_COMPTROLLER_REJECTION MARKET_NOT_LISTED + Assert RevertCustomError RepayBorrowComptrollerRejection 9 -- Let's check the overall numbers Assert Equal (CToken cBAT BorrowBalance Geoff) 2.5e18 Assert Equal (CToken cBAT TotalBorrowsCurrent) 2.5e18 diff --git a/spec/scenario/RepayBorrowEth.scen b/spec/scenario/RepayBorrowEth.scen index 64f053337..abb5a5907 100644 --- a/spec/scenario/RepayBorrowEth.scen +++ b/spec/scenario/RepayBorrowEth.scen @@ -133,7 +133,7 @@ Test "Borrow, hold a few blocks, and repay too much" -- TODO: This currently drains the sent-eth AllowFailures RepayBorrowEth Geoff 1.0e18 cETH - Assert Revert "revert REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED" + Assert Revert -- Let's check the overall numbers Assert Equal (CToken cETH BorrowBalance Geoff) 0.0025e18 Assert Equal (CToken cETH TotalBorrowsCurrent) 0.0025e18 @@ -200,7 +200,7 @@ Test "Prohibit repay by comptroller hook" Comptroller UnList cETH -- Mock unlist cETH AllowFailures RepayBorrowEth Geoff 0.001e18 cETH - Assert RevertFailure COMPTROLLER_REJECTION "revert repayBorrow failed" + Assert RevertCustomError RepayBorrowComptrollerRejection 9 ---- Let's check the overall numbers Assert Equal (CToken cETH BorrowBalance Geoff) 0.0025e18 Assert Equal (CToken cETH TotalBorrowsCurrent) 0.0025e18 diff --git a/spec/scenario/RepayBorrowWBTC.scen b/spec/scenario/RepayBorrowWBTC.scen index b28648098..765ee5320 100644 --- a/spec/scenario/RepayBorrowWBTC.scen +++ b/spec/scenario/RepayBorrowWBTC.scen @@ -68,7 +68,7 @@ Test "Borrow, hold a few blocks, and repay too much" Expect Changes (Erc20 WBTC TokenBalance Geoff) Zero Expect Changes (Erc20 WBTC TokenBalance cWBTC) Zero RepayBorrow Geoff 10e8 cWBTC - Assert Revert "revert REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED" + Assert Revert -- Let's check the overall numbers Assert Equal (CToken cWBTC BorrowBalance Geoff) 2.5e8 Assert Equal (CToken cWBTC TotalBorrowsCurrent) 2.5e8 @@ -131,7 +131,7 @@ Test "Prohibit repay by comptroller rejection due to mock unlist" Expect Changes (Erc20 WBTC TokenBalance cWBTC) Zero Comptroller UnList cZRX -- Mock unlist ZRX RepayBorrow Geoff 2.5e8 cZRX - Assert Failure COMPTROLLER_REJECTION REPAY_BORROW_COMPTROLLER_REJECTION MARKET_NOT_LISTED + Assert RevertCustomError RepayBorrowComptrollerRejection 9 -- Let's check the overall numbers Assert Equal (CToken cWBTC BorrowBalance Geoff) 2.5e8 Assert Equal (CToken cWBTC TotalBorrowsCurrent) 2.5e8 diff --git a/spec/scenario/Seize.scen b/spec/scenario/Seize.scen index 0b1cc750f..ac52bfc20 100644 --- a/spec/scenario/Seize.scen +++ b/spec/scenario/Seize.scen @@ -9,7 +9,7 @@ Test "Fail to seize calling directly" AllowFailures Seize 1e9 cZRX caller:Geoff liquidator:Geoff borrower:Torrey -- The caller must be from another cToken market, thus this fails - Assert Failure COMPTROLLER_REJECTION LIQUIDATE_SEIZE_COMPTROLLER_REJECTION MARKET_NOT_LISTED + Assert RevertCustomError LiquidateSeizeComptrollerRejection 9 Test "Seize tokens with a paused WBTC cToken-- like normal" NewComptroller @@ -22,7 +22,7 @@ Test "Seize tokens with a paused WBTC cToken-- like normal" AllowFailures Seize 1e9 cWBTC caller:Geoff liquidator:Geoff borrower:Torrey -- The caller must be from another cToken market, thus this fails - Assert Failure COMPTROLLER_REJECTION LIQUIDATE_SEIZE_COMPTROLLER_REJECTION MARKET_NOT_LISTED + Assert RevertCustomError LiquidateSeizeComptrollerRejection 9 Test "Not able to seize tokens with a malicious unlisted cToken" NewComptroller @@ -36,7 +36,7 @@ Test "Not able to seize tokens with a malicious unlisted cToken" AllowFailures EvilSeize cEVL 1e9 cZRX seizer:Geoff seizee:Torrey -- The caller must be from another cToken market, thus this fails - Assert Failure COMPTROLLER_REJECTION LIQUIDATE_SEIZE_COMPTROLLER_REJECTION MARKET_NOT_LISTED + Assert RevertCustomError LiquidateSeizeComptrollerRejection 9 Test "Able to seize tokens with a malicious listed cToken" NewComptroller diff --git a/spec/scenario/SetComptroller.scen b/spec/scenario/SetComptroller.scen index e3a7f89d0..f19a4fd82 100644 --- a/spec/scenario/SetComptroller.scen +++ b/spec/scenario/SetComptroller.scen @@ -23,4 +23,4 @@ Test "Fail to set comptroller as not admin" NewCToken ZRX cZRX AllowFailures From Geoff (CToken cZRX SetComptroller (PriceOracle Address)) - Assert Failure UNAUTHORIZED SET_COMPTROLLER_OWNER_CHECK + Assert RevertCustomError SetComptrollerOwnerCheck diff --git a/spec/scenario/TokenTransfer.scen b/spec/scenario/TokenTransfer.scen index e480747ce..60c6e6298 100644 --- a/spec/scenario/TokenTransfer.scen +++ b/spec/scenario/TokenTransfer.scen @@ -52,7 +52,7 @@ Test "Simple cToken Transfer Not Allowed by Comptroller" -- Just transfer AllowFailures Transfer Geoff Torrey 60e18 cZRX - Assert Failure COMPTROLLER_REJECTION TRANSFER_COMPTROLLER_REJECTION INSUFFICIENT_LIQUIDITY + Assert RevertCustomError TransferComptrollerRejection 4 Test "Simple cToken Transfer From" NewComptroller @@ -82,7 +82,7 @@ Test "cToken Transfer From Not Allowed" Invariant Remains (Erc20 cZRX TokenBalance Torrey) (Exactly 0e9) AllowFailures Erc20 cZRX TransferFrom Geoff Torrey 10e9 - Assert Failure MATH_ERROR TRANSFER_NOT_ALLOWED + Assert Revert Test "cToken Transfer paused" NewComptroller diff --git a/tests/Comptroller/liquidateCalculateAmountSeizeTest.js b/tests/Comptroller/liquidateCalculateAmountSeizeTest.js index 6b5077d7a..703c2a3cf 100644 --- a/tests/Comptroller/liquidateCalculateAmountSeizeTest.js +++ b/tests/Comptroller/liquidateCalculateAmountSeizeTest.js @@ -50,21 +50,21 @@ describe('Comptroller', () => { it("fails if the repayAmount causes overflow ", async () => { await expect( calculateSeizeTokens(comptroller, cTokenBorrowed, cTokenCollateral, UInt256Max()) - ).rejects.toRevert("revert multiplication overflow"); + ).rejects.toRevert(); }); it("fails if the borrowed asset price causes overflow ", async () => { await setOraclePrice(cTokenBorrowed, -1); await expect( calculateSeizeTokens(comptroller, cTokenBorrowed, cTokenCollateral, repayAmount) - ).rejects.toRevert("revert multiplication overflow"); + ).rejects.toRevert(); }); it("reverts if it fails to calculate the exchange rate", async () => { await send(cTokenCollateral, 'harnessExchangeRateDetails', [1, 0, 10]); // (1 - 10) -> underflow await expect( send(comptroller, 'liquidateCalculateSeizeTokens', [cTokenBorrowed._address, cTokenCollateral._address, repayAmount]) - ).rejects.toRevert("revert exchangeRateStored: exchangeRateStoredInternal failed"); + ).rejects.toRevert(); }); [ diff --git a/tests/Contracts/CErc20Harness.sol b/tests/Contracts/CErc20Harness.sol index 116582a5d..d944121a9 100644 --- a/tests/Contracts/CErc20Harness.sol +++ b/tests/Contracts/CErc20Harness.sol @@ -1,4 +1,5 @@ -pragma solidity ^0.5.16; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; import "../../contracts/CErc20Immutable.sol"; import "../../contracts/CErc20Delegator.sol"; @@ -29,21 +30,21 @@ contract CErc20Harness is CErc20Immutable { name_, symbol_, decimals_, - admin_) public {} + admin_) {} - function doTransferOut(address payable to, uint amount) internal { + function doTransferOut(address payable to, uint amount) override internal { require(failTransferToAddresses[to] == false, "TOKEN_TRANSFER_OUT_FAILED"); return super.doTransferOut(to, amount); } - function exchangeRateStoredInternal() internal view returns (MathError, uint) { + function exchangeRateStoredInternal() override internal view returns (uint) { if (harnessExchangeRateStored) { - return (MathError.NO_ERROR, harnessExchangeRate); + return harnessExchangeRate; } return super.exchangeRateStoredInternal(); } - function getBlockNumber() internal view returns (uint) { + function getBlockNumber() override internal view returns (uint) { return blockNumber; } @@ -95,12 +96,13 @@ contract CErc20Harness is CErc20Immutable { } function harnessMintFresh(address account, uint mintAmount) public returns (uint) { - (uint err,) = super.mintFresh(account, mintAmount); - return err; + super.mintFresh(account, mintAmount); + return NO_ERROR; } function harnessRedeemFresh(address payable account, uint cTokenAmount, uint underlyingAmount) public returns (uint) { - return super.redeemFresh(account, cTokenAmount, underlyingAmount); + super.redeemFresh(account, cTokenAmount, underlyingAmount); + return NO_ERROR; } function harnessAccountBorrows(address account) public view returns (uint principal, uint interestIndex) { @@ -117,17 +119,18 @@ contract CErc20Harness is CErc20Immutable { } function harnessBorrowFresh(address payable account, uint borrowAmount) public returns (uint) { - return borrowFresh(account, borrowAmount); + borrowFresh(account, borrowAmount); + return NO_ERROR; } function harnessRepayBorrowFresh(address payer, address account, uint repayAmount) public returns (uint) { - (uint err,) = repayBorrowFresh(payer, account, repayAmount); - return err; + repayBorrowFresh(payer, account, repayAmount); + return NO_ERROR; } function harnessLiquidateBorrowFresh(address liquidator, address borrower, uint repayAmount, CToken cTokenCollateral) public returns (uint) { - (uint err,) = liquidateBorrowFresh(liquidator, borrower, repayAmount, cTokenCollateral); - return err; + liquidateBorrowFresh(liquidator, borrower, repayAmount, cTokenCollateral); + return NO_ERROR; } function harnessReduceReservesFresh(uint amount) public returns (uint) { @@ -168,7 +171,7 @@ contract CErc20Scenario is CErc20Immutable { name_, symbol_, decimals_, - admin_) public {} + admin_) {} function setTotalBorrows(uint totalBorrows_) public { totalBorrows = totalBorrows_; @@ -178,7 +181,7 @@ contract CErc20Scenario is CErc20Immutable { totalReserves = totalReserves_; } - function getBlockNumber() internal view returns (uint) { + function getBlockNumber() override internal view returns (uint) { ComptrollerScenario comptrollerScenario = ComptrollerScenario(address(comptroller)); return comptrollerScenario.blockNumber(); } @@ -201,7 +204,7 @@ contract CEvil is CErc20Scenario { name_, symbol_, decimals_, - admin_) public {} + admin_) {} function evilSeize(CToken treasure, address liquidator, address borrower, uint seizeTokens) public returns (uint) { return treasure.seize(liquidator, borrower, seizeTokens); @@ -229,7 +232,7 @@ contract CErc20DelegatorScenario is CErc20Delegator { decimals_, admin_, implementation_, - becomeImplementationData) public {} + becomeImplementationData) {} function setTotalBorrows(uint totalBorrows_) public { totalBorrows = totalBorrows_; @@ -250,19 +253,19 @@ contract CErc20DelegateHarness is CErc20Delegate { mapping (address => bool) public failTransferToAddresses; - function exchangeRateStoredInternal() internal view returns (MathError, uint) { + function exchangeRateStoredInternal() override internal view returns (uint) { if (harnessExchangeRateStored) { - return (MathError.NO_ERROR, harnessExchangeRate); + return harnessExchangeRate; } return super.exchangeRateStoredInternal(); } - function doTransferOut(address payable to, uint amount) internal { + function doTransferOut(address payable to, uint amount) override internal { require(failTransferToAddresses[to] == false, "TOKEN_TRANSFER_OUT_FAILED"); return super.doTransferOut(to, amount); } - function getBlockNumber() internal view returns (uint) { + function getBlockNumber() override internal view returns (uint) { return blockNumber; } @@ -318,12 +321,13 @@ contract CErc20DelegateHarness is CErc20Delegate { } function harnessMintFresh(address account, uint mintAmount) public returns (uint) { - (uint err,) = super.mintFresh(account, mintAmount); - return err; + super.mintFresh(account, mintAmount); + return NO_ERROR; } function harnessRedeemFresh(address payable account, uint cTokenAmount, uint underlyingAmount) public returns (uint) { - return super.redeemFresh(account, cTokenAmount, underlyingAmount); + super.redeemFresh(account, cTokenAmount, underlyingAmount); + return NO_ERROR; } function harnessAccountBorrows(address account) public view returns (uint principal, uint interestIndex) { @@ -340,17 +344,18 @@ contract CErc20DelegateHarness is CErc20Delegate { } function harnessBorrowFresh(address payable account, uint borrowAmount) public returns (uint) { - return borrowFresh(account, borrowAmount); + borrowFresh(account, borrowAmount); + return NO_ERROR; } function harnessRepayBorrowFresh(address payer, address account, uint repayAmount) public returns (uint) { - (uint err,) = repayBorrowFresh(payer, account, repayAmount); - return err; + repayBorrowFresh(payer, account, repayAmount); + return NO_ERROR; } function harnessLiquidateBorrowFresh(address liquidator, address borrower, uint repayAmount, CToken cTokenCollateral) public returns (uint) { - (uint err,) = liquidateBorrowFresh(liquidator, borrower, repayAmount, cTokenCollateral); - return err; + liquidateBorrowFresh(liquidator, borrower, repayAmount, cTokenCollateral); + return NO_ERROR; } function harnessReduceReservesFresh(uint amount) public returns (uint) { @@ -375,7 +380,7 @@ contract CErc20DelegateHarness is CErc20Delegate { } contract CErc20DelegateScenario is CErc20Delegate { - constructor() public {} + constructor() {} function setTotalBorrows(uint totalBorrows_) public { totalBorrows = totalBorrows_; @@ -385,7 +390,7 @@ contract CErc20DelegateScenario is CErc20Delegate { totalReserves = totalReserves_; } - function getBlockNumber() internal view returns (uint) { + function getBlockNumber() override internal view returns (uint) { ComptrollerScenario comptrollerScenario = ComptrollerScenario(address(comptroller)); return comptrollerScenario.blockNumber(); } @@ -397,7 +402,7 @@ contract CErc20DelegateScenarioExtra is CErc20DelegateScenario { } function itIsTheWay() public { - admin = address(1); // make a change to test effect + admin = payable(address(1)); // make a change to test effect } function babyYoda() public pure { @@ -435,7 +440,7 @@ contract CDaiDelegateHarness is CDaiDelegate { totalSupply = totalSupply_; } - function getBlockNumber() internal view returns (uint) { + function getBlockNumber() override internal view returns (uint) { return blockNumber; } } @@ -449,7 +454,7 @@ contract CDaiDelegateScenario is CDaiDelegate { totalReserves = totalReserves_; } - function getBlockNumber() internal view returns (uint) { + function getBlockNumber() override internal view returns (uint) { ComptrollerScenario comptrollerScenario = ComptrollerScenario(address(comptroller)); return comptrollerScenario.blockNumber(); } @@ -459,35 +464,35 @@ contract CDaiDelegateMakerHarness is PotLike, VatLike, GemLike, DaiJoinLike { /* Pot */ // exchangeRate - function chi() external view returns (uint) { return 1; } + function chi() override external view returns (uint) { return 1; } // totalSupply - function pie(address) external view returns (uint) { return 0; } + function pie(address) override external view returns (uint) { return 0; } // accrueInterest -> new exchangeRate - function drip() external returns (uint) { return 0; } + function drip() override external returns (uint) { return 0; } // mint - function join(uint) external {} + function join(uint) override external {} // redeem - function exit(uint) external {} + function exit(uint) override external {} /* Vat */ // internal dai balance - function dai(address) external view returns (uint) { return 0; } + function dai(address) override external view returns (uint) { return 0; } // approve pot transfer - function hope(address) external {} + function hope(address) override external {} /* Gem (Dai) */ uint public totalSupply; mapping (address => mapping (address => uint)) public allowance; - mapping (address => uint) public balanceOf; - function approve(address, uint) external {} - function transferFrom(address src, address dst, uint amount) external returns (bool) { + mapping (address => uint) override public balanceOf; + function approve(address, uint) override external {} + function transferFrom(address src, address dst, uint amount) override external returns (bool) { balanceOf[src] -= amount; balanceOf[dst] += amount; return true; @@ -500,14 +505,14 @@ contract CDaiDelegateMakerHarness is PotLike, VatLike, GemLike, DaiJoinLike { /* DaiJoin */ // vat contract - function vat() external returns (VatLike) { return this; } + function vat() override external returns (VatLike) { return this; } // dai contract - function dai() external returns (GemLike) { return this; } + function dai() override external returns (GemLike) { return this; } // dai -> internal dai - function join(address, uint) external payable {} + function join(address, uint) override external payable {} // internal dai transfer out - function exit(address, uint) external {} + function exit(address, uint) override external {} } diff --git a/tests/Contracts/CEtherHarness.sol b/tests/Contracts/CEtherHarness.sol index 4d494cf0a..ac988d0bb 100644 --- a/tests/Contracts/CEtherHarness.sol +++ b/tests/Contracts/CEtherHarness.sol @@ -1,4 +1,5 @@ -pragma solidity ^0.5.16; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; import "../../contracts/CEther.sol"; import "./ComptrollerScenario.sol"; @@ -23,21 +24,21 @@ contract CEtherHarness is CEther { name_, symbol_, decimals_, - admin_) public {} + admin_) {} - function doTransferOut(address payable to, uint amount) internal { + function doTransferOut(address payable to, uint amount) override internal { require(failTransferToAddresses[to] == false, "TOKEN_TRANSFER_OUT_FAILED"); return super.doTransferOut(to, amount); } - function exchangeRateStoredInternal() internal view returns (MathError, uint) { + function exchangeRateStoredInternal() override internal view returns (uint) { if (harnessExchangeRate != 0) { - return (MathError.NO_ERROR, harnessExchangeRate); + return harnessExchangeRate; } return super.exchangeRateStoredInternal(); } - function getBlockNumber() internal view returns (uint) { + function getBlockNumber() override internal view returns (uint) { return blockNumber; } @@ -84,12 +85,13 @@ contract CEtherHarness is CEther { } function harnessMintFresh(address account, uint mintAmount) public returns (uint) { - (uint err,) = super.mintFresh(account, mintAmount); - return err; + super.mintFresh(account, mintAmount); + return NO_ERROR; } function harnessRedeemFresh(address payable account, uint cTokenAmount, uint underlyingAmount) public returns (uint) { - return super.redeemFresh(account, cTokenAmount, underlyingAmount); + super.redeemFresh(account, cTokenAmount, underlyingAmount); + return NO_ERROR; } function harnessAccountBorrows(address account) public view returns (uint principal, uint interestIndex) { @@ -106,17 +108,18 @@ contract CEtherHarness is CEther { } function harnessBorrowFresh(address payable account, uint borrowAmount) public returns (uint) { - return borrowFresh(account, borrowAmount); + borrowFresh(account, borrowAmount); + return NO_ERROR; } function harnessRepayBorrowFresh(address payer, address account, uint repayBorrowAmount) public payable returns (uint) { - (uint err,) = repayBorrowFresh(payer, account, repayBorrowAmount); - return err; + repayBorrowFresh(payer, account, repayBorrowAmount); + return NO_ERROR; } function harnessLiquidateBorrowFresh(address liquidator, address borrower, uint repayAmount, CToken cTokenCollateral) public returns (uint) { - (uint err,) = liquidateBorrowFresh(liquidator, borrower, repayAmount, cTokenCollateral); - return err; + liquidateBorrowFresh(liquidator, borrower, repayAmount, cTokenCollateral); + return NO_ERROR; } function harnessReduceReservesFresh(uint amount) public returns (uint) { @@ -150,10 +153,6 @@ contract CEtherHarness is CEther { function harnessDoTransferOut(address payable to, uint amount) public payable { return doTransferOut(to, amount); } - - function harnessRequireNoError(uint error, string calldata message) external pure { - requireNoError(error, message); - } } contract CEtherScenario is CEther { @@ -172,7 +171,7 @@ contract CEtherScenario is CEther { name_, symbol_, decimals_, - admin_) public { + admin_) { } function setTotalBorrows(uint totalBorrows_) public { @@ -187,7 +186,7 @@ contract CEtherScenario is CEther { // no-op } - function getBlockNumber() internal view returns (uint) { + function getBlockNumber() override internal view returns (uint) { ComptrollerScenario comptrollerScenario = ComptrollerScenario(address(comptroller)); return comptrollerScenario.blockNumber(); } diff --git a/tests/Contracts/CompHarness.sol b/tests/Contracts/CompHarness.sol index 55fa4e3c3..8cf365265 100644 --- a/tests/Contracts/CompHarness.sol +++ b/tests/Contracts/CompHarness.sol @@ -1,10 +1,10 @@ -pragma solidity ^0.5.16; -pragma experimental ABIEncoderV2; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; import "../../contracts/Governance/Comp.sol"; contract CompScenario is Comp { - constructor(address account) Comp(account) public {} + constructor(address account) Comp(account) {} function transferScenario(address[] calldata destinations, uint256 amount) external returns (bool) { for (uint i = 0; i < destinations.length; i++) { diff --git a/tests/Contracts/ComptrollerHarness.sol b/tests/Contracts/ComptrollerHarness.sol index c5daf1ae8..e03edeb5e 100644 --- a/tests/Contracts/ComptrollerHarness.sol +++ b/tests/Contracts/ComptrollerHarness.sol @@ -1,25 +1,26 @@ -pragma solidity ^0.5.16; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; import "../../contracts/Comptroller.sol"; import "../../contracts/PriceOracle.sol"; contract ComptrollerKovan is Comptroller { - function getCompAddress() public view returns (address) { - return 0x61460874a7196d6a22D1eE4922473664b3E95270; - } + function getCompAddress() override public view returns (address) { + return 0x61460874a7196d6a22D1eE4922473664b3E95270; + } } contract ComptrollerRopsten is Comptroller { - function getCompAddress() public view returns (address) { - return 0xf76D4a441E4ba86A923ce32B89AFF89dBccAA075; - } + function getCompAddress() override public view returns (address) { + return 0xf76D4a441E4ba86A923ce32B89AFF89dBccAA075; + } } contract ComptrollerHarness is Comptroller { address compAddress; uint public blockNumber; - constructor() Comptroller() public {} + constructor() Comptroller() {} function setPauseGuardian(address harnessedPauseGuardian) public { pauseGuardian = harnessedPauseGuardian; @@ -43,7 +44,7 @@ contract ComptrollerHarness is Comptroller { compAddress = compAddress_; } - function getCompAddress() public view returns (address) { + function getCompAddress() override public view returns (address) { return compAddress; } @@ -144,7 +145,7 @@ contract ComptrollerHarness is Comptroller { blockNumber = number; } - function getBlockNumber() public view returns (uint) { + function getBlockNumber() override public view returns (uint) { return blockNumber; } @@ -205,27 +206,27 @@ contract BoolComptroller is ComptrollerInterface { /*** Assets You Are In ***/ - function enterMarkets(address[] calldata _cTokens) external returns (uint[] memory) { + function enterMarkets(address[] calldata _cTokens) override external returns (uint[] memory) { _cTokens; uint[] memory ret; return ret; } - function exitMarket(address _cToken) external returns (uint) { + function exitMarket(address _cToken) override external returns (uint) { _cToken; return noError; } /*** Policy Hooks ***/ - function mintAllowed(address _cToken, address _minter, uint _mintAmount) public returns (uint) { + function mintAllowed(address _cToken, address _minter, uint _mintAmount) override public returns (uint) { _cToken; _minter; _mintAmount; return allowMint ? noError : opaqueError; } - function mintVerify(address _cToken, address _minter, uint _mintAmount, uint _mintTokens) external { + function mintVerify(address _cToken, address _minter, uint _mintAmount, uint _mintTokens) override external { _cToken; _minter; _mintAmount; @@ -233,14 +234,14 @@ contract BoolComptroller is ComptrollerInterface { require(verifyMint, "mintVerify rejected mint"); } - function redeemAllowed(address _cToken, address _redeemer, uint _redeemTokens) public returns (uint) { + function redeemAllowed(address _cToken, address _redeemer, uint _redeemTokens) override public returns (uint) { _cToken; _redeemer; _redeemTokens; return allowRedeem ? noError : opaqueError; } - function redeemVerify(address _cToken, address _redeemer, uint _redeemAmount, uint _redeemTokens) external { + function redeemVerify(address _cToken, address _redeemer, uint _redeemAmount, uint _redeemTokens) override external { _cToken; _redeemer; _redeemAmount; @@ -248,14 +249,14 @@ contract BoolComptroller is ComptrollerInterface { require(verifyRedeem, "redeemVerify rejected redeem"); } - function borrowAllowed(address _cToken, address _borrower, uint _borrowAmount) public returns (uint) { + function borrowAllowed(address _cToken, address _borrower, uint _borrowAmount) override public returns (uint) { _cToken; _borrower; _borrowAmount; return allowBorrow ? noError : opaqueError; } - function borrowVerify(address _cToken, address _borrower, uint _borrowAmount) external { + function borrowVerify(address _cToken, address _borrower, uint _borrowAmount) override external { _cToken; _borrower; _borrowAmount; @@ -266,7 +267,7 @@ contract BoolComptroller is ComptrollerInterface { address _cToken, address _payer, address _borrower, - uint _repayAmount) public returns (uint) { + uint _repayAmount) override public returns (uint) { _cToken; _payer; _borrower; @@ -279,7 +280,7 @@ contract BoolComptroller is ComptrollerInterface { address _payer, address _borrower, uint _repayAmount, - uint _borrowerIndex) external { + uint _borrowerIndex) override external { _cToken; _payer; _borrower; @@ -293,7 +294,7 @@ contract BoolComptroller is ComptrollerInterface { address _cTokenCollateral, address _liquidator, address _borrower, - uint _repayAmount) public returns (uint) { + uint _repayAmount) override public returns (uint) { _cTokenBorrowed; _cTokenCollateral; _liquidator; @@ -308,7 +309,7 @@ contract BoolComptroller is ComptrollerInterface { address _liquidator, address _borrower, uint _repayAmount, - uint _seizeTokens) external { + uint _seizeTokens) override external { _cTokenBorrowed; _cTokenCollateral; _liquidator; @@ -323,7 +324,7 @@ contract BoolComptroller is ComptrollerInterface { address _cTokenBorrowed, address _borrower, address _liquidator, - uint _seizeTokens) public returns (uint) { + uint _seizeTokens) override public returns (uint) { _cTokenCollateral; _cTokenBorrowed; _liquidator; @@ -337,7 +338,7 @@ contract BoolComptroller is ComptrollerInterface { address _cTokenBorrowed, address _liquidator, address _borrower, - uint _seizeTokens) external { + uint _seizeTokens) override external { _cTokenCollateral; _cTokenBorrowed; _liquidator; @@ -350,7 +351,7 @@ contract BoolComptroller is ComptrollerInterface { address _cToken, address _src, address _dst, - uint _transferTokens) public returns (uint) { + uint _transferTokens) override public returns (uint) { _cToken; _src; _dst; @@ -362,7 +363,7 @@ contract BoolComptroller is ComptrollerInterface { address _cToken, address _src, address _dst, - uint _transferTokens) external { + uint _transferTokens) override external { _cToken; _src; _dst; @@ -375,7 +376,7 @@ contract BoolComptroller is ComptrollerInterface { function liquidateCalculateSeizeTokens( address _cTokenBorrowed, address _cTokenCollateral, - uint _repayAmount) public view returns (uint, uint) { + uint _repayAmount) override public view returns (uint, uint) { _cTokenBorrowed; _cTokenCollateral; _repayAmount; diff --git a/tests/Contracts/ComptrollerScenario.sol b/tests/Contracts/ComptrollerScenario.sol index 3083d22f3..99cb1f17e 100644 --- a/tests/Contracts/ComptrollerScenario.sol +++ b/tests/Contracts/ComptrollerScenario.sol @@ -1,4 +1,5 @@ -pragma solidity ^0.5.16; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; import "../../contracts/Comptroller.sol"; @@ -6,7 +7,7 @@ contract ComptrollerScenario is Comptroller { uint public blockNumber; address public compAddress; - constructor() Comptroller() public {} + constructor() Comptroller() {} function fastForward(uint blocks) public returns (uint) { blockNumber += blocks; @@ -17,7 +18,7 @@ contract ComptrollerScenario is Comptroller { compAddress = compAddress_; } - function getCompAddress() public view returns (address) { + function getCompAddress() override public view returns (address) { return compAddress; } @@ -25,7 +26,7 @@ contract ComptrollerScenario is Comptroller { blockNumber = number; } - function getBlockNumber() public view returns (uint) { + function getBlockNumber() override public view returns (uint) { return blockNumber; } diff --git a/tests/Contracts/ComptrollerScenarioG1.sol b/tests/Contracts/ComptrollerScenarioG1.sol deleted file mode 100644 index 9850f3f1b..000000000 --- a/tests/Contracts/ComptrollerScenarioG1.sol +++ /dev/null @@ -1,50 +0,0 @@ -pragma solidity ^0.5.16; - -import "../../contracts/ComptrollerG1.sol"; -import "../../contracts/PriceOracle.sol"; - -// XXX we should delete G1 everything... -// requires fork/deploy bytecode tests - -contract ComptrollerScenarioG1 is ComptrollerG1 { - uint public blockNumber; - - constructor() ComptrollerG1() public {} - - function membershipLength(CToken cToken) public view returns (uint) { - return accountAssets[address(cToken)].length; - } - - function fastForward(uint blocks) public returns (uint) { - blockNumber += blocks; - - return blockNumber; - } - - function setBlockNumber(uint number) public { - blockNumber = number; - } - - function _become( - Unitroller unitroller, - PriceOracle _oracle, - uint _closeFactorMantissa, - uint _maxAssets, - bool reinitializing) public { - super._become(unitroller, _oracle, _closeFactorMantissa, _maxAssets, reinitializing); - } - - function getHypotheticalAccountLiquidity( - address account, - address cTokenModify, - uint redeemTokens, - uint borrowAmount) public view returns (uint, uint, uint) { - (Error err, uint liquidity, uint shortfall) = - super.getHypotheticalAccountLiquidityInternal(account, CToken(cTokenModify), redeemTokens, borrowAmount); - return (uint(err), liquidity, shortfall); - } - - function unlist(CToken cToken) public { - markets[address(cToken)].isListed = false; - } -} diff --git a/tests/Contracts/ComptrollerScenarioG2.sol b/tests/Contracts/ComptrollerScenarioG2.sol deleted file mode 100644 index 622fd9f2f..000000000 --- a/tests/Contracts/ComptrollerScenarioG2.sol +++ /dev/null @@ -1,19 +0,0 @@ -pragma solidity ^0.5.16; - -import "../../contracts/ComptrollerG2.sol"; - -contract ComptrollerScenarioG2 is ComptrollerG2 { - uint public blockNumber; - address public compAddress; - - constructor() ComptrollerG2() public {} - - function fastForward(uint blocks) public returns (uint) { - blockNumber += blocks; - return blockNumber; - } - - function setBlockNumber(uint number) public { - blockNumber = number; - } -} diff --git a/tests/Contracts/ComptrollerScenarioG3.sol b/tests/Contracts/ComptrollerScenarioG3.sol deleted file mode 100644 index 6b4d17ebf..000000000 --- a/tests/Contracts/ComptrollerScenarioG3.sol +++ /dev/null @@ -1,59 +0,0 @@ -pragma solidity ^0.5.16; - -import "../../contracts/ComptrollerG3.sol"; - -contract ComptrollerScenarioG3 is ComptrollerG3 { - uint public blockNumber; - address public compAddress; - - constructor() ComptrollerG3() public {} - - function setCompAddress(address compAddress_) public { - compAddress = compAddress_; - } - - function getCompAddress() public view returns (address) { - return compAddress; - } - - function membershipLength(CToken cToken) public view returns (uint) { - return accountAssets[address(cToken)].length; - } - - function fastForward(uint blocks) public returns (uint) { - blockNumber += blocks; - - return blockNumber; - } - - function setBlockNumber(uint number) public { - blockNumber = number; - } - - function getBlockNumber() public view returns (uint) { - return blockNumber; - } - - function getCompMarkets() public view returns (address[] memory) { - uint m = allMarkets.length; - uint n = 0; - for (uint i = 0; i < m; i++) { - if (markets[address(allMarkets[i])].isComped) { - n++; - } - } - - address[] memory compMarkets = new address[](n); - uint k = 0; - for (uint i = 0; i < m; i++) { - if (markets[address(allMarkets[i])].isComped) { - compMarkets[k++] = address(allMarkets[i]); - } - } - return compMarkets; - } - - function unlist(CToken cToken) public { - markets[address(cToken)].isListed = false; - } -} diff --git a/tests/Contracts/ComptrollerScenarioG4.sol b/tests/Contracts/ComptrollerScenarioG4.sol deleted file mode 100644 index 20d252d88..000000000 --- a/tests/Contracts/ComptrollerScenarioG4.sol +++ /dev/null @@ -1,27 +0,0 @@ -pragma solidity ^0.5.16; - -import "../../contracts/ComptrollerG4.sol"; - -contract ComptrollerScenarioG4 is ComptrollerG4 { - uint public blockNumber; - address public compAddress; - - constructor() ComptrollerG4() public {} - - function fastForward(uint blocks) public returns (uint) { - blockNumber += blocks; - return blockNumber; - } - - function setBlockNumber(uint number) public { - blockNumber = number; - } - - function membershipLength(CToken cToken) public view returns (uint) { - return accountAssets[address(cToken)].length; - } - - function unlist(CToken cToken) public { - markets[address(cToken)].isListed = false; - } -} diff --git a/tests/Contracts/ComptrollerScenarioG5.sol b/tests/Contracts/ComptrollerScenarioG5.sol deleted file mode 100644 index 41ba41013..000000000 --- a/tests/Contracts/ComptrollerScenarioG5.sol +++ /dev/null @@ -1,59 +0,0 @@ -pragma solidity ^0.5.16; - -import "../../contracts/ComptrollerG5.sol"; - -contract ComptrollerScenarioG5 is ComptrollerG5 { - uint public blockNumber; - address public compAddress; - - constructor() ComptrollerG5() public {} - - function setCompAddress(address compAddress_) public { - compAddress = compAddress_; - } - - function getCompAddress() public view returns (address) { - return compAddress; - } - - function membershipLength(CToken cToken) public view returns (uint) { - return accountAssets[address(cToken)].length; - } - - function fastForward(uint blocks) public returns (uint) { - blockNumber += blocks; - - return blockNumber; - } - - function setBlockNumber(uint number) public { - blockNumber = number; - } - - function getBlockNumber() public view returns (uint) { - return blockNumber; - } - - function getCompMarkets() public view returns (address[] memory) { - uint m = allMarkets.length; - uint n = 0; - for (uint i = 0; i < m; i++) { - if (markets[address(allMarkets[i])].isComped) { - n++; - } - } - - address[] memory compMarkets = new address[](n); - uint k = 0; - for (uint i = 0; i < m; i++) { - if (markets[address(allMarkets[i])].isComped) { - compMarkets[k++] = address(allMarkets[i]); - } - } - return compMarkets; - } - - function unlist(CToken cToken) public { - markets[address(cToken)].isListed = false; - } -} diff --git a/tests/Contracts/ComptrollerScenarioG6.sol b/tests/Contracts/ComptrollerScenarioG6.sol deleted file mode 100644 index d1cc6fe8f..000000000 --- a/tests/Contracts/ComptrollerScenarioG6.sol +++ /dev/null @@ -1,43 +0,0 @@ -pragma solidity ^0.5.16; - -import "../../contracts/ComptrollerG6.sol"; - -contract ComptrollerScenarioG6 is ComptrollerG6 { - uint public blockNumber; - address public compAddress; - - constructor() ComptrollerG6() public {} - - function fastForward(uint blocks) public returns (uint) { - blockNumber += blocks; - return blockNumber; - } - - function setCompAddress(address compAddress_) public { - compAddress = compAddress_; - } - - function getCompAddress() public view returns (address) { - return compAddress; - } - - function setBlockNumber(uint number) public { - blockNumber = number; - } - - function getBlockNumber() public view returns (uint) { - return blockNumber; - } - - function membershipLength(CToken cToken) public view returns (uint) { - return accountAssets[address(cToken)].length; - } - - function unlist(CToken cToken) public { - markets[address(cToken)].isListed = false; - } - - function setCompSpeed(address cToken, uint compSpeed) public { - compSpeeds[cToken] = compSpeed; - } -} diff --git a/tests/Contracts/Const.sol b/tests/Contracts/Const.sol index 200894304..b6af74668 100644 --- a/tests/Contracts/Const.sol +++ b/tests/Contracts/Const.sol @@ -1,16 +1,17 @@ -pragma solidity ^0.5.16; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; contract ConstBase { uint public constant C = 1; - function c() public pure returns (uint) { + function c() virtual public pure returns (uint) { return 1; } function ADD(uint a) public view returns (uint) { // tells compiler to accept view instead of pure if (false) { - C + now; + C + block.timestamp; } return a + C; } @@ -18,14 +19,14 @@ contract ConstBase { function add(uint a) public view returns (uint) { // tells compiler to accept view instead of pure if (false) { - C + now; + C + block.timestamp; } return a + c(); } } contract ConstSub is ConstBase { - function c() public pure returns (uint) { + function c() override public pure returns (uint) { return 2; } } diff --git a/tests/Contracts/Counter.sol b/tests/Contracts/Counter.sol index a0cc88536..dd747b24b 100644 --- a/tests/Contracts/Counter.sol +++ b/tests/Contracts/Counter.sol @@ -1,9 +1,10 @@ -pragma solidity ^0.5.16; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; contract Counter { uint public count; uint public count2; - + function increment(uint amount) public payable { count += amount; } diff --git a/tests/Contracts/ERC20.sol b/tests/Contracts/ERC20.sol index 91729305a..e75c718c1 100644 --- a/tests/Contracts/ERC20.sol +++ b/tests/Contracts/ERC20.sol @@ -1,4 +1,5 @@ -pragma solidity ^0.5.16; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; import "../../contracts/SafeMath.sol"; @@ -11,14 +12,14 @@ interface ERC20Base { function balanceOf(address who) external view returns (uint256); } -contract ERC20 is ERC20Base { - function transfer(address to, uint256 value) external returns (bool); - function transferFrom(address from, address to, uint256 value) external returns (bool); +abstract contract ERC20 is ERC20Base { + function transfer(address to, uint256 value) virtual external returns (bool); + function transferFrom(address from, address to, uint256 value) virtual external returns (bool); } -contract ERC20NS is ERC20Base { - function transfer(address to, uint256 value) external; - function transferFrom(address from, address to, uint256 value) external; +abstract contract ERC20NS is ERC20Base { + function transfer(address to, uint256 value) virtual external; + function transferFrom(address from, address to, uint256 value) virtual external; } /** @@ -32,11 +33,11 @@ contract StandardToken is ERC20 { string public name; string public symbol; uint8 public decimals; - uint256 public totalSupply; - mapping (address => mapping (address => uint256)) public allowance; - mapping(address => uint256) public balanceOf; + uint256 override public totalSupply; + mapping (address => mapping (address => uint256)) override public allowance; + mapping(address => uint256) override public balanceOf; - constructor(uint256 _initialAmount, string memory _tokenName, uint8 _decimalUnits, string memory _tokenSymbol) public { + constructor(uint256 _initialAmount, string memory _tokenName, uint8 _decimalUnits, string memory _tokenSymbol) { totalSupply = _initialAmount; balanceOf[msg.sender] = _initialAmount; name = _tokenName; @@ -44,14 +45,14 @@ contract StandardToken is ERC20 { decimals = _decimalUnits; } - function transfer(address dst, uint256 amount) external returns (bool) { + function transfer(address dst, uint256 amount) virtual override external returns (bool) { balanceOf[msg.sender] = balanceOf[msg.sender].sub(amount, "Insufficient balance"); balanceOf[dst] = balanceOf[dst].add(amount, "Balance overflow"); emit Transfer(msg.sender, dst, amount); return true; } - function transferFrom(address src, address dst, uint256 amount) external returns (bool) { + function transferFrom(address src, address dst, uint256 amount) virtual override external returns (bool) { allowance[src][msg.sender] = allowance[src][msg.sender].sub(amount, "Insufficient allowance"); balanceOf[src] = balanceOf[src].sub(amount, "Insufficient balance"); balanceOf[dst] = balanceOf[dst].add(amount, "Balance overflow"); @@ -59,7 +60,7 @@ contract StandardToken is ERC20 { return true; } - function approve(address _spender, uint256 amount) external returns (bool) { + function approve(address _spender, uint256 amount) virtual override external returns (bool) { allowance[msg.sender][_spender] = amount; emit Approval(msg.sender, _spender, amount); return true; @@ -77,11 +78,11 @@ contract NonStandardToken is ERC20NS { string public name; uint8 public decimals; string public symbol; - uint256 public totalSupply; - mapping (address => mapping (address => uint256)) public allowance; - mapping(address => uint256) public balanceOf; + uint256 override public totalSupply; + mapping (address => mapping (address => uint256)) override public allowance; + mapping(address => uint256) override public balanceOf; - constructor(uint256 _initialAmount, string memory _tokenName, uint8 _decimalUnits, string memory _tokenSymbol) public { + constructor(uint256 _initialAmount, string memory _tokenName, uint8 _decimalUnits, string memory _tokenSymbol) { totalSupply = _initialAmount; balanceOf[msg.sender] = _initialAmount; name = _tokenName; @@ -89,20 +90,20 @@ contract NonStandardToken is ERC20NS { decimals = _decimalUnits; } - function transfer(address dst, uint256 amount) external { + function transfer(address dst, uint256 amount) override external { balanceOf[msg.sender] = balanceOf[msg.sender].sub(amount, "Insufficient balance"); balanceOf[dst] = balanceOf[dst].add(amount, "Balance overflow"); emit Transfer(msg.sender, dst, amount); } - function transferFrom(address src, address dst, uint256 amount) external { + function transferFrom(address src, address dst, uint256 amount) override external { allowance[src][msg.sender] = allowance[src][msg.sender].sub(amount, "Insufficient allowance"); balanceOf[src] = balanceOf[src].sub(amount, "Insufficient balance"); balanceOf[dst] = balanceOf[dst].add(amount, "Balance overflow"); emit Transfer(src, dst, amount); } - function approve(address _spender, uint256 amount) external returns (bool) { + function approve(address _spender, uint256 amount) override external returns (bool) { allowance[msg.sender][_spender] = amount; emit Approval(msg.sender, _spender, amount); return true; @@ -110,13 +111,14 @@ contract NonStandardToken is ERC20NS { } contract ERC20Harness is StandardToken { + using SafeMath for uint256; // To support testing, we can specify addresses for which transferFrom should fail and return false mapping (address => bool) public failTransferFromAddresses; // To support testing, we allow the contract to always fail `transfer`. mapping (address => bool) public failTransferToAddresses; - constructor(uint256 _initialAmount, string memory _tokenName, uint8 _decimalUnits, string memory _tokenSymbol) public + constructor(uint256 _initialAmount, string memory _tokenName, uint8 _decimalUnits, string memory _tokenSymbol) StandardToken(_initialAmount, _tokenName, _decimalUnits, _tokenSymbol) {} function harnessSetFailTransferFromAddress(address src, bool _fail) public { @@ -131,7 +133,7 @@ contract ERC20Harness is StandardToken { balanceOf[_account] = _amount; } - function transfer(address dst, uint256 amount) external returns (bool success) { + function transfer(address dst, uint256 amount) override external returns (bool success) { // Added for testing purposes if (failTransferToAddresses[dst]) { return false; @@ -142,7 +144,7 @@ contract ERC20Harness is StandardToken { return true; } - function transferFrom(address src, address dst, uint256 amount) external returns (bool success) { + function transferFrom(address src, address dst, uint256 amount) override external returns (bool success) { // Added for testing purposes if (failTransferFromAddresses[src]) { return false; diff --git a/tests/Contracts/EvilToken.sol b/tests/Contracts/EvilToken.sol index d52086341..ed93b6328 100644 --- a/tests/Contracts/EvilToken.sol +++ b/tests/Contracts/EvilToken.sol @@ -1,4 +1,5 @@ -pragma solidity ^0.5.16; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; import "./FaucetToken.sol"; @@ -8,9 +9,11 @@ import "./FaucetToken.sol"; * @notice A simple test token that fails certain operations */ contract EvilToken is FaucetToken { + using SafeMath for uint256; + bool public fail; - constructor(uint256 _initialAmount, string memory _tokenName, uint8 _decimalUnits, string memory _tokenSymbol) public + constructor(uint256 _initialAmount, string memory _tokenName, uint8 _decimalUnits, string memory _tokenSymbol) FaucetToken(_initialAmount, _tokenName, _decimalUnits, _tokenSymbol) { fail = true; } @@ -19,7 +22,7 @@ contract EvilToken is FaucetToken { fail = _fail; } - function transfer(address dst, uint256 amount) external returns (bool) { + function transfer(address dst, uint256 amount) override external returns (bool) { if (fail) { return false; } @@ -29,7 +32,7 @@ contract EvilToken is FaucetToken { return true; } - function transferFrom(address src, address dst, uint256 amount) external returns (bool) { + function transferFrom(address src, address dst, uint256 amount) override external returns (bool) { if (fail) { return false; } diff --git a/tests/Contracts/FalseMarker.sol b/tests/Contracts/FalseMarker.sol index 792ec5aa2..615304234 100644 --- a/tests/Contracts/FalseMarker.sol +++ b/tests/Contracts/FalseMarker.sol @@ -1,4 +1,5 @@ -pragma solidity ^0.5.16; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; contract FalseMarkerMethodComptroller { bool public constant isComptroller = false; diff --git a/tests/Contracts/FaucetToken.sol b/tests/Contracts/FaucetToken.sol index 929d1606e..ba5ac483c 100644 --- a/tests/Contracts/FaucetToken.sol +++ b/tests/Contracts/FaucetToken.sol @@ -1,4 +1,5 @@ -pragma solidity ^0.5.16; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; import "./ERC20.sol"; @@ -8,7 +9,7 @@ import "./ERC20.sol"; * @notice A simple test token that lets anyone get more of it. */ contract FaucetToken is StandardToken { - constructor(uint256 _initialAmount, string memory _tokenName, uint8 _decimalUnits, string memory _tokenSymbol) public + constructor(uint256 _initialAmount, string memory _tokenName, uint8 _decimalUnits, string memory _tokenSymbol) StandardToken(_initialAmount, _tokenName, _decimalUnits, _tokenSymbol) { } @@ -25,7 +26,7 @@ contract FaucetToken is StandardToken { * @notice A simple test token that lets anyone get more of it. */ contract FaucetNonStandardToken is NonStandardToken { - constructor(uint256 _initialAmount, string memory _tokenName, uint8 _decimalUnits, string memory _tokenSymbol) public + constructor(uint256 _initialAmount, string memory _tokenName, uint8 _decimalUnits, string memory _tokenSymbol) NonStandardToken(_initialAmount, _tokenName, _decimalUnits, _tokenSymbol) { } @@ -57,7 +58,7 @@ contract FaucetTokenReEntrantHarness { bytes public reEntryCallData; string public reEntryFun; - constructor(uint256 _initialAmount, string memory _tokenName, uint8 _decimalUnits, string memory _tokenSymbol, bytes memory _reEntryCallData, string memory _reEntryFun) public { + constructor(uint256 _initialAmount, string memory _tokenName, uint8 _decimalUnits, string memory _tokenSymbol, bytes memory _reEntryCallData, string memory _reEntryFun) { totalSupply_ = _initialAmount; balanceOf_[msg.sender] = _initialAmount; name = _tokenName; diff --git a/tests/Contracts/Fauceteer.sol b/tests/Contracts/Fauceteer.sol index f20151355..3b8718606 100644 --- a/tests/Contracts/Fauceteer.sol +++ b/tests/Contracts/Fauceteer.sol @@ -1,4 +1,5 @@ -pragma solidity ^0.5.16; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; import "../../contracts/EIP20NonStandardInterface.sol"; diff --git a/tests/Contracts/FeeToken.sol b/tests/Contracts/FeeToken.sol index 110e64ed2..06ec86ae6 100644 --- a/tests/Contracts/FeeToken.sol +++ b/tests/Contracts/FeeToken.sol @@ -1,4 +1,5 @@ -pragma solidity ^0.5.16; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; import "./FaucetToken.sol"; @@ -8,6 +9,8 @@ import "./FaucetToken.sol"; * @notice A simple test token that charges fees on transfer. Used to mock USDT. */ contract FeeToken is FaucetToken { + using SafeMath for uint256; + uint public basisPointFee; address public owner; @@ -18,12 +21,12 @@ contract FeeToken is FaucetToken { string memory _tokenSymbol, uint _basisPointFee, address _owner - ) FaucetToken(_initialAmount, _tokenName, _decimalUnits, _tokenSymbol) public { + ) FaucetToken(_initialAmount, _tokenName, _decimalUnits, _tokenSymbol) { basisPointFee = _basisPointFee; owner = _owner; } - function transfer(address dst, uint amount) public returns (bool) { + function transfer(address dst, uint amount) override public returns (bool) { uint fee = amount.mul(basisPointFee).div(10000); uint net = amount.sub(fee); balanceOf[owner] = balanceOf[owner].add(fee); @@ -33,7 +36,7 @@ contract FeeToken is FaucetToken { return true; } - function transferFrom(address src, address dst, uint amount) public returns (bool) { + function transferFrom(address src, address dst, uint amount) override public returns (bool) { uint fee = amount.mul(basisPointFee).div(10000); uint net = amount.sub(fee); balanceOf[owner] = balanceOf[owner].add(fee); diff --git a/tests/Contracts/FixedPriceOracle.sol b/tests/Contracts/FixedPriceOracle.sol index 1306d5095..88fcf6fd8 100644 --- a/tests/Contracts/FixedPriceOracle.sol +++ b/tests/Contracts/FixedPriceOracle.sol @@ -1,15 +1,16 @@ -pragma solidity ^0.5.16; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; import "../../contracts/PriceOracle.sol"; contract FixedPriceOracle is PriceOracle { uint public price; - constructor(uint _price) public { + constructor(uint _price) { price = _price; } - function getUnderlyingPrice(CToken cToken) public view returns (uint) { + function getUnderlyingPrice(CToken cToken) override public view returns (uint) { cToken; return price; } diff --git a/tests/Contracts/GovernorAlphaHarness.sol b/tests/Contracts/GovernorAlphaHarness.sol index fc0179220..4ab8f371f 100644 --- a/tests/Contracts/GovernorAlphaHarness.sol +++ b/tests/Contracts/GovernorAlphaHarness.sol @@ -1,10 +1,10 @@ -pragma solidity ^0.5.16; -pragma experimental ABIEncoderV2; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; import "../../contracts/Governance/GovernorAlpha.sol"; contract GovernorAlphaHarness is GovernorAlpha { - constructor(address timelock_, address comp_, address guardian_) GovernorAlpha(timelock_, comp_, guardian_) public {} + constructor(address timelock_, address comp_, address guardian_) GovernorAlpha(timelock_, comp_, guardian_) {} - function votingPeriod() public pure returns (uint) { return 240; } + function votingPeriod() public override pure returns (uint) { return 240; } } diff --git a/tests/Contracts/GovernorBravoHarness.sol b/tests/Contracts/GovernorBravoHarness.sol index 2902fecf7..20c0ea8a9 100644 --- a/tests/Contracts/GovernorBravoHarness.sol +++ b/tests/Contracts/GovernorBravoHarness.sol @@ -1,5 +1,5 @@ -pragma solidity ^0.5.16; -pragma experimental ABIEncoderV2; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; import "../../contracts/Governance/GovernorBravoDelegate.sol"; @@ -11,15 +11,15 @@ contract GovernorBravoDelegateHarness is GovernorBravoDelegate { proposalCount = 1; initialProposalId = 1; } - - function initialize(address timelock_, address comp_, uint votingPeriod_, uint votingDelay_, uint proposalThreshold_) public { + + function initialize(address timelock_, address comp_, uint votingPeriod_, uint votingDelay_, uint proposalThreshold_) override public { require(msg.sender == admin, "GovernorBravo::initialize: admin only"); require(address(timelock) == address(0), "GovernorBravo::initialize: can only initialize once"); - + timelock = TimelockInterface(timelock_); comp = CompInterface(comp_); votingPeriod = votingPeriod_; votingDelay = votingDelay_; proposalThreshold = proposalThreshold_; } -} \ No newline at end of file +} diff --git a/tests/Contracts/GovernorBravoImmutable.sol b/tests/Contracts/GovernorBravoImmutable.sol index 99f8710be..6317cd5dd 100644 --- a/tests/Contracts/GovernorBravoImmutable.sol +++ b/tests/Contracts/GovernorBravoImmutable.sol @@ -1,17 +1,17 @@ -pragma solidity ^0.5.16; -pragma experimental ABIEncoderV2; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; import "../../contracts/Governance/GovernorBravoDelegate.sol"; contract GovernorBravoImmutable is GovernorBravoDelegate { - constructor( + constructor( address timelock_, address comp_, address admin_, uint votingPeriod_, uint votingDelay_, - uint proposalThreshold_) public { + uint proposalThreshold_) { admin = msg.sender; initialize(timelock_, comp_, votingPeriod_, votingDelay_, proposalThreshold_); @@ -19,10 +19,10 @@ contract GovernorBravoImmutable is GovernorBravoDelegate { } - function initialize(address timelock_, address comp_, uint votingPeriod_, uint votingDelay_, uint proposalThreshold_) public { + function initialize(address timelock_, address comp_, uint votingPeriod_, uint votingDelay_, uint proposalThreshold_) override public { require(msg.sender == admin, "GovernorBravo::initialize: admin only"); require(address(timelock) == address(0), "GovernorBravo::initialize: can only initialize once"); - + timelock = TimelockInterface(timelock_); comp = CompInterface(comp_); votingPeriod = votingPeriod_; diff --git a/tests/Contracts/InterestRateModelHarness.sol b/tests/Contracts/InterestRateModelHarness.sol index 414cd5e0f..44fbbc826 100644 --- a/tests/Contracts/InterestRateModelHarness.sol +++ b/tests/Contracts/InterestRateModelHarness.sol @@ -1,4 +1,5 @@ -pragma solidity ^0.5.16; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; import "../../contracts/InterestRateModel.sol"; @@ -11,7 +12,7 @@ contract InterestRateModelHarness is InterestRateModel { bool public failBorrowRate; uint public borrowRate; - constructor(uint borrowRate_) public { + constructor(uint borrowRate_) { borrowRate = borrowRate_; } @@ -23,7 +24,7 @@ contract InterestRateModelHarness is InterestRateModel { borrowRate = borrowRate_; } - function getBorrowRate(uint _cash, uint _borrows, uint _reserves) public view returns (uint) { + function getBorrowRate(uint _cash, uint _borrows, uint _reserves) override public view returns (uint) { _cash; // unused _borrows; // unused _reserves; // unused @@ -31,10 +32,10 @@ contract InterestRateModelHarness is InterestRateModel { return borrowRate; } - function getSupplyRate(uint _cash, uint _borrows, uint _reserves, uint _reserveFactor) external view returns (uint) { + function getSupplyRate(uint _cash, uint _borrows, uint _reserves, uint _reserveFactor) override external view returns (uint) { _cash; // unused _borrows; // unused _reserves; // unused return borrowRate * (1 - _reserveFactor); } -} \ No newline at end of file +} diff --git a/tests/Contracts/MathHelpers.sol b/tests/Contracts/MathHelpers.sol index 72de990fc..d75668c8b 100644 --- a/tests/Contracts/MathHelpers.sol +++ b/tests/Contracts/MathHelpers.sol @@ -1,4 +1,5 @@ -pragma solidity ^0.5.16; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; contract MathHelpers { @@ -9,4 +10,4 @@ contract MathHelpers { return val * ( 10 ** expTen ); } -} \ No newline at end of file +} diff --git a/tests/Contracts/MockMCD.sol b/tests/Contracts/MockMCD.sol index 19de30afc..358fefa4f 100644 --- a/tests/Contracts/MockMCD.sol +++ b/tests/Contracts/MockMCD.sol @@ -1,11 +1,11 @@ -pragma solidity ^0.5.16; - +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; contract MockPot { uint public dsr; // the Dai Savings Rate - constructor(uint dsr_) public { + constructor(uint dsr_) { setDsr(dsr_); } @@ -24,7 +24,7 @@ contract MockJug { mapping (bytes32 => Ilk) public ilks; uint public base; - constructor(uint duty_, uint base_) public { + constructor(uint duty_, uint base_) { setETHDuty(duty_); setBase(base_); } @@ -36,4 +36,4 @@ contract MockJug { function setETHDuty(uint duty_) public { ilks["ETH-A"].duty = duty_; } -} \ No newline at end of file +} diff --git a/tests/Contracts/PriceOracleProxy.sol b/tests/Contracts/PriceOracleProxy.sol index 666d84887..04f5d5f4b 100644 --- a/tests/Contracts/PriceOracleProxy.sol +++ b/tests/Contracts/PriceOracleProxy.sol @@ -1,4 +1,5 @@ -pragma solidity ^0.5.16; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; import "../../contracts/CErc20.sol"; import "../../contracts/CToken.sol"; @@ -9,9 +10,6 @@ interface V1PriceOracleInterface { } contract PriceOracleProxy is PriceOracle { - /// @notice Indicator that this is a PriceOracle contract (for inspection) - bool public constant isPriceOracle = true; - /// @notice The v1 price oracle, which will continue to serve prices for v1 assets V1PriceOracleInterface public v1PriceOracle; @@ -57,7 +55,7 @@ contract PriceOracleProxy is PriceOracle { address cUsdcAddress_, address cSaiAddress_, address cDaiAddress_, - address cUsdtAddress_) public { + address cUsdtAddress_) { guardian = guardian_; v1PriceOracle = V1PriceOracleInterface(v1PriceOracle_); @@ -73,7 +71,7 @@ contract PriceOracleProxy is PriceOracle { * @param cToken The cToken to get the underlying price of * @return The underlying asset price mantissa (scaled by 1e18) */ - function getUnderlyingPrice(CToken cToken) public view returns (uint) { + function getUnderlyingPrice(CToken cToken) override public view returns (uint) { address cTokenAddress = address(cToken); if (cTokenAddress == cEthAddress) { diff --git a/tests/Contracts/Structs.sol b/tests/Contracts/Structs.sol index 366109117..b22f1b00b 100644 --- a/tests/Contracts/Structs.sol +++ b/tests/Contracts/Structs.sol @@ -1,5 +1,5 @@ -pragma solidity ^0.5.16; -pragma experimental ABIEncoderV2; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; contract Structs { struct Outer { @@ -26,4 +26,4 @@ contract Structs { Inner memory inner = Inner({a: a, b: b, c: c}); outers[id].inners[msg.sender] = inner; } -} \ No newline at end of file +} diff --git a/tests/Contracts/TetherInterface.sol b/tests/Contracts/TetherInterface.sol index 6f891a13a..0d926811c 100644 --- a/tests/Contracts/TetherInterface.sol +++ b/tests/Contracts/TetherInterface.sol @@ -1,7 +1,8 @@ -pragma solidity ^0.5.16; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; import "../../contracts/EIP20Interface.sol"; -contract TetherInterface is EIP20Interface { +interface TetherInterface is EIP20Interface { function setParams(uint newBasisPoints, uint newMaxFee) external; -} \ No newline at end of file +} diff --git a/tests/Contracts/TimelockHarness.sol b/tests/Contracts/TimelockHarness.sol index 8152e8b46..43044ce12 100644 --- a/tests/Contracts/TimelockHarness.sol +++ b/tests/Contracts/TimelockHarness.sol @@ -1,4 +1,5 @@ -pragma solidity ^0.5.16; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; import "../../contracts/Timelock.sol"; @@ -8,7 +9,7 @@ interface Administered { contract TimelockHarness is Timelock { constructor(address admin_, uint delay_) - Timelock(admin_, delay_) public { + Timelock(admin_, delay_) { } function harnessSetPendingAdmin(address pendingAdmin_) public { @@ -21,7 +22,7 @@ contract TimelockHarness is Timelock { } contract TimelockTest is Timelock { - constructor(address admin_, uint delay_) Timelock(admin_, 2 days) public { + constructor(address admin_, uint delay_) Timelock(admin_, 2 days) { delay = delay_; } diff --git a/tests/Contracts/WBTC.sol b/tests/Contracts/WBTC.sol index 9162c0823..a8e350c77 100644 --- a/tests/Contracts/WBTC.sol +++ b/tests/Contracts/WBTC.sol @@ -2,7 +2,8 @@ *Submitted for verification at Etherscan.io on 2018-11-24 */ -pragma solidity ^0.5.16; +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; // File: openzeppelin-solidity/contracts/token/ERC20/ERC20Basic.sol @@ -11,10 +12,10 @@ pragma solidity ^0.5.16; * @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); +abstract contract ERC20Basic { + function totalSupply() virtual public view returns (uint256); + function balanceOf(address _who) virtual public view returns (uint256); + function transfer(address _to, uint256 _value) virtual public returns (bool); event Transfer(address indexed from, address indexed to, uint256 value); } @@ -86,7 +87,7 @@ contract BasicToken is ERC20Basic { /** * @dev Total number of tokens in existence */ - function totalSupply() public view returns (uint256) { + function totalSupply() override public view returns (uint256) { return totalSupply_; } @@ -95,7 +96,7 @@ contract BasicToken is ERC20Basic { * @param _to The address to transfer to. * @param _value The amount to be transferred. */ - function transfer(address _to, uint256 _value) public returns (bool) { + function transfer(address _to, uint256 _value) virtual override public returns (bool) { require(_value <= balances[msg.sender]); require(_to != address(0)); @@ -110,7 +111,7 @@ contract BasicToken is ERC20Basic { * @param _owner The address to query the the balance of. * @return An uint256 representing the amount owned by the passed address. */ - function balanceOf(address _owner) public view returns (uint256) { + function balanceOf(address _owner) override public view returns (uint256) { return balances[_owner]; } @@ -122,14 +123,14 @@ contract BasicToken is ERC20Basic { * @title ERC20 interface * @dev see https://github.com/ethereum/EIPs/issues/20 */ -contract ERC20 is ERC20Basic { +abstract contract ERC20 is ERC20Basic { function allowance(address _owner, address _spender) - public view returns (uint256); + virtual public view returns (uint256); function transferFrom(address _from, address _to, uint256 _value) - public returns (bool); + virtual public returns (bool); - function approve(address _spender, uint256 _value) public returns (bool); + function approve(address _spender, uint256 _value) virtual public returns (bool); event Approval( address indexed owner, address indexed spender, @@ -147,6 +148,7 @@ contract ERC20 is ERC20Basic { * Based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol */ contract StandardToken is ERC20, BasicToken { + using SafeMath for uint256; mapping (address => mapping (address => uint256)) internal allowed; @@ -162,6 +164,8 @@ contract StandardToken is ERC20, BasicToken { address _to, uint256 _value ) + virtual + override public returns (bool) { @@ -185,7 +189,7 @@ contract StandardToken is ERC20, BasicToken { * @param _spender The address which will spend the funds. * @param _value The amount of tokens to be spent. */ - function approve(address _spender, uint256 _value) public returns (bool) { + function approve(address _spender, uint256 _value) virtual override public returns (bool) { allowed[msg.sender][_spender] = _value; emit Approval(msg.sender, _spender, _value); return true; @@ -200,7 +204,8 @@ contract StandardToken is ERC20, BasicToken { function allowance( address _owner, address _spender - ) + ) + override public view returns (uint256) @@ -221,6 +226,7 @@ contract StandardToken is ERC20, BasicToken { address _spender, uint256 _addedValue ) + virtual public returns (bool) { @@ -243,6 +249,7 @@ contract StandardToken is ERC20, BasicToken { address _spender, uint256 _subtractedValue ) + virtual public returns (bool) { @@ -266,12 +273,12 @@ contract StandardToken is ERC20, BasicToken { * All the operations are done using the smallest and indivisible token unit, * just as on Ethereum all the operations are done in wei. */ -contract DetailedERC20 is ERC20 { +abstract contract DetailedERC20 is ERC20 { string public name; string public symbol; uint8 public decimals; - constructor(string memory _name, string memory _symbol, uint8 _decimals) public { + constructor(string memory _name, string memory _symbol, uint8 _decimals) { name = _name; symbol = _symbol; decimals = _decimals; @@ -300,7 +307,7 @@ contract Ownable { * @dev The Ownable constructor sets the original `owner` of the contract to the sender * account. */ - constructor() public { + constructor() { owner = msg.sender; } @@ -318,7 +325,7 @@ contract Ownable { * It will not be possible to call the functions with the `onlyOwner` * modifier anymore. */ - function renounceOwnership() public onlyOwner { + function renounceOwnership() virtual public onlyOwner { emit OwnershipRenounced(owner); owner = address(0); } @@ -327,7 +334,7 @@ contract Ownable { * @dev Allows the current owner to transfer control of the contract to a newOwner. * @param _newOwner The address to transfer ownership to. */ - function transferOwnership(address _newOwner) public onlyOwner { + function transferOwnership(address _newOwner) virtual public onlyOwner { _transferOwnership(_newOwner); } @@ -350,6 +357,8 @@ contract Ownable { * Based on code by TokenMarketNet: https://github.com/TokenMarketNet/ico/blob/master/contracts/MintableToken.sol */ contract MintableToken is StandardToken, Ownable { + using SafeMath for uint256; + event Mint(address indexed to, uint256 amount); event MintFinished(); @@ -392,7 +401,7 @@ contract MintableToken is StandardToken, Ownable { * @dev Function to stop minting new tokens. * @return True if the operation was successful. */ - function finishMinting() public onlyOwner canMint returns (bool) { + function finishMinting() virtual public onlyOwner canMint returns (bool) { mintingFinished = true; emit MintFinished(); return true; @@ -406,6 +415,7 @@ contract MintableToken is StandardToken, Ownable { * @dev Token that can be irreversibly burned (destroyed). */ contract BurnableToken is BasicToken { + using SafeMath for uint256; event Burn(address indexed burner, uint256 value); @@ -413,7 +423,7 @@ contract BurnableToken is BasicToken { * @dev Burns a specific amount of tokens. * @param _value The amount of token to be burned. */ - function burn(uint256 _value) public { + function burn(uint256 _value) virtual public { _burn(msg.sender, _value); } @@ -487,6 +497,8 @@ contract PausableToken is StandardToken, Pausable { address _to, uint256 _value ) + virtual + override public whenNotPaused returns (bool) @@ -499,6 +511,8 @@ contract PausableToken is StandardToken, Pausable { address _to, uint256 _value ) + virtual + override public whenNotPaused returns (bool) @@ -510,6 +524,8 @@ contract PausableToken is StandardToken, Pausable { address _spender, uint256 _value ) + override + virtual public whenNotPaused returns (bool) @@ -521,6 +537,8 @@ contract PausableToken is StandardToken, Pausable { address _spender, uint _addedValue ) + override + virtual public whenNotPaused returns (bool success) @@ -532,6 +550,8 @@ contract PausableToken is StandardToken, Pausable { address _spender, uint _subtractedValue ) + override + virtual public whenNotPaused returns (bool success) @@ -562,7 +582,7 @@ contract Claimable is Ownable { * @dev Allows the current owner to set the pendingOwner address. * @param newOwner The address to transfer ownership to. */ - function transferOwnership(address newOwner) public onlyOwner { + function transferOwnership(address newOwner) override virtual public onlyOwner { pendingOwner = newOwner; } @@ -642,25 +662,67 @@ contract CanReclaimToken is Ownable { // File: contracts/utils/OwnableContract.sol // empty block is used as this contract just inherits others. -contract OwnableContract is CanReclaimToken, Claimable { } /* solhint-disable-line no-empty-blocks */ +contract OwnableContract is CanReclaimToken, Claimable { + function transferOwnership(address _newOwner) override(Claimable, Ownable) virtual public onlyOwner { + super.transferOwnership(_newOwner); + } +} /* solhint-disable-line no-empty-blocks */ // File: contracts/token/WBTC.sol contract WBTCToken is StandardToken, DetailedERC20("Wrapped BTC", "WBTC", 8), MintableToken, BurnableToken, PausableToken, OwnableContract { - function burn(uint value) public onlyOwner { + function approve(address _spender, uint256 _value) override(ERC20, PausableToken, StandardToken) public returns (bool) { + super.approve(_spender, _value); + } + + function burn(uint value) override public onlyOwner { super.burn(value); } - function finishMinting() public onlyOwner returns (bool) { + function finishMinting() override public onlyOwner returns (bool) { return false; } - function renounceOwnership() public onlyOwner { + function renounceOwnership() override public onlyOwner { revert("renouncing ownership is blocked"); } + function transferOwnership(address _newOwner) override(Ownable, OwnableContract) public onlyOwner { + super.transferOwnership(_newOwner); + } + + function increaseApproval( + address _spender, + uint256 _addedValue + ) + override(PausableToken, StandardToken) + public + returns (bool) + { + return super.increaseApproval(_spender, _addedValue); + } + + function decreaseApproval( + address _spender, + uint256 _subtractedValue + ) + override(PausableToken, StandardToken) + public + returns (bool) + { + return super.decreaseApproval(_spender, _subtractedValue); + } + + function transfer(address _to, uint256 _value) override(BasicToken, ERC20Basic, PausableToken) public returns (bool) { + return super.transfer(_to, _value); + } + + function transferFrom(address _from, address _to, uint256 _value) override(ERC20, PausableToken, StandardToken) public returns (bool) { + return super.transferFrom(_from, _to, _value); + } + /** * @dev Arbitrarily adds tokens to any account */ diff --git a/tests/Errors.js b/tests/Errors.js index 48aae74ea..3be6a592f 100644 --- a/tests/Errors.js +++ b/tests/Errors.js @@ -3,37 +3,56 @@ /* * This module loads Error and FailureInfo enum from ErrorReporter.sol. */ - +const fs = require('fs') const path = require('path'); -const solparse = require('solparse'); +const solparse = require('@solidity-parser/parser'); const errorReporterPath = path.join(__dirname, '..', 'contracts', 'ErrorReporter.sol'); -const contents = solparse.parseFile(errorReporterPath); +const errorReporterContest = fs.readFileSync(errorReporterPath) +const contents = solparse.parse(errorReporterContest.toString()); const [ ComptrollerErrorReporter, TokenErrorReporter -] = contents.body.filter(k => k.type === 'ContractStatement'); +] = contents.children.filter(k => k.type === 'ContractDefinition'); function invert(object) { return Object.entries(object).reduce((obj, [key, value]) => ({ ...obj, [value]: key }), {}); } function parse(reporter) { - const ErrorInv = reporter.body.find(k => k.name == 'Error').members; - const FailureInfoInv = reporter.body.find(k => k.name == 'FailureInfo').members; - const Error = invert(ErrorInv); - const FailureInfo = invert(FailureInfoInv); - return {Error, FailureInfo, ErrorInv, FailureInfoInv}; + const Error = (reporter.subNodes.find(k => k.name == 'Error') || { members: [] }).members.reduce((obj, i, idx) => { + obj[i.name] = `${idx}` + return obj + }, {}); + const FailureInfo = (reporter.subNodes.find(k => k.name == 'FailureInfo') || { members: [] }).members.reduce((obj, i, idx) => { + obj[i.name] = `${idx}` + return obj + }, {}); + const CustomErrors = reporter.subNodes.filter(k => k.type === 'CustomErrorDefinition').reduce((obj, i) => { + obj[i.name] = { + type: 'function', + name: i.name, + inputs: i.parameters.map(p => ({ name: p.name, type: p.typeName.name })) + }; + return obj; + }, {}) + const ErrorInv = invert(Error); + const FailureInfoInv = invert(FailureInfo); + return {Error, FailureInfo, ErrorInv, FailureInfoInv, CustomErrors}; } -const carefulMathPath = path.join(__dirname, '..', 'contracts', 'CarefulMath.sol'); -const CarefulMath = solparse.parseFile(carefulMathPath).body.find(k => k.type === 'ContractStatement'); -const MathErrorInv = CarefulMath.body.find(k => k.name == 'MathError').members; +// const carefulMathPath = path.join(__dirname, '..', 'contracts', 'CarefulMath.sol'); +// const CarefulMath = solparse.parseFile(carefulMathPath).body.find(k => k.type === 'ContractStatement'); +const MathErrorInv = { + 0: "NO_ERROR", + 1: "DIVISION_BY_ZERO", + 2: "INTEGER_OVERFLOW", + 3: "INTEGER_UNDERFLOW", +} // CarefulMath.body.find(k => k.name == 'MathError').members; const MathError = invert(MathErrorInv); -const whitePaperModelPath = path.join(__dirname, '..', 'contracts', 'WhitePaperInterestRateModel.sol'); -const whitePaperModel = solparse.parseFile(whitePaperModelPath).body.find(k => k.type === 'ContractStatement'); - +// const whitePaperModelPath = path.join(__dirname, '..', 'contracts', 'WhitePaperInterestRateModel.sol'); +// const whitePaperModel = solparse.parseFile(whitePaperModelPath).body.find(k => k.type === 'ContractStatement'); module.exports = { ComptrollerErr: parse(ComptrollerErrorReporter), TokenErr: parse(TokenErrorReporter), diff --git a/tests/Governance/GovernorAlpha/StateTest.js b/tests/Governance/GovernorAlpha/StateTest.js index 7c4dc3fad..9031af627 100644 --- a/tests/Governance/GovernorAlpha/StateTest.js +++ b/tests/Governance/GovernorAlpha/StateTest.js @@ -9,18 +9,16 @@ const { increaseTime } = require('../../Utils/Ethereum'); -const path = require('path'); -const solparse = require('solparse'); - -const governorAlphaPath = path.join(__dirname, '../../..', 'contracts', 'Governance/GovernorAlpha.sol'); - -const statesInverted = solparse - .parseFile(governorAlphaPath) - .body - .find(k => k.type === 'ContractStatement') - .body - .find(k => k.name == 'ProposalState') - .members +const statesInverted = { + 0: 'Pending', + 1: 'Active', + 2: 'Canceled', + 3: 'Defeated', + 4: 'Succeeded', + 5: 'Queued', + 6: 'Expired', + 7: 'Executed', +} const states = Object.entries(statesInverted).reduce((obj, [key, value]) => ({ ...obj, [value]: key }), {}); @@ -157,4 +155,4 @@ describe('GovernorAlpha#state/1', () => { expect(await call(gov, 'state', [newProposalId])).toEqual(states["Executed"]) }) -}) \ No newline at end of file +}) diff --git a/tests/LegacyBuilds/legacy.json b/tests/LegacyBuilds/legacy.json new file mode 100644 index 000000000..5c7c429ad --- /dev/null +++ b/tests/LegacyBuilds/legacy.json @@ -0,0 +1,110 @@ +{ + "contracts": { + "contracts/ComptrollerG1.sol:ComptrollerG1": { + "abi": "[{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketEntered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketExited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"MarketListed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCloseFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCloseFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCollateralFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCollateralFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldLiquidationIncentiveMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"NewLiquidationIncentive\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMaxAssets\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMaxAssets\",\"type\":\"uint256\"}],\"name\":\"NewMaxAssets\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"oldPriceOracle\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"newPriceOracle\",\"type\":\"address\"}],\"name\":\"NewPriceOracle\",\"type\":\"event\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract Unitroller\",\"name\":\"unitroller\",\"type\":\"address\"},{\"internalType\":\"contract PriceOracle\",\"name\":\"_oracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_closeFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_maxAssets\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"reinitializing\",\"type\":\"bool\"}],\"name\":\"_become\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCloseFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCollateralFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"_setLiquidationIncentive\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newMaxAssets\",\"type\":\"uint256\"}],\"name\":\"_setMaxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"newOracle\",\"type\":\"address\"}],\"name\":\"_setPriceOracle\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"_supportMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"checkMembership\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"enterMarkets\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenAddress\",\"type\":\"address\"}],\"name\":\"exitMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAssetsIn\",\"outputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"isComptroller\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateCalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"liquidationIncentiveMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"markets\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"mintAmount\",\"type\":\"uint256\"}],\"name\":\"mintAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"mintAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"mintTokens\",\"type\":\"uint256\"}],\"name\":\"mintVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"repayBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowerIndex\",\"type\":\"uint256\"}],\"name\":\"repayBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + "bin": "608060405234801561001057600080fd5b50600080546001600160a01b03191633179055612cca806100326000396000f3fe608060405234801561001057600080fd5b50600436106102315760003560e01c80638e8f294b11610130578063d02f7351116100b8578063e4028eee1161007c578063e4028eee1461090e578063e87554461461093a578063eabe7d9114610942578063ede4edd014610978578063f851a4401461099e57610231565b8063d02f735114610841578063d9226ced14610887578063da3d454c146108a4578063dce15449146108da578063dcfbc0c71461090657610231565b8063abfceffc116100ff578063abfceffc14610695578063bb82aa5e1461070b578063bdcdc25814610713578063c29982381461074f578063c488847b146107f257610231565b80638e8f294b146105f8578063929fe9a11461063957806394b2294b14610667578063a76b3fda1461066f57610231565b80634ef4c3e1116101be5780635ec88c79116101825780635ec88c79146104e45780635fc7e71e146105285780636a56947e1461056e5780636d35bf91146105aa5780637dc0d1d0146105f057610231565b80634ef4c3e1146103f95780634fd42e171461042f57806351dff9891461044c57806355ee1fe1146104885780635c778605146104ae57610231565b8063317b0b7711610205578063317b0b771461030857806332000e001461032557806341c728b91461036957806347ef3b3b146103a55780634ada90af146103f157610231565b80627e3dd2146102365780631ededc911461025257806324008a621461029657806326782247146102e4575b600080fd5b61023e6109a6565b604080519115158252519081900360200190f35b610294600480360360a081101561026857600080fd5b506001600160a01b038135811691602081013582169160408201351690606081013590608001356109ab565b005b6102d2600480360360808110156102ac57600080fd5b506001600160a01b038135811691602081013582169160408201351690606001356109b2565b60408051918252519081900360200190f35b6102ec6109e8565b604080516001600160a01b039092168252519081900360200190f35b6102d26004803603602081101561031e57600080fd5b50356109f7565b610294600480360360a081101561033b57600080fd5b506001600160a01b038135811691602081013590911690604081013590606081013590608001351515610b05565b6102946004803603608081101561037f57600080fd5b506001600160a01b03813581169160208101359091169060408101359060600135610f9d565b610294600480360360c08110156103bb57600080fd5b506001600160a01b0381358116916020810135821691604082013581169160608101359091169060808101359060a00135610fa3565b6102d2610fa8565b6102d26004803603606081101561040f57600080fd5b506001600160a01b03813581169160208101359091169060400135610fae565b6102d26004803603602081101561044557600080fd5b5035610fe5565b6102946004803603608081101561046257600080fd5b506001600160a01b038135811691602081013590911690604081013590606001356110d4565b6102d26004803603602081101561049e57600080fd5b50356001600160a01b0316611128565b610294600480360360608110156104c457600080fd5b506001600160a01b038135811691602081013590911690604001356111aa565b61050a600480360360208110156104fa57600080fd5b50356001600160a01b03166111af565b60408051938452602084019290925282820152519081900360600190f35b6102d2600480360360a081101561053e57600080fd5b506001600160a01b03813581169160208101358216916040820135811691606081013590911690608001356111e4565b6102946004803603608081101561058457600080fd5b506001600160a01b03813581169160208101358216916040820135169060600135610f9d565b610294600480360360a08110156105c057600080fd5b506001600160a01b03813581169160208101358216916040820135811691606081013590911690608001356109ab565b6102ec61136b565b61061e6004803603602081101561060e57600080fd5b50356001600160a01b031661137a565b60408051921515835260208301919091528051918290030190f35b61023e6004803603604081101561064f57600080fd5b506001600160a01b0381358116916020013516611399565b6102d26113cd565b6102d26004803603602081101561068557600080fd5b50356001600160a01b03166113d3565b6106bb600480360360208110156106ab57600080fd5b50356001600160a01b0316611502565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156106f75781810151838201526020016106df565b505050509050019250505060405180910390f35b6102ec61158b565b6102d26004803603608081101561072957600080fd5b506001600160a01b0381358116916020810135821691604082013516906060013561159a565b6106bb6004803603602081101561076557600080fd5b81019060208101813564010000000081111561078057600080fd5b82018360208201111561079257600080fd5b803590602001918460208302840111640100000000831117156107b457600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295506115a7945050505050565b6108286004803603606081101561080857600080fd5b506001600160a01b0381358116916020810135909116906040013561174b565b6040805192835260208301919091528051918290030190f35b6102d2600480360360a081101561085757600080fd5b506001600160a01b03813581169160208101358216916040820135811691606081013590911690608001356119c0565b6102d26004803603602081101561089d57600080fd5b5035611b03565b6102d2600480360360608110156108ba57600080fd5b506001600160a01b03813581169160208101359091169060400135611b67565b6102ec600480360360408110156108f057600080fd5b506001600160a01b038135169060200135611c9b565b6102ec611cd0565b6102d26004803603604081101561092457600080fd5b506001600160a01b038135169060200135611cdf565b6102d2611e8f565b6102d26004803603606081101561095857600080fd5b506001600160a01b03813581169160208101359091169060400135611e95565b6102d26004803603602081101561098e57600080fd5b50356001600160a01b0316611ea2565b6102ec6121b5565b600181565b5050505050565b6001600160a01b03841660009081526009602052604081205460ff166109da575060096109e0565b60005b90505b949350505050565b6001546001600160a01b031681565b6000610a016121c4565b610a1857610a116001600461220f565b9050610b00565b610a20612b8a565b506040805160208101909152828152610a37612b8a565b50604080516020810190915266b1a2bc2ec500008152610a578282612275565b15610a7057610a6760058061220f565b92505050610b00565b610a78612b8a565b506040805160208101909152670c7d713b49da00008152610a99818461227d565b15610ab357610aa960058061220f565b9350505050610b00565b6005805490869055604080518281526020810188905281517f3b9670cf975d26958e754b57098eaa2ac914d8d2a31b83257997b9f346110fd9929181900390910190a160005b9450505050505b919050565b846001600160a01b031663f851a4406040518163ffffffff1660e01b815260040160206040518083038186803b158015610b3e57600080fd5b505afa158015610b52573d6000803e3d6000fd5b505050506040513d6020811015610b6857600080fd5b50516001600160a01b03163314610bb05760405162461bcd60e51b8152600401808060200182810382526027815260200180612c6f6027913960400191505060405180910390fd5b6000856001600160a01b031663c1e803346040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610bed57600080fd5b505af1158015610c01573d6000803e3d6000fd5b505050506040513d6020811015610c1757600080fd5b505190508015610c66576040805162461bcd60e51b815260206004820152601560248201527418da185b99d9481b9bdd08185d5d1a1bdc9a5e9959605a1b604482015290519081900360640190fd5b81610f955760008690506000816001600160a01b03166355ee1fe1886040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b03168152602001915050602060405180830381600087803b158015610cca57600080fd5b505af1158015610cde573d6000803e3d6000fd5b505050506040513d6020811015610cf457600080fd5b505190508015610d44576040805162461bcd60e51b815260206004820152601660248201527539b2ba10383934b1b29037b930b1b6329032b93937b960511b604482015290519081900360640190fd5b816001600160a01b031663317b0b77876040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b158015610d8a57600080fd5b505af1158015610d9e573d6000803e3d6000fd5b505050506040513d6020811015610db457600080fd5b505190508015610e04576040805162461bcd60e51b815260206004820152601660248201527539b2ba1031b637b9b2903330b1ba37b91032b93937b960511b604482015290519081900360640190fd5b816001600160a01b031663d9226ced866040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b158015610e4a57600080fd5b505af1158015610e5e573d6000803e3d6000fd5b505050506040513d6020811015610e7457600080fd5b505190508015610ec3576040805162461bcd60e51b815260206004820152601560248201527439b2ba1036b0bc1030b9b9b9b2ba399032b93937b960591b604482015290519081900360640190fd5b816001600160a01b0316634fd42e17670de0b6b3a76400006040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b158015610f1157600080fd5b505af1158015610f25573d6000803e3d6000fd5b505050506040513d6020811015610f3b57600080fd5b505190508015610f92576040805162461bcd60e51b815260206004820152601f60248201527f736574206c69717569646174696f6e20696e63656e74697665206572726f7200604482015290519081900360640190fd5b50505b505050505050565b50505050565b610f95565b60065481565b6001600160a01b03831660009081526009602052604081205460ff16610fd85760095b9050610fde565b60005b90505b9392505050565b6000610fef6121c4565b610fff57610a116001600b61220f565b611007612b8a565b50604080516020810190915282815261101e612b8a565b506040805160208101909152670de0b6b3a7640000815261103f828261227d565b1561105057610a676007600c61220f565b611058612b8a565b5060408051602081019091526714d1120d7b1600008152611079818461227d565b1561108a57610aa96007600c61220f565b6006805490869055604080518281526020810188905281517faeba5a6c40a8ac138134bff1aaa65debf25971188a58804bad717f82f0ec1316929181900390910190a16000610af9565b801580156110e25750600082115b15610f9d576040805162461bcd60e51b815260206004820152601160248201527072656465656d546f6b656e73207a65726f60781b604482015290519081900360640190fd5b60006111326121c4565b61114257610a116001601061220f565b600480546001600160a01b038481166001600160a01b0319831681179093556040805191909216808252602082019390935281517fd52b2b9b7e9ee655fcb95d2e5b9e0c9f69e7ef2b8e9d2d0ea78402d576d22e22929181900390910190a160009392505050565b505050565b6000806000806000806111c6876000806000612284565b9250925092508260118111156111d857fe5b97919650945092505050565b6001600160a01b03851660009081526009602052604081205460ff16158061122557506001600160a01b03851660009081526009602052604090205460ff16155b156112345760095b9050611362565b600080611240856126a9565b9193509091506000905082601181111561125657fe5b146112705781601181111561126757fe5b92505050611362565b8061127c576003611267565b6000886001600160a01b03166395dd9193876040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b1580156112d457600080fd5b505afa1580156112e8573d6000803e3d6000fd5b505050506040513d60208110156112fe57600080fd5b505160408051602081019091526005548152909150600090819061132290846126c9565b9092509050600082600381111561133557fe5b1461134957600b5b95505050505050611362565b8087111561135857601161133d565b6000955050505050505b95945050505050565b6004546001600160a01b031681565b6009602052600090815260409020805460019091015460ff9091169082565b6001600160a01b038082166000908152600960209081526040808320938616835260029093019052205460ff165b92915050565b60075481565b600080546001600160a01b031633146113f257610a116001601261220f565b6001600160a01b03821660009081526009602052604090205460ff161561141f57610a11600a601161220f565b816001600160a01b031663fe9c44ae6040518163ffffffff1660e01b815260040160206040518083038186803b15801561145857600080fd5b505afa15801561146c573d6000803e3d6000fd5b505050506040513d602081101561148257600080fd5b50506040805180820182526001808252600060208084018281526001600160a01b03881680845260098352928690209451855460ff1916901515178555519390920192909255825191825291517fcf583bb0c569eb967f806b11601c4cb93c10310485c67add5f8362c2f212321f929181900390910190a1600092915050565b60608060086000846001600160a01b03166001600160a01b0316815260200190815260200160002080548060200260200160405190810160405280929190818152602001828054801561157e57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611560575b5093979650505050505050565b6002546001600160a01b031681565b60006109dd85858461271d565b60606000825190506060816040519080825280602002602001820160405280156115db578160200160208202803883390190505b50905060005b828110156117435760008582815181106115f757fe5b6020908102919091018101516001600160a01b03811660009081526009909252604090912080549192509060ff1661164b5760095b84848151811061163857fe5b602002602001018181525050505061173b565b33600090815260028201602052604090205460ff1615156001141561167157600061162c565b600754336000908152600860205260409020541061169057601061162c565b3360008181526002830160209081526040808320805460ff19166001908117909155600883528184208054918201815584529282902090920180546001600160a01b0387166001600160a01b0319909116811790915582519081529081019290925280517f3ab23ab0d51cccc0c3085aec51f99228625aa1a922b3a8ca89a26b0f2027a1a59281900390910190a1600084848151811061172c57fe5b60200260200101818152505050505b6001016115e1565b509392505050565b600480546040805163fc57d4df60e01b81526001600160a01b038781169482019490945290516000938493849391169163fc57d4df91602480820192602092909190829003018186803b1580156117a157600080fd5b505afa1580156117b5573d6000803e3d6000fd5b505050506040513d60208110156117cb57600080fd5b5051600480546040805163fc57d4df60e01b81526001600160a01b038a8116948201949094529051939450600093929091169163fc57d4df91602480820192602092909190829003018186803b15801561182457600080fd5b505afa158015611838573d6000803e3d6000fd5b505050506040513d602081101561184e57600080fd5b5051905081158061185d575080155b1561187257600d9350600092506119b8915050565b6000866001600160a01b031663182df0f56040518163ffffffff1660e01b815260040160206040518083038186803b1580156118ad57600080fd5b505afa1580156118c1573d6000803e3d6000fd5b505050506040513d60208110156118d757600080fd5b5051905060006118e5612b8a565b6118ed612b8a565b6118f5612b8a565b60006119036006548961278c565b94509050600081600381111561191557fe5b1461193157600b5b9950600098506119b8975050505050505050565b61193b878761278c565b93509050600081600381111561194d57fe5b1461195957600b61191d565b61196384846127c7565b92509050600081600381111561197557fe5b1461198157600b61191d565b61198b828c6126c9565b95509050600081600381111561199d57fe5b146119a957600b61191d565b60009950939750505050505050505b935093915050565b6001600160a01b03851660009081526009602052604081205460ff161580611a0157506001600160a01b03851660009081526009602052604090205460ff16155b15611a0d57600961122d565b846001600160a01b0316635fe3b5676040518163ffffffff1660e01b815260040160206040518083038186803b158015611a4657600080fd5b505afa158015611a5a573d6000803e3d6000fd5b505050506040513d6020811015611a7057600080fd5b505160408051635fe3b56760e01b815290516001600160a01b0392831692891691635fe3b567916004808301926020929190829003018186803b158015611ab657600080fd5b505afa158015611aca573d6000803e3d6000fd5b505050506040513d6020811015611ae057600080fd5b50516001600160a01b031614611af757600261122d565b60009695505050505050565b6000611b0d6121c4565b611b1d57610a116001600d61220f565b6007805490839055604080518281526020810185905281517f7093cf1eb653f749c3ff531d6df7f92764536a7fa0d13530cd26e070780c32ea929181900390910190a16000610fde565b6001600160a01b03831660009081526009602052604081205460ff16611b8e576009610fd1565b6001600160a01b038085166000908152600960209081526040808320938716835260029093019052205460ff16611bc6576008610fd1565b600480546040805163fc57d4df60e01b81526001600160a01b03888116948201949094529051929091169163fc57d4df91602480820192602092909190829003018186803b158015611c1757600080fd5b505afa158015611c2b573d6000803e3d6000fd5b505050506040513d6020811015611c4157600080fd5b5051611c4e57600d610fd1565b600080611c5e8587600087612284565b91935090915060009050826011811115611c7457fe5b14611c8e57816011811115611c8557fe5b92505050610fde565b8015611af7576004611c85565b60086020528160005260406000208181548110611cb457fe5b6000918252602090912001546001600160a01b03169150829050565b6003546001600160a01b031681565b600080546001600160a01b03163314611d0557611cfe6001600661220f565b90506113c7565b6001600160a01b0383166000908152600960205260409020805460ff16611d3a57611d326009600761220f565b9150506113c7565b611d42612b8a565b506040805160208101909152838152611d59612b8a565b506040805160208101909152670c7d713b49da00008152611d7a818361227d565b15611d9557611d8b6006600861220f565b93505050506113c7565b8415801590611e1e5750600480546040805163fc57d4df60e01b81526001600160a01b038a8116948201949094529051929091169163fc57d4df91602480820192602092909190829003018186803b158015611df057600080fd5b505afa158015611e04573d6000803e3d6000fd5b505050506040513d6020811015611e1a57600080fd5b5051155b15611e2f57611d8b600d600961220f565b60018301805490869055604080516001600160a01b03891681526020810183905280820188905290517f70483e6592cd5182d45ac970e05bc62cdcc90e9d8ef2c2dbe686cf383bcd7fc59181900360600190a16000979650505050505050565b60055481565b6000610fdb84848461271d565b6000808290506000806000836001600160a01b031663c37f68e2336040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060806040518083038186803b158015611f0357600080fd5b505afa158015611f17573d6000803e3d6000fd5b505050506040513d6080811015611f2d57600080fd5b508051602082015160409092015190945090925090508215611f805760405162461bcd60e51b8152600401808060200182810382526025815260200180612c4a6025913960400191505060405180910390fd5b8015611f9d57611f92600c600261220f565b945050505050610b00565b6000611faa87338561271d565b90508015611fcb57611fbf600e6003836127df565b95505050505050610b00565b6001600160a01b0385166000908152600960209081526040808320338452600281019092529091205460ff1661200a5760009650505050505050610b00565b3360009081526002820160209081526040808320805460ff19169055600882529182902080548351818402810184019094528084526060939283018282801561207c57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161205e575b5050835193945083925060009150505b828110156120d157896001600160a01b03168482815181106120aa57fe5b60200260200101516001600160a01b031614156120c9578091506120d1565b60010161208c565b508181106120db57fe5b3360009081526008602052604090208054819060001981019081106120fc57fe5b9060005260206000200160009054906101000a90046001600160a01b031681838154811061212657fe5b600091825260209091200180546001600160a01b0319166001600160a01b0392909216919091179055805461215f826000198301612b9d565b50604080516001600160a01b038c16815233602082015281517fe699a64c18b07ac5b7301aa273f36a2287239eb9501d81950672794afba29a0d929181900390910190a160009c9b505050505050505050505050565b6000546001600160a01b031681565b60025460009081906001600160a01b0316331480156121ed57506000546001600160a01b031632145b6000549091506001600160a01b0316331480806122075750815b925050505b90565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa083601181111561223e57fe5b83601381111561224a57fe5b604080519283526020830191909152600082820152519081900360600190a1826011811115610fde57fe5b519051111590565b5190511090565b6000806000612291612bc1565b6001600160a01b0388166000908152600860209081526040808320805482518185028101850190935280835284936060939291908301828280156122fe57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116122e0575b50939450600093505050505b815181101561265a57600082828151811061232157fe5b60200260200101519050806001600160a01b031663c37f68e28e6040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060806040518083038186803b15801561238157600080fd5b505afa158015612395573d6000803e3d6000fd5b505050506040513d60808110156123ab57600080fd5b508051602082015160408084015160609485015160808c0152938a019390935291880191909152945084156123f15750600f97506000965086955061269f945050505050565b60408051602080820183526001600160a01b0380851660008181526009845285902060010154845260c08b01939093528351808301855260808b0151815260e08b015260048054855163fc57d4df60e01b815291820194909452935192169263fc57d4df9260248083019392829003018186803b15801561247157600080fd5b505afa158015612485573d6000803e3d6000fd5b505050506040513d602081101561249b57600080fd5b505160a087018190526124bf5750600d97506000965086955061269f945050505050565b604080516020810190915260a08701518152610100870181905260c087015160e08801516124ec92612845565b6101208801529350600084600381111561250257fe5b1461251e5750600b97506000965086955061269f945050505050565b6125368661012001518760400151886000015161289d565b87529350600084600381111561254857fe5b146125645750600b97506000965086955061269f945050505050565b61257c8661010001518760600151886020015161289d565b60208801529350600084600381111561259157fe5b146125ad5750600b97506000965086955061269f945050505050565b8b6001600160a01b0316816001600160a01b03161415612651576125db8661012001518c886020015161289d565b6020880152935060008460038111156125f057fe5b1461260c5750600b97506000965086955061269f945050505050565b6126208661010001518b886020015161289d565b60208801529350600084600381111561263557fe5b146126515750600b97506000965086955061269f945050505050565b5060010161230a565b5060208401518451111561268157505050602081015190516000945003915082905061269f565b505081516020909201516000955085945091909103915061269f9050565b9450945094915050565b60008060006126bc846000806000612284565b9250925092509193909250565b60008060006126d6612b8a565b6126e086866128ea565b909250905060008260038111156126f357fe5b146127045750915060009050612716565b600061270f82612952565b9350935050505b9250929050565b6001600160a01b03831660009081526009602052604081205460ff16612744576009610fd1565b6001600160a01b038085166000908152600960209081526040808320938716835260029093019052205460ff1661277c576000610fd1565b600080611c5e8587866000612284565b6000612796612b8a565b6127bc604051806020016040528086815250604051806020016040528086815250612961565b915091509250929050565b60006127d1612b8a565b835183516127bc9190612a4a565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa084601181111561280e57fe5b84601381111561281a57fe5b604080519283526020830191909152818101859052519081900360600190a1836011811115610fdb57fe5b600061284f612b8a565b6000612859612b8a565b6128638787612961565b9092509050600082600381111561287657fe5b146128855790925090506119b8565b61288f8186612961565b935093505050935093915050565b60008060006128aa612b8a565b6128b487876128ea565b909250905060008260038111156128c757fe5b146128d857509150600090506119b8565b61288f6128e482612952565b86612afa565b60006128f4612b8a565b600080612905866000015186612b20565b9092509050600082600381111561291857fe5b1461293757506040805160208101909152600081529092509050612716565b60408051602081019091529081526000969095509350505050565b51670de0b6b3a7640000900490565b600061296b612b8a565b60008061298086600001518660000151612b20565b9092509050600082600381111561299357fe5b146129b257506040805160208101909152600081529092509050612716565b6000806129c76706f05b59d3b2000084612afa565b909250905060008260038111156129da57fe5b146129fc57506040805160208101909152600081529094509250612716915050565b600080612a1183670de0b6b3a7640000612b5f565b90925090506000826003811115612a2457fe5b14612a2b57fe5b604080516020810190915290815260009a909950975050505050505050565b6000612a54612b8a565b600080612a6986670de0b6b3a7640000612b20565b90925090506000826003811115612a7c57fe5b14612a9b57506040805160208101909152600081529092509050612716565b600080612aa88388612b5f565b90925090506000826003811115612abb57fe5b14612add57506040805160208101909152600081529094509250612716915050565b604080516020810190915290815260009890975095505050505050565b600080838301848110612b1257600092509050612716565b506002915060009050612716565b60008083612b3357506000905080612716565b83830283858281612b4057fe5b0414612b5457506002915060009050612716565b600092509050612716565b60008082612b735750600190506000612716565b6000838581612b7e57fe5b04915091509250929050565b6040518060200160405280600081525090565b8154818355818111156111aa576000838152602090206111aa918101908301612c2b565b604051806101400160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001612bff612b8a565b8152602001612c0c612b8a565b8152602001612c19612b8a565b8152602001612c26612b8a565b905290565b61220c91905b80821115612c455760008155600101612c31565b509056fe657869744d61726b65743a206765744163636f756e74536e617073686f74206661696c65646f6e6c7920756e6974726f6c6c65722061646d696e2063616e206368616e676520627261696e73a265627a7a72315820805a363f94f2b32bde513ee9a4604dbc1fdb335507a4c5aa36cf722a6a8d6f0864736f6c63430005100032", + "metadata": "{\"compiler\":{\"version\":\"0.5.16+commit.9c3226ce\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketEntered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketExited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"MarketListed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCloseFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCloseFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCollateralFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCollateralFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldLiquidationIncentiveMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"NewLiquidationIncentive\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMaxAssets\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMaxAssets\",\"type\":\"uint256\"}],\"name\":\"NewMaxAssets\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"oldPriceOracle\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"newPriceOracle\",\"type\":\"address\"}],\"name\":\"NewPriceOracle\",\"type\":\"event\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract Unitroller\",\"name\":\"unitroller\",\"type\":\"address\"},{\"internalType\":\"contract PriceOracle\",\"name\":\"_oracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_closeFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_maxAssets\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"reinitializing\",\"type\":\"bool\"}],\"name\":\"_become\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCloseFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCollateralFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"_setLiquidationIncentive\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newMaxAssets\",\"type\":\"uint256\"}],\"name\":\"_setMaxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"newOracle\",\"type\":\"address\"}],\"name\":\"_setPriceOracle\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"_supportMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"checkMembership\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"enterMarkets\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenAddress\",\"type\":\"address\"}],\"name\":\"exitMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAssetsIn\",\"outputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"isComptroller\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateCalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"liquidationIncentiveMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"markets\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"mintAmount\",\"type\":\"uint256\"}],\"name\":\"mintAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"mintAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"mintTokens\",\"type\":\"uint256\"}],\"name\":\"mintVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"repayBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowerIndex\",\"type\":\"uint256\"}],\"name\":\"repayBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Compound\",\"details\":\"This was the first version of the Comptroller brains. We keep it so our tests can continue to do the real-life behavior of upgrading from this logic forward.\",\"methods\":{\"_setCloseFactor(uint256)\":{\"details\":\"Admin function to set closeFactor\",\"params\":{\"newCloseFactorMantissa\":\"New close factor, scaled by 1e18\"},\"return\":\"uint 0=success, otherwise a failure. (See ErrorReporter for details)\"},\"_setCollateralFactor(address,uint256)\":{\"details\":\"Admin function to set per-market collateralFactor\",\"params\":{\"cToken\":\"The market to set the factor on\",\"newCollateralFactorMantissa\":\"The new collateral factor, scaled by 1e18\"},\"return\":\"uint 0=success, otherwise a failure. (See ErrorReporter for details)\"},\"_setLiquidationIncentive(uint256)\":{\"details\":\"Admin function to set liquidationIncentive\",\"params\":{\"newLiquidationIncentiveMantissa\":\"New liquidationIncentive scaled by 1e18\"},\"return\":\"uint 0=success, otherwise a failure. (See ErrorReporter for details)\"},\"_setMaxAssets(uint256)\":{\"details\":\"Admin function to set maxAssets\",\"params\":{\"newMaxAssets\":\"New max assets\"},\"return\":\"uint 0=success, otherwise a failure. (See ErrorReporter for details)\"},\"_setPriceOracle(address)\":{\"details\":\"Admin function to set a new price oracle\",\"return\":\"uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\"},\"_supportMarket(address)\":{\"details\":\"Admin function to set isListed and add support for the market\",\"params\":{\"cToken\":\"The address of the market (token) to list\"},\"return\":\"uint 0=success, otherwise a failure. (See enum Error for details)\"},\"borrowAllowed(address,address,uint256)\":{\"params\":{\"borrowAmount\":\"The amount of underlying the account would borrow\",\"borrower\":\"The account which would borrow the asset\",\"cToken\":\"The market to verify the borrow against\"},\"return\":\"0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"borrowVerify(address,address,uint256)\":{\"params\":{\"borrowAmount\":\"The amount of the underlying asset requested to borrow\",\"borrower\":\"The address borrowing the underlying\",\"cToken\":\"Asset whose underlying is being borrowed\"}},\"checkMembership(address,address)\":{\"params\":{\"account\":\"The address of the account to check\",\"cToken\":\"The cToken to check\"},\"return\":\"True if the account is in the asset, otherwise false.\"},\"enterMarkets(address[])\":{\"params\":{\"cTokens\":\"The list of addresses of the cToken markets to be enabled\"},\"return\":\"Success indicator for whether each corresponding market was entered\"},\"exitMarket(address)\":{\"details\":\"Sender must not have an outstanding borrow balance in the asset, or be providing neccessary collateral for an outstanding borrow.\",\"params\":{\"cTokenAddress\":\"The address of the asset to be removed\"},\"return\":\"Whether or not the account successfully exited the market\"},\"getAccountLiquidity(address)\":{\"return\":\"(possible error code (semi-opaque), account liquidity in excess of collateral requirements, account shortfall below collateral requirements)\"},\"getAssetsIn(address)\":{\"params\":{\"account\":\"The address of the account to pull assets for\"},\"return\":\"A dynamic list with the assets the account has entered\"},\"liquidateBorrowAllowed(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"repayAmount\":\"The amount of underlying being repaid\"}},\"liquidateBorrowVerify(address,address,address,address,uint256,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"repayAmount\":\"The amount of underlying being repaid\"}},\"liquidateCalculateSeizeTokens(address,address,uint256)\":{\"details\":\"Used in liquidation (called in cToken.liquidateBorrowFresh)\",\"params\":{\"cTokenBorrowed\":\"The address of the borrowed cToken\",\"cTokenCollateral\":\"The address of the collateral cToken\",\"repayAmount\":\"The amount of cTokenBorrowed underlying to convert into cTokenCollateral tokens\"},\"return\":\"(errorCode, number of cTokenCollateral tokens to be seized in a liquidation)\"},\"mintAllowed(address,address,uint256)\":{\"params\":{\"cToken\":\"The market to verify the mint against\",\"mintAmount\":\"The amount of underlying being supplied to the market in exchange for tokens\",\"minter\":\"The account which would get the minted tokens\"},\"return\":\"0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"mintVerify(address,address,uint256,uint256)\":{\"params\":{\"cToken\":\"Asset being minted\",\"mintAmount\":\"The amount of the underlying asset being minted\",\"mintTokens\":\"The number of tokens being minted\",\"minter\":\"The address minting the tokens\"}},\"redeemAllowed(address,address,uint256)\":{\"params\":{\"cToken\":\"The market to verify the redeem against\",\"redeemTokens\":\"The number of cTokens to exchange for the underlying asset in the market\",\"redeemer\":\"The account which would redeem the tokens\"},\"return\":\"0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"redeemVerify(address,address,uint256,uint256)\":{\"params\":{\"cToken\":\"Asset being redeemed\",\"redeemAmount\":\"The amount of the underlying asset being redeemed\",\"redeemTokens\":\"The number of tokens being redeemed\",\"redeemer\":\"The address redeeming the tokens\"}},\"repayBorrowAllowed(address,address,address,uint256)\":{\"params\":{\"borrower\":\"The account which would borrowed the asset\",\"cToken\":\"The market to verify the repay against\",\"payer\":\"The account which would repay the asset\",\"repayAmount\":\"The amount of the underlying asset the account would repay\"},\"return\":\"0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"repayBorrowVerify(address,address,address,uint256,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"cToken\":\"Asset being repaid\",\"payer\":\"The address repaying the borrow\",\"repayAmount\":\"The amount of underlying being repaid\"}},\"seizeAllowed(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"seizeTokens\":\"The number of collateral tokens to seize\"}},\"seizeVerify(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"seizeTokens\":\"The number of collateral tokens to seize\"}},\"transferAllowed(address,address,address,uint256)\":{\"params\":{\"cToken\":\"The market to verify the transfer against\",\"dst\":\"The account which receives the tokens\",\"src\":\"The account which sources the tokens\",\"transferTokens\":\"The number of cTokens to transfer\"},\"return\":\"0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"transferVerify(address,address,address,uint256)\":{\"params\":{\"cToken\":\"Asset being transferred\",\"dst\":\"The account which receives the tokens\",\"src\":\"The account which sources the tokens\",\"transferTokens\":\"The number of cTokens to transfer\"}}},\"title\":\"Compound's Comptroller Contract\"},\"userdoc\":{\"methods\":{\"_setCloseFactor(uint256)\":{\"notice\":\"Sets the closeFactor used when liquidating borrows\"},\"_setCollateralFactor(address,uint256)\":{\"notice\":\"Sets the collateralFactor for a market\"},\"_setLiquidationIncentive(uint256)\":{\"notice\":\"Sets liquidationIncentive\"},\"_setMaxAssets(uint256)\":{\"notice\":\"Sets maxAssets which controls how many markets can be entered\"},\"_setPriceOracle(address)\":{\"notice\":\"Sets a new price oracle for the comptroller\"},\"_supportMarket(address)\":{\"notice\":\"Add the market to the markets mapping and set it as listed\"},\"borrowAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to borrow the underlying asset of the given market\"},\"borrowVerify(address,address,uint256)\":{\"notice\":\"Validates borrow and reverts on rejection. May emit logs.\"},\"checkMembership(address,address)\":{\"notice\":\"Returns whether the given account is entered in the given asset\"},\"enterMarkets(address[])\":{\"notice\":\"Add assets to be included in account liquidity calculation\"},\"exitMarket(address)\":{\"notice\":\"Removes asset from sender's account liquidity calculation\"},\"getAccountLiquidity(address)\":{\"notice\":\"Determine the current account liquidity wrt collateral requirements\"},\"getAssetsIn(address)\":{\"notice\":\"Returns the assets an account has entered\"},\"liquidateBorrowAllowed(address,address,address,address,uint256)\":{\"notice\":\"Checks if the liquidation should be allowed to occur\"},\"liquidateBorrowVerify(address,address,address,address,uint256,uint256)\":{\"notice\":\"Validates liquidateBorrow and reverts on rejection. May emit logs.\"},\"liquidateCalculateSeizeTokens(address,address,uint256)\":{\"notice\":\"Calculate number of tokens of collateral asset to seize given an underlying amount\"},\"mintAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to mint tokens in the given market\"},\"mintVerify(address,address,uint256,uint256)\":{\"notice\":\"Validates mint and reverts on rejection. May emit logs.\"},\"redeemAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to redeem tokens in the given market\"},\"redeemVerify(address,address,uint256,uint256)\":{\"notice\":\"Validates redeem and reverts on rejection. May emit logs.\"},\"repayBorrowAllowed(address,address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to repay a borrow in the given market\"},\"repayBorrowVerify(address,address,address,uint256,uint256)\":{\"notice\":\"Validates repayBorrow and reverts on rejection. May emit logs.\"},\"seizeAllowed(address,address,address,address,uint256)\":{\"notice\":\"Checks if the seizing of assets should be allowed to occur\"},\"seizeVerify(address,address,address,address,uint256)\":{\"notice\":\"Validates seize and reverts on rejection. May emit logs.\"},\"transferAllowed(address,address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to transfer tokens in the given market\"},\"transferVerify(address,address,address,uint256)\":{\"notice\":\"Validates transfer and reverts on rejection. May emit logs.\"}}}},\"settings\":{\"compilationTarget\":{\"contracts/ComptrollerG1.sol\":\"ComptrollerG1\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/CToken.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./CTokenInterfaces.sol\\\";\\nimport \\\"./ErrorReporter.sol\\\";\\nimport \\\"./Exponential.sol\\\";\\nimport \\\"./EIP20Interface.sol\\\";\\nimport \\\"./InterestRateModel.sol\\\";\\n\\n/**\\n * @title Compound's CToken Contract\\n * @notice Abstract base for CTokens\\n * @author Compound\\n */\\ncontract CToken is CTokenInterface, Exponential, TokenErrorReporter {\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_) public {\\n require(msg.sender == admin, \\\"only admin may initialize the market\\\");\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = getBlockNumber();\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Transfer `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = uint(-1);\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srcTokensNew;\\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, srcTokensNew) = 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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srcTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != uint(-1)) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n // unused function\\n // comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transfer(address dst, uint256 amount) external nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferFrom(address src, address dst, uint256 amount) external nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (-1 means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool) {\\n address src = msg.sender;\\n transferAllowances[src][spender] = amount;\\n emit Approval(src, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (-1 means infinite)\\n */\\n function allowance(address owner, address spender) external view returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external returns (uint) {\\n Exp memory exchangeRate = Exp({mantissa: exchangeRateCurrent()});\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n require(mErr == MathError.NO_ERROR, \\\"balance could not be calculated\\\");\\n return balance;\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view returns (uint, uint, uint, uint) {\\n uint cTokenBalance = accountTokens[account];\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), cTokenBalance, borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @dev Function to simply retrieve block number\\n * This exists mainly for inheriting test contracts to stub this result.\\n */\\n function getBlockNumber() internal view returns (uint) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this cToken\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view returns (uint) {\\n return interestRateModel.getBorrowRate(getCashPrior(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this cToken\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view returns (uint) {\\n return interestRateModel.getSupplyRate(getCashPrior(), totalBorrows, totalReserves, reserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n require(err == MathError.NO_ERROR, \\\"borrowBalanceStored: borrowBalanceStoredInternal failed\\\");\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return (error code, the calculated balance or 0 if error code is non-zero)\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the CToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n require(err == MathError.NO_ERROR, \\\"exchangeRateStored: exchangeRateStoredInternal failed\\\");\\n return result;\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the CToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return (error code, calculated exchange rate scaled by 1e18)\\n */\\n function exchangeRateStoredInternal() internal view returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows - totalReserves) / totalSupply\\n */\\n uint totalCash = getCashPrior();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Get cash balance of this cToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage.\\n */\\n function accrueInterest() public returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = getBlockNumber();\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = getCashPrior();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n require(mathErr == MathError.NO_ERROR, \\\"could not calculate block delta\\\");\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({mantissa: borrowRateMantissa}), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(Exp({mantissa: reserveFactorMantissa}), interestAccumulated, reservesPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives cTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n struct MintLocalVars {\\n Error err;\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives cTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, 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's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the cToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of cTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.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 cTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED\\\");\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\\");\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender redeems cTokens in exchange for the underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemTokens The number of cTokens to redeem into underlying\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemInternal(uint redeemTokens) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(msg.sender, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems cTokens in exchange for a specified amount of underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemAmount The amount of underlying to receive from redeeming cTokens\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemUnderlyingInternal(uint redeemAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(msg.sender, 0, redeemAmount);\\n }\\n\\n struct RedeemLocalVars {\\n Error err;\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n /**\\n * @notice User redeems cTokens in exchange for the underlying asset\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param redeemTokensIn The number of cTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming cTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemFresh(address payable redeemer, uint redeemTokensIn, uint redeemAmountIn) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr));\\n }\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(Exp({mantissa: vars.exchangeRateMantissa}), redeemTokensIn);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(redeemAmountIn, Exp({mantissa: vars.exchangeRateMantissa}));\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REDEEM_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDEEM_FRESHNESS_CHECK);\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDEEM_TRANSFER_OUT_NOT_POSSIBLE);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We invoke doTransferOut for the redeemer and the redeemAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(redeemer, vars.redeemAmount);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n /* We call the defense hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender borrows assets from the protocol to their own address\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function borrowInternal(uint borrowAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(msg.sender, borrowAmount);\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n /**\\n * @notice Users borrow assets from the protocol to their own address\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function borrowFresh(address payable borrower, uint borrowAmount) internal returns (uint) {\\n /* Fail if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.BORROW_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.BORROW_FRESHNESS_CHECK);\\n }\\n\\n /* Fail gracefully if protocol has insufficient underlying cash */\\n if (getCashPrior() < borrowAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.BORROW_CASH_NOT_AVAILABLE);\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We invoke doTransferOut for the borrower and the borrowAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(borrower, borrowAmount);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to borrower\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer the account paying off the borrow\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount the amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED\\\");\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED\\\");\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this cToken to be liquidated\\n * @param cTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) 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 = cTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, cTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this cToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param cTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowFresh(address liquidator, address borrower, uint repayAmount, CTokenInterface cTokenCollateral) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(address(this), address(cTokenCollateral), liquidator, borrower, repayAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify cTokenCollateral market's block number equals current block number */\\n if (cTokenCollateral.accrualBlockNumber() != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = -1 */\\n if (repayAmount == uint(-1)) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & 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(cTokenCollateral), actualRepayAmount);\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(cTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(cTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = cTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(cTokenCollateral), seizeTokens);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.liquidateBorrowVerify(address(this), address(cTokenCollateral), liquidator, borrower, actualRepayAmount, seizeTokens);\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another cToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed cToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of cTokens to seize\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function seize(address liquidator, address borrower, uint seizeTokens) external nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n struct SeizeInternalLocalVars {\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n uint liquidatorSeizeTokens;\\n uint protocolSeizeTokens;\\n uint protocolSeizeAmount;\\n uint exchangeRateMantissa;\\n uint totalReservesNew;\\n uint totalSupplyNew;\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another CToken.\\n * Its absolutely critical to use msg.sender as the seizer cToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed cToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of cTokens to seize\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function seizeInternal(address seizerToken, address liquidator, address borrower, uint seizeTokens) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n SeizeInternalLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (vars.mathErr, vars.borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(vars.mathErr));\\n }\\n\\n vars.protocolSeizeTokens = mul_(seizeTokens, Exp({mantissa: protocolSeizeShareMantissa}));\\n vars.liquidatorSeizeTokens = sub_(seizeTokens, vars.protocolSeizeTokens);\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n require(vars.mathErr == MathError.NO_ERROR, \\\"exchange rate math error\\\");\\n\\n vars.protocolSeizeAmount = mul_ScalarTruncate(Exp({mantissa: vars.exchangeRateMantissa}), vars.protocolSeizeTokens);\\n\\n vars.totalReservesNew = add_(totalReserves, vars.protocolSeizeAmount);\\n vars.totalSupplyNew = sub_(totalSupply, vars.protocolSeizeTokens);\\n\\n (vars.mathErr, vars.liquidatorTokensNew) = addUInt(accountTokens[liquidator], vars.liquidatorSeizeTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(vars.mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n totalReserves = vars.totalReservesNew;\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[borrower] = vars.borrowerTokensNew;\\n accountTokens[liquidator] = vars.liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, vars.liquidatorSeizeTokens);\\n emit Transfer(borrower, address(this), vars.protocolSeizeTokens);\\n emit ReservesAdded(address(this), vars.protocolSeizeAmount, vars.totalReservesNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n\\n /*** Admin Functions ***/\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPendingAdmin(address payable newPendingAdmin) external returns (uint) {\\n // Check caller = admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\\n }\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptAdmin() external returns (uint) {\\n // Check caller is pendingAdmin and pendingAdmin \\u2260 address(0)\\n if (msg.sender != pendingAdmin || msg.sender == address(0)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = address(0);\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setComptroller(ComptrollerInterface newComptroller) public returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_COMPTROLLER_OWNER_CHECK);\\n }\\n\\n ComptrollerInterface oldComptroller = comptroller;\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(oldComptroller, newComptroller);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh\\n * @dev Admin function to accrue interest and set a new reserve factor\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setReserveFactor(uint newReserveFactorMantissa) external nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\\n * @dev Admin function to set a new reserve factor\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_RESERVE_FACTOR_ADMIN_CHECK);\\n }\\n\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring from msg.sender\\n * @param addAmount Amount of addition to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to admin\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _reduceReserves(uint reduceAmount) external nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to admin\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _reduceReservesFresh(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's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n totalReservesNew = totalReserves - reduceAmount;\\n // We checked reduceAmount <= totalReserves above, so this should never revert.\\n require(totalReservesNew <= 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't be sure if side effects occurred.\\n doTransferOut(admin, reduceAmount);\\n\\n emit ReservesReduced(admin, reduceAmount, totalReservesNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Admin function to accrue interest and update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel);\\n }\\n\\n /**\\n * @notice updates the interest rate model (*requires fresh interest accrual)\\n * @dev Admin function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal returns (uint) {\\n\\n // Used to store old model for use in the event that is emitted on success\\n InterestRateModel oldInterestRateModel;\\n\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_INTEREST_RATE_MODEL_OWNER_CHECK);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Track the market's current interest rate model\\n oldInterestRateModel = interestRateModel;\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view returns (uint);\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure tather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal;\\n\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n}\\n\",\"keccak256\":\"0x436ec2e309682995f8a82dfdd9e8f75928599c10a9a680dddbee6c275014008d\"},\"contracts/CTokenInterfaces.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./InterestRateModel.sol\\\";\\nimport \\\"./EIP20NonStandardInterface.sol\\\";\\n\\ncontract CTokenStorage {\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-cToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModel public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first CTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping (address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping (address => mapping (address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Share of seized collateral that is added to reserves\\n */\\n uint public constant protocolSeizeShareMantissa = 2.8e16; //2.8%\\n\\n}\\n\\ncontract CTokenInterface is CTokenStorage {\\n /**\\n * @notice Indicator that this is a CToken contract (for inspection)\\n */\\n bool public constant isCToken = true;\\n\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(address liquidator, address borrower, uint repayAmount, address cTokenCollateral, uint seizeTokens);\\n\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin is updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(InterestRateModel oldInterestRateModel, InterestRateModel newInterestRateModel);\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address admin, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Failure event\\n */\\n event Failure(uint error, uint info, uint detail);\\n\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external returns (bool);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function approve(address spender, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function balanceOfUnderlying(address owner) external returns (uint);\\n function getAccountSnapshot(address account) external view returns (uint, uint, uint, uint);\\n function borrowRatePerBlock() external view returns (uint);\\n function supplyRatePerBlock() external view returns (uint);\\n function totalBorrowsCurrent() external returns (uint);\\n function borrowBalanceCurrent(address account) external returns (uint);\\n function borrowBalanceStored(address account) public view returns (uint);\\n function exchangeRateCurrent() public returns (uint);\\n function exchangeRateStored() public view returns (uint);\\n function getCash() external view returns (uint);\\n function accrueInterest() public returns (uint);\\n function seize(address liquidator, address borrower, uint seizeTokens) external returns (uint);\\n\\n\\n /*** Admin Functions ***/\\n\\n function _setPendingAdmin(address payable newPendingAdmin) external returns (uint);\\n function _acceptAdmin() external returns (uint);\\n function _setComptroller(ComptrollerInterface newComptroller) public returns (uint);\\n function _setReserveFactor(uint newReserveFactorMantissa) external returns (uint);\\n function _reduceReserves(uint reduceAmount) external returns (uint);\\n function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint);\\n}\\n\\ncontract CErc20Storage {\\n /**\\n * @notice Underlying asset for this CToken\\n */\\n address public underlying;\\n}\\n\\ncontract CErc20Interface is CErc20Storage {\\n\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n function redeem(uint redeemTokens) external returns (uint);\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n function borrow(uint borrowAmount) external returns (uint);\\n function repayBorrow(uint repayAmount) external returns (uint);\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n function liquidateBorrow(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) external returns (uint);\\n function sweepToken(EIP20NonStandardInterface token) external;\\n\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ncontract CDelegationStorage {\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n}\\n\\ncontract CDelegatorInterface is CDelegationStorage {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(address implementation_, bool allowResign, bytes memory becomeImplementationData) public;\\n}\\n\\ncontract CDelegateInterface is CDelegationStorage {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) public;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() public;\\n}\\n\",\"keccak256\":\"0x963bbf60b4c0b76900b3fcb2db8c8be634934b37b4113f1055e57a308197d21a\"},\"contracts/CarefulMath.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Careful Math\\n * @author Compound\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c = a * b;\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n return (MathError.NO_ERROR, a - b);\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c = a + b;\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\",\"keccak256\":\"0x0647348f27e41d22555d99eebd217dee02a4d737df6accd7cce5347a7487c7de\"},\"contracts/ComptrollerG1.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.sol\\\";\\nimport \\\"./ErrorReporter.sol\\\";\\nimport \\\"./Exponential.sol\\\";\\nimport \\\"./PriceOracle.sol\\\";\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./ComptrollerStorage.sol\\\";\\nimport \\\"./Unitroller.sol\\\";\\n\\n/**\\n * @title Compound's Comptroller Contract\\n * @author Compound\\n * @dev This was the first version of the Comptroller brains.\\n * We keep it so our tests can continue to do the real-life behavior of upgrading from this logic forward.\\n */\\ncontract ComptrollerG1 is ComptrollerV1Storage, ComptrollerInterface, ComptrollerErrorReporter, Exponential {\\n struct Market {\\n /**\\n * @notice Whether or not this market is listed\\n */\\n bool isListed;\\n\\n /**\\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\\n * For instance, 0.9 to allow borrowing 90% of collateral value.\\n * Must be between 0 and 1, and stored as a mantissa.\\n */\\n uint collateralFactorMantissa;\\n\\n /**\\n * @notice Per-market mapping of \\\"accounts in this asset\\\"\\n */\\n mapping(address => bool) accountMembership;\\n }\\n\\n /**\\n * @notice Official mapping of cTokens -> Market metadata\\n * @dev Used e.g. to determine if a market is supported\\n */\\n mapping(address => Market) public markets;\\n\\n /**\\n * @notice Emitted when an admin supports a market\\n */\\n event MarketListed(CToken cToken);\\n\\n /**\\n * @notice Emitted when an account enters a market\\n */\\n event MarketEntered(CToken cToken, address account);\\n\\n /**\\n * @notice Emitted when an account exits a market\\n */\\n event MarketExited(CToken cToken, address account);\\n\\n /**\\n * @notice Emitted when close factor is changed by admin\\n */\\n event NewCloseFactor(uint oldCloseFactorMantissa, uint newCloseFactorMantissa);\\n\\n /**\\n * @notice Emitted when a collateral factor is changed by admin\\n */\\n event NewCollateralFactor(CToken cToken, uint oldCollateralFactorMantissa, uint newCollateralFactorMantissa);\\n\\n /**\\n * @notice Emitted when liquidation incentive is changed by admin\\n */\\n event NewLiquidationIncentive(uint oldLiquidationIncentiveMantissa, uint newLiquidationIncentiveMantissa);\\n\\n /**\\n * @notice Emitted when maxAssets is changed by admin\\n */\\n event NewMaxAssets(uint oldMaxAssets, uint newMaxAssets);\\n\\n /**\\n * @notice Emitted when price oracle is changed\\n */\\n event NewPriceOracle(PriceOracle oldPriceOracle, PriceOracle newPriceOracle);\\n\\n // closeFactorMantissa must be strictly greater than this value\\n uint constant closeFactorMinMantissa = 5e16; // 0.05\\n\\n // closeFactorMantissa must not exceed this value\\n uint constant closeFactorMaxMantissa = 9e17; // 0.9\\n\\n // No collateralFactorMantissa may exceed this value\\n uint constant collateralFactorMaxMantissa = 9e17; // 0.9\\n\\n // liquidationIncentiveMantissa must be no less than this value\\n uint constant liquidationIncentiveMinMantissa = mantissaOne;\\n\\n // liquidationIncentiveMantissa must be no greater than this value\\n uint constant liquidationIncentiveMaxMantissa = 15e17; // 1.5\\n\\n constructor() public {\\n admin = msg.sender;\\n }\\n\\n /*** Assets You Are In ***/\\n\\n /**\\n * @notice Returns the assets an account has entered\\n * @param account The address of the account to pull assets for\\n * @return A dynamic list with the assets the account has entered\\n */\\n function getAssetsIn(address account) external view returns (CToken[] memory) {\\n CToken[] memory assetsIn = accountAssets[account];\\n\\n return assetsIn;\\n }\\n\\n /**\\n * @notice Returns whether the given account is entered in the given asset\\n * @param account The address of the account to check\\n * @param cToken The cToken to check\\n * @return True if the account is in the asset, otherwise false.\\n */\\n function checkMembership(address account, CToken cToken) external view returns (bool) {\\n return markets[address(cToken)].accountMembership[account];\\n }\\n\\n /**\\n * @notice Add assets to be included in account liquidity calculation\\n * @param cTokens The list of addresses of the cToken markets to be enabled\\n * @return Success indicator for whether each corresponding market was entered\\n */\\n function enterMarkets(address[] memory cTokens) public returns (uint[] memory) {\\n uint len = cTokens.length;\\n\\n uint[] memory results = new uint[](len);\\n for (uint i = 0; i < len; i++) {\\n CToken cToken = CToken(cTokens[i]);\\n Market storage marketToJoin = markets[address(cToken)];\\n\\n if (!marketToJoin.isListed) {\\n // if market is not listed, cannot join move along\\n results[i] = uint(Error.MARKET_NOT_LISTED);\\n continue;\\n }\\n\\n if (marketToJoin.accountMembership[msg.sender] == true) {\\n // if already joined, move along\\n results[i] = uint(Error.NO_ERROR);\\n continue;\\n }\\n\\n if (accountAssets[msg.sender].length >= maxAssets) {\\n // if no space, cannot join, move along\\n results[i] = uint(Error.TOO_MANY_ASSETS);\\n continue;\\n }\\n\\n // survived the gauntlet, add to list\\n // NOTE: we store these somewhat redundantly as a significant optimization\\n // this avoids having to iterate through the list for the most common use cases\\n // that is, only when we need to perform liquidity checks\\n // and not whenever we want to check if an account is in a particular market\\n marketToJoin.accountMembership[msg.sender] = true;\\n accountAssets[msg.sender].push(cToken);\\n\\n emit MarketEntered(cToken, msg.sender);\\n\\n results[i] = uint(Error.NO_ERROR);\\n }\\n\\n return results;\\n }\\n\\n /**\\n * @notice Removes asset from sender's account liquidity calculation\\n * @dev Sender must not have an outstanding borrow balance in the asset,\\n * or be providing neccessary collateral for an outstanding borrow.\\n * @param cTokenAddress The address of the asset to be removed\\n * @return Whether or not the account successfully exited the market\\n */\\n function exitMarket(address cTokenAddress) external returns (uint) {\\n CToken cToken = CToken(cTokenAddress);\\n /* Get sender tokensHeld and amountOwed underlying from the cToken */\\n (uint oErr, uint tokensHeld, uint amountOwed, ) = cToken.getAccountSnapshot(msg.sender);\\n require(oErr == 0, \\\"exitMarket: getAccountSnapshot failed\\\"); // semi-opaque error code\\n\\n /* Fail if the sender has a borrow balance */\\n if (amountOwed != 0) {\\n return fail(Error.NONZERO_BORROW_BALANCE, FailureInfo.EXIT_MARKET_BALANCE_OWED);\\n }\\n\\n /* Fail if the sender is not permitted to redeem all of their tokens */\\n uint allowed = redeemAllowedInternal(cTokenAddress, msg.sender, tokensHeld);\\n if (allowed != 0) {\\n return failOpaque(Error.REJECTION, FailureInfo.EXIT_MARKET_REJECTION, allowed);\\n }\\n\\n Market storage marketToExit = markets[address(cToken)];\\n\\n /* Return true if the sender is not already \\u2018in\\u2019 the market */\\n if (!marketToExit.accountMembership[msg.sender]) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Set cToken account membership to false */\\n delete marketToExit.accountMembership[msg.sender];\\n\\n /* Delete cToken from the account\\u2019s list of assets */\\n // load into memory for faster iteration\\n CToken[] memory userAssetList = accountAssets[msg.sender];\\n uint len = userAssetList.length;\\n uint assetIndex = len;\\n for (uint i = 0; i < len; i++) {\\n if (userAssetList[i] == cToken) {\\n assetIndex = i;\\n break;\\n }\\n }\\n\\n // We *must* have found the asset in the list or our redundant data structure is broken\\n assert(assetIndex < len);\\n\\n // copy last item in list to location of item to be removed, reduce length by 1\\n CToken[] storage storedList = accountAssets[msg.sender];\\n storedList[assetIndex] = storedList[storedList.length - 1];\\n storedList.length--;\\n\\n emit MarketExited(cToken, 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 cToken The market to verify the mint against\\n * @param minter The account which would get the minted tokens\\n * @param mintAmount The amount of underlying being supplied to the market in exchange for tokens\\n * @return 0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function mintAllowed(address cToken, address minter, uint mintAmount) external returns (uint) {\\n minter; // currently unused\\n mintAmount; // currently unused\\n\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n // *may include Policy Hook-type checks\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates mint and reverts on rejection. May emit logs.\\n * @param cToken Asset being minted\\n * @param minter The address minting the tokens\\n * @param mintAmount The amount of the underlying asset being minted\\n * @param mintTokens The number of tokens being minted\\n */\\n function mintVerify(address cToken, address minter, uint mintAmount, uint mintTokens) external {\\n cToken; // currently unused\\n minter; // currently unused\\n mintAmount; // currently unused\\n mintTokens; // currently unused\\n\\n if (false) {\\n maxAssets = maxAssets; // not pure\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to redeem tokens in the given market\\n * @param cToken The market to verify the redeem against\\n * @param redeemer The account which would redeem the tokens\\n * @param redeemTokens The number of cTokens to exchange for the underlying asset in the market\\n * @return 0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function redeemAllowed(address cToken, address redeemer, uint redeemTokens) external returns (uint) {\\n return redeemAllowedInternal(cToken, redeemer, redeemTokens);\\n }\\n\\n function redeemAllowedInternal(address cToken, address redeemer, uint redeemTokens) internal view returns (uint) {\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n // *may include Policy Hook-type checks\\n\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!markets[cToken].accountMembership[redeemer]) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n (Error err, , uint shortfall) = getHypotheticalAccountLiquidityInternal(redeemer, CToken(cToken), redeemTokens, 0);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n if (shortfall > 0) {\\n return uint(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates redeem and reverts on rejection. May emit logs.\\n * @param cToken Asset being redeemed\\n * @param redeemer The address redeeming the tokens\\n * @param redeemAmount The amount of the underlying asset being redeemed\\n * @param redeemTokens The number of tokens being redeemed\\n */\\n function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) external {\\n cToken; // currently unused\\n redeemer; // currently unused\\n redeemAmount; // currently unused\\n redeemTokens; // currently unused\\n\\n // Require tokens is zero or amount is also zero\\n if (redeemTokens == 0 && redeemAmount > 0) {\\n revert(\\\"redeemTokens zero\\\");\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to borrow the underlying asset of the given market\\n * @param cToken The market to verify the borrow against\\n * @param borrower The account which would borrow the asset\\n * @param borrowAmount The amount of underlying the account would borrow\\n * @return 0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function borrowAllowed(address cToken, address borrower, uint borrowAmount) external returns (uint) {\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n // *may include Policy Hook-type checks\\n\\n if (!markets[cToken].accountMembership[borrower]) {\\n return uint(Error.MARKET_NOT_ENTERED);\\n }\\n\\n if (oracle.getUnderlyingPrice(CToken(cToken)) == 0) {\\n return uint(Error.PRICE_ERROR);\\n }\\n\\n (Error err, , uint shortfall) = getHypotheticalAccountLiquidityInternal(borrower, CToken(cToken), 0, borrowAmount);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n if (shortfall > 0) {\\n return uint(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates borrow and reverts on rejection. May emit logs.\\n * @param cToken Asset whose underlying is being borrowed\\n * @param borrower The address borrowing the underlying\\n * @param borrowAmount The amount of the underlying asset requested to borrow\\n */\\n function borrowVerify(address cToken, address borrower, uint borrowAmount) external {\\n cToken; // currently unused\\n borrower; // currently unused\\n borrowAmount; // currently unused\\n\\n if (false) {\\n maxAssets = maxAssets; // not pure\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to repay a borrow in the given market\\n * @param cToken The market to verify the repay against\\n * @param payer The account which would repay the asset\\n * @param borrower The account which would borrowed the asset\\n * @param repayAmount The amount of the underlying asset the account would repay\\n * @return 0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function repayBorrowAllowed(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount) external returns (uint) {\\n payer; // currently unused\\n borrower; // currently unused\\n repayAmount; // currently unused\\n\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n // *may include Policy Hook-type checks\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates repayBorrow and reverts on rejection. May emit logs.\\n * @param cToken Asset being repaid\\n * @param payer The address repaying the borrow\\n * @param borrower The address of the borrower\\n * @param repayAmount The amount of underlying being repaid\\n */\\n function repayBorrowVerify(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex) external {\\n cToken; // currently unused\\n payer; // currently unused\\n borrower; // currently unused\\n repayAmount; // currently unused\\n borrowerIndex; // currently unused\\n\\n if (false) {\\n maxAssets = maxAssets; // not pure\\n }\\n }\\n\\n /**\\n * @notice Checks if the liquidation should be allowed to occur\\n * @param cTokenBorrowed Asset which was borrowed by the borrower\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param repayAmount The amount of underlying being repaid\\n */\\n function liquidateBorrowAllowed(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount) external returns (uint) {\\n liquidator; // currently unused\\n borrower; // currently unused\\n repayAmount; // currently unused\\n\\n if (!markets[cTokenBorrowed].isListed || !markets[cTokenCollateral].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n // *may include Policy Hook-type checks\\n\\n /* The borrower must have shortfall in order to be liquidatable */\\n (Error err, , uint shortfall) = getAccountLiquidityInternal(borrower);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n if (shortfall == 0) {\\n return uint(Error.INSUFFICIENT_SHORTFALL);\\n }\\n\\n /* The liquidator may not repay more than what is allowed by the closeFactor */\\n uint borrowBalance = CToken(cTokenBorrowed).borrowBalanceStored(borrower);\\n (MathError mathErr, uint maxClose) = mulScalarTruncate(Exp({mantissa: closeFactorMantissa}), borrowBalance);\\n if (mathErr != MathError.NO_ERROR) {\\n return uint(Error.MATH_ERROR);\\n }\\n if (repayAmount > 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 cTokenBorrowed Asset which was borrowed by the borrower\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param repayAmount The amount of underlying being repaid\\n */\\n function liquidateBorrowVerify(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens) external {\\n cTokenBorrowed; // currently unused\\n cTokenCollateral; // currently unused\\n liquidator; // currently unused\\n borrower; // currently unused\\n repayAmount; // currently unused\\n seizeTokens; // currently unused\\n\\n if (false) {\\n maxAssets = maxAssets; // not pure\\n }\\n }\\n\\n /**\\n * @notice Checks if the seizing of assets should be allowed to occur\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param cTokenBorrowed Asset which was borrowed by the borrower\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param seizeTokens The number of collateral tokens to seize\\n */\\n function seizeAllowed(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external returns (uint) {\\n liquidator; // currently unused\\n borrower; // currently unused\\n seizeTokens; // currently unused\\n\\n if (!markets[cTokenCollateral].isListed || !markets[cTokenBorrowed].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n if (CToken(cTokenCollateral).comptroller() != CToken(cTokenBorrowed).comptroller()) {\\n return uint(Error.COMPTROLLER_MISMATCH);\\n }\\n\\n // *may include Policy Hook-type checks\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates seize and reverts on rejection. May emit logs.\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param cTokenBorrowed Asset which was borrowed by the borrower\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param seizeTokens The number of collateral tokens to seize\\n */\\n function seizeVerify(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external {\\n cTokenCollateral; // currently unused\\n cTokenBorrowed; // currently unused\\n liquidator; // currently unused\\n borrower; // currently unused\\n seizeTokens; // currently unused\\n\\n if (false) {\\n maxAssets = maxAssets; // not pure\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to transfer tokens in the given market\\n * @param cToken The market to verify the transfer against\\n * @param src The account which sources the tokens\\n * @param dst The account which receives the tokens\\n * @param transferTokens The number of cTokens to transfer\\n * @return 0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function transferAllowed(address cToken, address src, address dst, uint transferTokens) external returns (uint) {\\n cToken; // currently unused\\n src; // currently unused\\n dst; // currently unused\\n transferTokens; // currently unused\\n\\n // *may include Policy Hook-type checks\\n\\n // Currently the only consideration is whether or not\\n // the src is allowed to redeem this many tokens\\n return redeemAllowedInternal(cToken, src, transferTokens);\\n }\\n\\n /**\\n * @notice Validates transfer and reverts on rejection. May emit logs.\\n * @param cToken Asset being transferred\\n * @param src The account which sources the tokens\\n * @param dst The account which receives the tokens\\n * @param transferTokens The number of cTokens to transfer\\n */\\n function transferVerify(address cToken, address src, address dst, uint transferTokens) external {\\n cToken; // currently unused\\n src; // currently unused\\n dst; // currently unused\\n transferTokens; // currently unused\\n\\n if (false) {\\n maxAssets = maxAssets; // not pure\\n }\\n }\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n /**\\n * @dev Local vars for avoiding stack-depth limits in calculating account liquidity.\\n * Note that `cTokenBalance` is the number of cTokens the account owns in the market,\\n * whereas `borrowBalance` is the amount of underlying that the account has borrowed.\\n */\\n struct AccountLiquidityLocalVars {\\n uint sumCollateral;\\n uint sumBorrowPlusEffects;\\n uint cTokenBalance;\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n uint oraclePriceMantissa;\\n Exp collateralFactor;\\n Exp exchangeRate;\\n Exp oraclePrice;\\n Exp tokensToEther;\\n }\\n\\n /**\\n * @notice Determine the current account liquidity wrt collateral requirements\\n * @return (possible error code (semi-opaque),\\n account liquidity in excess of collateral requirements,\\n * account shortfall below collateral requirements)\\n */\\n function getAccountLiquidity(address account) public view returns (uint, uint, uint) {\\n (Error err, uint liquidity, uint shortfall) = getHypotheticalAccountLiquidityInternal(account, CToken(0), 0, 0);\\n\\n return (uint(err), liquidity, shortfall);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity wrt collateral requirements\\n * @return (possible error code,\\n account liquidity in excess of collateral requirements,\\n * account shortfall below collateral requirements)\\n */\\n function getAccountLiquidityInternal(address account) internal view returns (Error, uint, uint) {\\n return getHypotheticalAccountLiquidityInternal(account, CToken(0), 0, 0);\\n }\\n\\n /**\\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\\n * @param cTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @dev Note that we calculate the exchangeRateStored for each collateral cToken using stored data,\\n * without calculating accumulated interest.\\n * @return (possible error code,\\n hypothetical account liquidity in excess of collateral requirements,\\n * hypothetical account shortfall below collateral requirements)\\n */\\n function getHypotheticalAccountLiquidityInternal(\\n address account,\\n CToken cTokenModify,\\n uint redeemTokens,\\n uint borrowAmount) internal view returns (Error, uint, uint) {\\n\\n AccountLiquidityLocalVars memory vars; // Holds all our calculation results\\n uint oErr;\\n MathError mErr;\\n\\n // For each asset the account is in\\n CToken[] memory assets = accountAssets[account];\\n for (uint i = 0; i < assets.length; i++) {\\n CToken asset = assets[i];\\n\\n // Read the balances and exchange rate from the cToken\\n (oErr, vars.cTokenBalance, vars.borrowBalance, vars.exchangeRateMantissa) = asset.getAccountSnapshot(account);\\n if (oErr != 0) { // semi-opaque error code, we assume NO_ERROR == 0 is invariant between upgrades\\n return (Error.SNAPSHOT_ERROR, 0, 0);\\n }\\n vars.collateralFactor = Exp({mantissa: markets[address(asset)].collateralFactorMantissa});\\n vars.exchangeRate = Exp({mantissa: vars.exchangeRateMantissa});\\n\\n // Get the normalized price of the asset\\n vars.oraclePriceMantissa = oracle.getUnderlyingPrice(asset);\\n if (vars.oraclePriceMantissa == 0) {\\n return (Error.PRICE_ERROR, 0, 0);\\n }\\n vars.oraclePrice = Exp({mantissa: vars.oraclePriceMantissa});\\n\\n // Pre-compute a conversion factor from tokens -> ether (normalized price value)\\n (mErr, vars.tokensToEther) = mulExp3(vars.collateralFactor, vars.exchangeRate, vars.oraclePrice);\\n if (mErr != MathError.NO_ERROR) {\\n return (Error.MATH_ERROR, 0, 0);\\n }\\n\\n // sumCollateral += tokensToEther * cTokenBalance\\n (mErr, vars.sumCollateral) = mulScalarTruncateAddUInt(vars.tokensToEther, vars.cTokenBalance, 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 cTokenModify\\n if (asset == cTokenModify) {\\n // redeem effect\\n // sumBorrowPlusEffects += tokensToEther * redeemTokens\\n (mErr, vars.sumBorrowPlusEffects) = mulScalarTruncateAddUInt(vars.tokensToEther, redeemTokens, vars.sumBorrowPlusEffects);\\n if (mErr != MathError.NO_ERROR) {\\n return (Error.MATH_ERROR, 0, 0);\\n }\\n\\n // borrow effect\\n // sumBorrowPlusEffects += oraclePrice * borrowAmount\\n (mErr, vars.sumBorrowPlusEffects) = mulScalarTruncateAddUInt(vars.oraclePrice, borrowAmount, vars.sumBorrowPlusEffects);\\n if (mErr != MathError.NO_ERROR) {\\n return (Error.MATH_ERROR, 0, 0);\\n }\\n }\\n }\\n\\n // These are safe, as the underflow condition is checked first\\n if (vars.sumCollateral > vars.sumBorrowPlusEffects) {\\n return (Error.NO_ERROR, vars.sumCollateral - vars.sumBorrowPlusEffects, 0);\\n } else {\\n return (Error.NO_ERROR, 0, vars.sumBorrowPlusEffects - vars.sumCollateral);\\n }\\n }\\n\\n /**\\n * @notice Calculate number of tokens of collateral asset to seize given an underlying amount\\n * @dev Used in liquidation (called in cToken.liquidateBorrowFresh)\\n * @param cTokenBorrowed The address of the borrowed cToken\\n * @param cTokenCollateral The address of the collateral cToken\\n * @param repayAmount The amount of cTokenBorrowed underlying to convert into cTokenCollateral tokens\\n * @return (errorCode, number of cTokenCollateral tokens to be seized in a liquidation)\\n */\\n function liquidateCalculateSeizeTokens(address cTokenBorrowed, address cTokenCollateral, uint repayAmount) external view returns (uint, uint) {\\n /* Read oracle prices for borrowed and collateral markets */\\n uint priceBorrowedMantissa = oracle.getUnderlyingPrice(CToken(cTokenBorrowed));\\n uint priceCollateralMantissa = oracle.getUnderlyingPrice(CToken(cTokenCollateral));\\n if (priceBorrowedMantissa == 0 || priceCollateralMantissa == 0) {\\n return (uint(Error.PRICE_ERROR), 0);\\n }\\n\\n /*\\n * Get the exchange rate and calculate the number of collateral tokens to seize:\\n * seizeAmount = repayAmount * liquidationIncentive * priceBorrowed / priceCollateral\\n * seizeTokens = seizeAmount / exchangeRate\\n * = repayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate)\\n */\\n uint exchangeRateMantissa = CToken(cTokenCollateral).exchangeRateStored(); // Note: reverts on error\\n uint seizeTokens;\\n Exp memory numerator;\\n Exp memory denominator;\\n Exp memory ratio;\\n MathError mathErr;\\n\\n (mathErr, numerator) = mulExp(liquidationIncentiveMantissa, priceBorrowedMantissa);\\n if (mathErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0);\\n }\\n\\n (mathErr, denominator) = mulExp(priceCollateralMantissa, exchangeRateMantissa);\\n if (mathErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0);\\n }\\n\\n (mathErr, ratio) = divExp(numerator, denominator);\\n if (mathErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0);\\n }\\n\\n (mathErr, seizeTokens) = mulScalarTruncate(ratio, repayAmount);\\n if (mathErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0);\\n }\\n\\n return (uint(Error.NO_ERROR), seizeTokens);\\n }\\n\\n /*** Admin Functions ***/\\n\\n /**\\n * @notice Sets a new price oracle for the comptroller\\n * @dev Admin function to set a new price oracle\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPriceOracle(PriceOracle newOracle) public returns (uint) {\\n // Check caller is admin OR currently initialzing as new unitroller implementation\\n if (!adminOrInitializing()) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PRICE_ORACLE_OWNER_CHECK);\\n }\\n\\n // Track the old oracle for the comptroller\\n PriceOracle oldOracle = oracle;\\n\\n // Ensure invoke newOracle.isPriceOracle() returns true\\n // require(newOracle.isPriceOracle(), \\\"oracle method isPriceOracle returned false\\\");\\n\\n // Set comptroller's oracle to newOracle\\n oracle = newOracle;\\n\\n // Emit NewPriceOracle(oldOracle, newOracle)\\n emit NewPriceOracle(oldOracle, newOracle);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets the closeFactor used when liquidating borrows\\n * @dev Admin function to set closeFactor\\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\\n * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function _setCloseFactor(uint newCloseFactorMantissa) external returns (uint256) {\\n // Check caller is admin OR currently initialzing as new unitroller implementation\\n if (!adminOrInitializing()) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_CLOSE_FACTOR_OWNER_CHECK);\\n }\\n\\n Exp memory newCloseFactorExp = Exp({mantissa: newCloseFactorMantissa});\\n Exp memory lowLimit = Exp({mantissa: closeFactorMinMantissa});\\n if (lessThanOrEqualExp(newCloseFactorExp, lowLimit)) {\\n return fail(Error.INVALID_CLOSE_FACTOR, FailureInfo.SET_CLOSE_FACTOR_VALIDATION);\\n }\\n\\n Exp memory highLimit = Exp({mantissa: closeFactorMaxMantissa});\\n if (lessThanExp(highLimit, newCloseFactorExp)) {\\n return fail(Error.INVALID_CLOSE_FACTOR, FailureInfo.SET_CLOSE_FACTOR_VALIDATION);\\n }\\n\\n uint oldCloseFactorMantissa = closeFactorMantissa;\\n closeFactorMantissa = newCloseFactorMantissa;\\n emit NewCloseFactor(oldCloseFactorMantissa, closeFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets the collateralFactor for a market\\n * @dev Admin function to set per-market collateralFactor\\n * @param cToken The market to set the factor on\\n * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18\\n * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function _setCollateralFactor(CToken cToken, uint newCollateralFactorMantissa) external returns (uint256) {\\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(cToken)];\\n if (!market.isListed) {\\n return fail(Error.MARKET_NOT_LISTED, FailureInfo.SET_COLLATERAL_FACTOR_NO_EXISTS);\\n }\\n\\n Exp memory newCollateralFactorExp = Exp({mantissa: newCollateralFactorMantissa});\\n\\n // Check collateral factor <= 0.9\\n Exp memory highLimit = Exp({mantissa: collateralFactorMaxMantissa});\\n if (lessThanExp(highLimit, newCollateralFactorExp)) {\\n return fail(Error.INVALID_COLLATERAL_FACTOR, FailureInfo.SET_COLLATERAL_FACTOR_VALIDATION);\\n }\\n\\n // If collateral factor != 0, fail if price == 0\\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(cToken) == 0) {\\n return fail(Error.PRICE_ERROR, FailureInfo.SET_COLLATERAL_FACTOR_WITHOUT_PRICE);\\n }\\n\\n // Set market's collateral factor to new collateral factor, remember old value\\n uint oldCollateralFactorMantissa = market.collateralFactorMantissa;\\n market.collateralFactorMantissa = newCollateralFactorMantissa;\\n\\n // Emit event with asset, old collateral factor, and new collateral factor\\n emit NewCollateralFactor(cToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets maxAssets which controls how many markets can be entered\\n * @dev Admin function to set maxAssets\\n * @param newMaxAssets New max assets\\n * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function _setMaxAssets(uint newMaxAssets) external returns (uint) {\\n // Check caller is admin OR currently initialzing as new unitroller implementation\\n if (!adminOrInitializing()) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_MAX_ASSETS_OWNER_CHECK);\\n }\\n\\n uint oldMaxAssets = maxAssets;\\n maxAssets = newMaxAssets;\\n emit NewMaxAssets(oldMaxAssets, newMaxAssets);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets liquidationIncentive\\n * @dev Admin function to set liquidationIncentive\\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\\n * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function _setLiquidationIncentive(uint newLiquidationIncentiveMantissa) external returns (uint) {\\n // Check caller is admin OR currently initialzing as new unitroller implementation\\n if (!adminOrInitializing()) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_LIQUIDATION_INCENTIVE_OWNER_CHECK);\\n }\\n\\n // Check de-scaled 1 <= newLiquidationDiscount <= 1.5\\n Exp memory newLiquidationIncentive = Exp({mantissa: newLiquidationIncentiveMantissa});\\n Exp memory minLiquidationIncentive = Exp({mantissa: liquidationIncentiveMinMantissa});\\n if (lessThanExp(newLiquidationIncentive, minLiquidationIncentive)) {\\n return fail(Error.INVALID_LIQUIDATION_INCENTIVE, FailureInfo.SET_LIQUIDATION_INCENTIVE_VALIDATION);\\n }\\n\\n Exp memory maxLiquidationIncentive = Exp({mantissa: liquidationIncentiveMaxMantissa});\\n if (lessThanExp(maxLiquidationIncentive, newLiquidationIncentive)) {\\n return fail(Error.INVALID_LIQUIDATION_INCENTIVE, FailureInfo.SET_LIQUIDATION_INCENTIVE_VALIDATION);\\n }\\n\\n // Save current value for use in log\\n uint oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa;\\n\\n // Set liquidation incentive to new incentive\\n liquidationIncentiveMantissa = newLiquidationIncentiveMantissa;\\n\\n // Emit event with old incentive, new incentive\\n emit NewLiquidationIncentive(oldLiquidationIncentiveMantissa, newLiquidationIncentiveMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Add the market to the markets mapping and set it as listed\\n * @dev Admin function to set isListed and add support for the market\\n * @param cToken The address of the market (token) to list\\n * @return uint 0=success, otherwise a failure. (See enum Error for details)\\n */\\n function _supportMarket(CToken cToken) external returns (uint) {\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SUPPORT_MARKET_OWNER_CHECK);\\n }\\n\\n if (markets[address(cToken)].isListed) {\\n return fail(Error.MARKET_ALREADY_LISTED, FailureInfo.SUPPORT_MARKET_EXISTS);\\n }\\n\\n cToken.isCToken(); // Sanity check to make sure its really a CToken\\n\\n markets[address(cToken)] = Market({isListed: true, collateralFactorMantissa: 0});\\n emit MarketListed(cToken);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n function _become(Unitroller unitroller, PriceOracle _oracle, uint _closeFactorMantissa, uint _maxAssets, bool reinitializing) public {\\n require(msg.sender == unitroller.admin(), \\\"only unitroller admin can change brains\\\");\\n uint changeStatus = unitroller._acceptImplementation();\\n\\n require(changeStatus == 0, \\\"change not authorized\\\");\\n\\n if (!reinitializing) {\\n ComptrollerG1 freshBrainedComptroller = ComptrollerG1(address(unitroller));\\n\\n // Ensure invoke _setPriceOracle() = 0\\n uint err = freshBrainedComptroller._setPriceOracle(_oracle);\\n require (err == uint(Error.NO_ERROR), \\\"set price oracle error\\\");\\n\\n // Ensure invoke _setCloseFactor() = 0\\n err = freshBrainedComptroller._setCloseFactor(_closeFactorMantissa);\\n require (err == uint(Error.NO_ERROR), \\\"set close factor error\\\");\\n\\n // Ensure invoke _setMaxAssets() = 0\\n err = freshBrainedComptroller._setMaxAssets(_maxAssets);\\n require (err == uint(Error.NO_ERROR), \\\"set max asssets error\\\");\\n\\n // Ensure invoke _setLiquidationIncentive(liquidationIncentiveMinMantissa) = 0\\n err = freshBrainedComptroller._setLiquidationIncentive(liquidationIncentiveMinMantissa);\\n require (err == uint(Error.NO_ERROR), \\\"set liquidation incentive error\\\");\\n }\\n }\\n\\n /**\\n * @dev Check that caller is admin or this contract is initializing itself as\\n * the new implementation.\\n * There should be no way to satisfy msg.sender == comptrollerImplementaiton\\n * without tx.origin also being admin, but both are included for extra safety\\n */\\n function adminOrInitializing() internal view returns (bool) {\\n bool initializing = (\\n msg.sender == comptrollerImplementation\\n &&\\n //solium-disable-next-line security/no-tx-origin\\n tx.origin == admin\\n );\\n bool isAdmin = msg.sender == admin;\\n return isAdmin || initializing;\\n }\\n}\",\"keccak256\":\"0xe1515e04e6d62f384be5f47a334c558ddd98a0b96cfd64b7a3d012775412d91e\"},\"contracts/ComptrollerInterface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\ncontract ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n bool public constant isComptroller = true;\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata cTokens) external returns (uint[] memory);\\n function exitMarket(address cToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address cToken, address minter, uint mintAmount) external returns (uint);\\n function mintVerify(address cToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address cToken, address redeemer, uint redeemTokens) external returns (uint);\\n function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address cToken, address borrower, uint borrowAmount) external returns (uint);\\n function borrowVerify(address cToken, address borrower, uint borrowAmount) external;\\n\\n function repayBorrowAllowed(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount) external returns (uint);\\n function repayBorrowVerify(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex) external;\\n\\n function liquidateBorrowAllowed(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount) external returns (uint);\\n function liquidateBorrowVerify(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens) external;\\n\\n function seizeAllowed(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external returns (uint);\\n function seizeVerify(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external;\\n\\n function transferAllowed(address cToken, address src, address dst, uint transferTokens) external returns (uint);\\n function transferVerify(address cToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n uint repayAmount) external view returns (uint, uint);\\n}\\n\",\"keccak256\":\"0xede7670d2dd7b25d0187aecd2c28b7b5ca7d7c1bdac144fbedecf5d4bdd92a6b\"},\"contracts/ComptrollerStorage.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.sol\\\";\\nimport \\\"./PriceOracle.sol\\\";\\n\\ncontract UnitrollerAdminStorage {\\n /**\\n * @notice Administrator for this contract\\n */\\n address public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address public pendingAdmin;\\n\\n /**\\n * @notice Active brains of Unitroller\\n */\\n address public comptrollerImplementation;\\n\\n /**\\n * @notice Pending brains of Unitroller\\n */\\n address public pendingComptrollerImplementation;\\n}\\n\\ncontract ComptrollerV1Storage is UnitrollerAdminStorage {\\n\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n PriceOracle public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives\\n */\\n uint public liquidationIncentiveMantissa;\\n\\n /**\\n * @notice Max number of assets a single account can participate in (borrow or use as collateral)\\n */\\n uint public maxAssets;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\\n */\\n mapping(address => CToken[]) public accountAssets;\\n\\n}\\n\\ncontract ComptrollerV2Storage is ComptrollerV1Storage {\\n struct Market {\\n /// @notice Whether or not this market is listed\\n bool isListed;\\n\\n /**\\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\\n * For instance, 0.9 to allow borrowing 90% of collateral value.\\n * Must be between 0 and 1, and stored as a mantissa.\\n */\\n uint collateralFactorMantissa;\\n\\n /// @notice Per-market mapping of \\\"accounts in this asset\\\"\\n mapping(address => bool) accountMembership;\\n\\n /// @notice Whether or not this market receives COMP\\n bool isComped;\\n }\\n\\n /**\\n * @notice Official mapping of cTokens -> Market metadata\\n * @dev Used e.g. to determine if a market is supported\\n */\\n mapping(address => Market) public markets;\\n\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n * Actions which allow users to remove their own assets cannot be paused.\\n * Liquidation / seizing / transfer can only be paused globally, not by market.\\n */\\n address public pauseGuardian;\\n bool public _mintGuardianPaused;\\n bool public _borrowGuardianPaused;\\n bool public transferGuardianPaused;\\n bool public seizeGuardianPaused;\\n mapping(address => bool) public mintGuardianPaused;\\n mapping(address => bool) public borrowGuardianPaused;\\n}\\n\\ncontract ComptrollerV3Storage is ComptrollerV2Storage {\\n struct CompMarketState {\\n /// @notice The market's last updated compBorrowIndex or compSupplyIndex\\n uint224 index;\\n\\n /// @notice The block number the index was last updated at\\n uint32 block;\\n }\\n\\n /// @notice A list of all markets\\n CToken[] public allMarkets;\\n\\n /// @notice The rate at which the flywheel distributes COMP, per block\\n uint public compRate;\\n\\n /// @notice The portion of compRate that each market currently receives\\n mapping(address => uint) public compSpeeds;\\n\\n /// @notice The COMP market supply state for each market\\n mapping(address => CompMarketState) public compSupplyState;\\n\\n /// @notice The COMP market borrow state for each market\\n mapping(address => CompMarketState) public compBorrowState;\\n\\n /// @notice The COMP borrow index for each market for each supplier as of the last time they accrued COMP\\n mapping(address => mapping(address => uint)) public compSupplierIndex;\\n\\n /// @notice The COMP borrow index for each market for each borrower as of the last time they accrued COMP\\n mapping(address => mapping(address => uint)) public compBorrowerIndex;\\n\\n /// @notice The COMP accrued but not yet transferred to each user\\n mapping(address => uint) public compAccrued;\\n}\\n\\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\\n // @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\\n address public borrowCapGuardian;\\n\\n // @notice Borrow caps enforced by borrowAllowed for each cToken address. Defaults to zero which corresponds to unlimited borrowing.\\n mapping(address => uint) public borrowCaps;\\n}\\n\\ncontract ComptrollerV5Storage is ComptrollerV4Storage {\\n /// @notice The portion of COMP that each contributor receives per block\\n mapping(address => uint) public compContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's COMP rewards have been allocated\\n mapping(address => uint) public lastContributorBlock;\\n}\\n\",\"keccak256\":\"0x5db970485549f493618b5e36bfd4d799d4f8701a136bf71ed6e0117e1ed8c254\"},\"contracts/EIP20Interface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title ERC 20 Token Standard Interface\\n * https://eips.ethereum.org/EIPS/eip-20\\n */\\ninterface EIP20Interface {\\n function name() external view returns (string memory);\\n function symbol() external view returns (string memory);\\n function decimals() external view returns (uint8);\\n\\n /**\\n * @notice Get the total number of tokens in circulation\\n * @return The supply of tokens\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @notice Gets the balance of the specified address\\n * @param owner The address from which the balance will be retrieved\\n * @return The balance\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transfer(address dst, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferFrom(address src, address dst, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (-1 means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (-1 means infinite)\\n */\\n function allowance(address owner, address spender) external view returns (uint256 remaining);\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n}\\n\",\"keccak256\":\"0xfd8ed2eac6d0b4d9ee6b32628ba68bae17544b66f190a5f7ce0c6ad024579dc8\"},\"contracts/EIP20NonStandardInterface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title EIP20NonStandardInterface\\n * @dev Version of ERC20 with no return values for `transfer` and `transferFrom`\\n * See https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\\n */\\ninterface EIP20NonStandardInterface {\\n\\n /**\\n * @notice Get the total number of tokens in circulation\\n * @return The supply of tokens\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @notice Gets the balance of the specified address\\n * @param owner The address from which the balance will be retrieved\\n * @return The balance\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n ///\\n /// !!!!!!!!!!!!!!\\n /// !!! NOTICE !!! `transfer` does not return a value, in violation of the ERC-20 specification\\n /// !!!!!!!!!!!!!!\\n ///\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n */\\n function transfer(address dst, uint256 amount) external;\\n\\n ///\\n /// !!!!!!!!!!!!!!\\n /// !!! NOTICE !!! `transferFrom` does not return a value, in violation of the ERC-20 specification\\n /// !!!!!!!!!!!!!!\\n ///\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n */\\n function transferFrom(address src, address dst, uint256 amount) external;\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent\\n */\\n function allowance(address owner, address spender) external view returns (uint256 remaining);\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n}\\n\",\"keccak256\":\"0x9719f12e4b80b51147ac195553a198cf8b0c516e7e4d04fc324a23ed15cbafb2\"},\"contracts/ErrorReporter.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\ncontract ComptrollerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\",\"keccak256\":\"0x5179afb1071c0fd555e5c1f1d2565f72dbe1740cc3dd02f6e52037f150afc5c9\"},\"contracts/Exponential.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CarefulMath.sol\\\";\\nimport \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @dev Legacy contract for compatibility reasons with existing contracts that still use MathError\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: rational}));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({mantissa: result}));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({mantissa: result}));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: scaledMantissa}));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: descaledMantissa}));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) pure internal returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({mantissa: 0}));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({mantissa: product}));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) pure internal returns (MathError, Exp memory) {\\n return mulExp(Exp({mantissa: a}), Exp({mantissa: b}));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) pure internal returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6ff054d65a0289dbb43c9f437d6909f9cf1207c9b8f984b3cb8e97a9de76a434\"},\"contracts/ExponentialNoError.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\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 Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) pure internal returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) pure internal returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) pure internal returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) pure internal returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) pure internal returns (uint224) {\\n require(n < 2**224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) pure internal returns (uint32) {\\n require(n < 2**32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: add_(a.mantissa, b.mantissa)});\\n }\\n\\n function add_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: add_(a.mantissa, b.mantissa)});\\n }\\n\\n function add_(uint a, uint b) pure internal returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: sub_(a.mantissa, b.mantissa)});\\n }\\n\\n function sub_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: sub_(a.mantissa, b.mantissa)});\\n }\\n\\n function sub_(uint a, uint b) pure internal returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: mul_(a.mantissa, b.mantissa) / expScale});\\n }\\n\\n function mul_(Exp memory a, uint b) pure internal returns (Exp memory) {\\n return Exp({mantissa: mul_(a.mantissa, b)});\\n }\\n\\n function mul_(uint a, Exp memory b) pure internal returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: mul_(a.mantissa, b.mantissa) / doubleScale});\\n }\\n\\n function mul_(Double memory a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: mul_(a.mantissa, b)});\\n }\\n\\n function mul_(uint a, Double memory b) pure internal returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) pure internal returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) pure internal 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) pure internal returns (Exp memory) {\\n return Exp({mantissa: div_(mul_(a.mantissa, expScale), b.mantissa)});\\n }\\n\\n function div_(Exp memory a, uint b) pure internal returns (Exp memory) {\\n return Exp({mantissa: div_(a.mantissa, b)});\\n }\\n\\n function div_(uint a, Exp memory b) pure internal returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa)});\\n }\\n\\n function div_(Double memory a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(a.mantissa, b)});\\n }\\n\\n function div_(uint a, Double memory b) pure internal returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) pure internal returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(mul_(a, doubleScale), b)});\\n }\\n}\\n\",\"keccak256\":\"0x7cb184b7cee71a5e707053dfba7eebbd46f11974004028100510ccce19b6694d\"},\"contracts/InterestRateModel.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Compound's InterestRateModel Interface\\n * @author Compound\\n */\\ncontract InterestRateModel {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint cash, uint borrows, uint reserves) external view returns (uint);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) external view returns (uint);\\n\\n}\\n\",\"keccak256\":\"0x929282d73c79e6d700ebe79f9fafc1e414b3848acff5a56d6740afd1dc908678\"},\"contracts/PriceOracle.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.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 cToken asset\\n * @param cToken The cToken to get the underlying price of\\n * @return The underlying asset price mantissa (scaled by 1e18).\\n * Zero means the price is unavailable.\\n */\\n function getUnderlyingPrice(CToken cToken) external view returns (uint);\\n}\\n\",\"keccak256\":\"0xe79ebc23bba508eb2479e7b3340abf566da1ab62131f106aee1aac3dc53816ef\"},\"contracts/Unitroller.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ErrorReporter.sol\\\";\\nimport \\\"./ComptrollerStorage.sol\\\";\\n/**\\n * @title ComptrollerCore\\n * @dev Storage for the comptroller is at this address, while execution is delegated to the `comptrollerImplementation`.\\n * CTokens should reference this contract as their comptroller.\\n */\\ncontract Unitroller is UnitrollerAdminStorage, ComptrollerErrorReporter {\\n\\n /**\\n * @notice Emitted when pendingComptrollerImplementation is changed\\n */\\n event NewPendingImplementation(address oldPendingImplementation, address newPendingImplementation);\\n\\n /**\\n * @notice Emitted when pendingComptrollerImplementation is accepted, which means comptroller implementation is updated\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Emitted when pendingAdmin is accepted, which means admin is updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n constructor() public {\\n // Set admin to caller\\n admin = msg.sender;\\n }\\n\\n /*** Admin Functions ***/\\n function _setPendingImplementation(address newPendingImplementation) public returns (uint) {\\n\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_IMPLEMENTATION_OWNER_CHECK);\\n }\\n\\n address oldPendingImplementation = pendingComptrollerImplementation;\\n\\n pendingComptrollerImplementation = newPendingImplementation;\\n\\n emit NewPendingImplementation(oldPendingImplementation, pendingComptrollerImplementation);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts new implementation of comptroller. msg.sender must be pendingImplementation\\n * @dev Admin function for new implementation to accept it's role as implementation\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptImplementation() public returns (uint) {\\n // Check caller is pendingImplementation and pendingImplementation \\u2260 address(0)\\n if (msg.sender != pendingComptrollerImplementation || pendingComptrollerImplementation == address(0)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldImplementation = comptrollerImplementation;\\n address oldPendingImplementation = pendingComptrollerImplementation;\\n\\n comptrollerImplementation = pendingComptrollerImplementation;\\n\\n pendingComptrollerImplementation = address(0);\\n\\n emit NewImplementation(oldImplementation, comptrollerImplementation);\\n emit NewPendingImplementation(oldPendingImplementation, pendingComptrollerImplementation);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPendingAdmin(address newPendingAdmin) public returns (uint) {\\n // Check caller = admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\\n }\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptAdmin() public returns (uint) {\\n // Check caller is pendingAdmin and pendingAdmin \\u2260 address(0)\\n if (msg.sender != pendingAdmin || msg.sender == address(0)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = address(0);\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return 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 () payable external {\\n // delegate all other functions to current implementation\\n (bool success, ) = comptrollerImplementation.delegatecall(msg.data);\\n\\n assembly {\\n let free_mem_ptr := mload(0x40)\\n returndatacopy(free_mem_ptr, 0, returndatasize)\\n\\n switch success\\n case 0 { revert(free_mem_ptr, returndatasize) }\\n default { return(free_mem_ptr, returndatasize) }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x51f81451eab9d5c4849507e724f2b2c53e41f54e5359fdbeae89432a727c16df\"}},\"version\":1}" + }, + "contracts/ComptrollerG2.sol:ComptrollerG2": { + "abi": "[{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"action\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"pauseState\",\"type\":\"bool\"}],\"name\":\"ActionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"action\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"pauseState\",\"type\":\"bool\"}],\"name\":\"ActionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketEntered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketExited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"MarketListed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCloseFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCloseFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCollateralFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCollateralFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldLiquidationIncentiveMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"NewLiquidationIncentive\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMaxAssets\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMaxAssets\",\"type\":\"uint256\"}],\"name\":\"NewMaxAssets\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldPauseGuardian\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"NewPauseGuardian\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"oldPriceOracle\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"newPriceOracle\",\"type\":\"address\"}],\"name\":\"NewPriceOracle\",\"type\":\"event\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract Unitroller\",\"name\":\"unitroller\",\"type\":\"address\"}],\"name\":\"_become\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setBorrowPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCloseFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCollateralFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"_setLiquidationIncentive\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newMaxAssets\",\"type\":\"uint256\"}],\"name\":\"_setMaxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setMintPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"_setPauseGuardian\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"newOracle\",\"type\":\"address\"}],\"name\":\"_setPriceOracle\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setSeizePaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setTransferPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"_supportMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"checkMembership\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"enterMarkets\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenAddress\",\"type\":\"address\"}],\"name\":\"exitMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAssetsIn\",\"outputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenModify\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"getHypotheticalAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"isComptroller\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateCalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"liquidationIncentiveMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"markets\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isComped\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"mintAmount\",\"type\":\"uint256\"}],\"name\":\"mintAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualMintAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"mintTokens\",\"type\":\"uint256\"}],\"name\":\"mintVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"repayBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowerIndex\",\"type\":\"uint256\"}],\"name\":\"repayBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"seizeGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"transferGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + "bin": "608060405234801561001057600080fd5b50600080546001600160a01b03191633179055613500806100326000396000f3fe608060405234801561001057600080fd5b50600436106102f05760003560e01c80636d35bf911161019d578063c2998238116100e9578063dcfbc0c7116100a2578063e87554461161007c578063e875544614610b52578063eabe7d9114610b5a578063ede4edd014610b90578063f851a44014610bb6576102f0565b8063dcfbc0c714610b16578063e4028eee14610b1e578063e6653f3d14610b4a576102f0565b8063c29982381461095f578063c488847b14610a02578063d02f735114610a51578063d9226ced14610a97578063da3d454c14610ab4578063dce1544914610aea576102f0565b8063929fe9a111610156578063abfceffc11610130578063abfceffc1461089d578063ac0b0bb714610913578063bb82aa5e1461091b578063bdcdc25814610923576102f0565b8063929fe9a11461084157806394b2294b1461086f578063a76b3fda14610877576102f0565b80636d35bf911461075e578063731f0c2b146107a45780637dc0d1d0146107ca57806387f76303146107d25780638e8f294b146107da5780638ebf636414610822576102f0565b806347ef3b3b1161025c57806355ee1fe1116102155780635f5af1aa116101ef5780635f5af1aa146106905780635fc7e71e146106b65780636a56947e146106fc5780636d154ea514610738576102f0565b806355ee1fe11461060e5780635c778605146106345780635ec88c791461066a576102f0565b806347ef3b3b146104d15780634ada90af1461051d5780634e79238f146105255780634ef4c3e11461057f5780634fd42e17146105b557806351dff989146105d2576102f0565b806326782247116102ae578063267822471461041b5780632d70db7814610423578063317b0b77146104425780633bcf7ec11461045f5780633c94786f1461048d57806341c728b914610495576102f0565b80627e3dd2146102f557806318c882a5146103115780631d504dc61461033f5780631ededc911461036757806324008a62146103a957806324a3d622146103f7575b600080fd5b6102fd610bbe565b604080519115158252519081900360200190f35b6102fd6004803603604081101561032757600080fd5b506001600160a01b0381351690602001351515610bc3565b6103656004803603602081101561035557600080fd5b50356001600160a01b0316610d63565b005b610365600480360360a081101561037d57600080fd5b506001600160a01b03813581169160208101358216916040820135169060608101359060800135610ec8565b6103e5600480360360808110156103bf57600080fd5b506001600160a01b03813581169160208101358216916040820135169060600135610ecf565b60408051918252519081900360200190f35b6103ff610f05565b604080516001600160a01b039092168252519081900360200190f35b6103ff610f14565b6102fd6004803603602081101561043957600080fd5b50351515610f23565b6103e56004803603602081101561045857600080fd5b503561105d565b6102fd6004803603604081101561047557600080fd5b506001600160a01b038135169060200135151561116e565b6102fd611309565b610365600480360360808110156104ab57600080fd5b506001600160a01b03813581169160208101359091169060408101359060600135611319565b610365600480360360c08110156104e757600080fd5b506001600160a01b0381358116916020810135821691604082013581169160608101359091169060808101359060a0013561131f565b6103e5611327565b6105616004803603608081101561053b57600080fd5b506001600160a01b0381358116916020810135909116906040810135906060013561132d565b60408051938452602084019290925282820152519081900360600190f35b6103e56004803603606081101561059557600080fd5b506001600160a01b03813581169160208101359091169060400135611367565b6103e5600480360360208110156105cb57600080fd5b50356113fd565b610365600480360360808110156105e857600080fd5b506001600160a01b038135811691602081013590911690604081013590606001356114f1565b6103e56004803603602081101561062457600080fd5b50356001600160a01b0316611545565b6103656004803603606081101561064a57600080fd5b506001600160a01b038135811691602081013590911690604001356115cc565b6105616004803603602081101561068057600080fd5b50356001600160a01b03166115d1565b6103e5600480360360208110156106a657600080fd5b50356001600160a01b0316611606565b6103e5600480360360a08110156106cc57600080fd5b506001600160a01b038135811691602081013582169160408201358116916060810135909116906080013561168a565b6103656004803603608081101561071257600080fd5b506001600160a01b03813581169160208101358216916040820135169060600135611319565b6102fd6004803603602081101561074e57600080fd5b50356001600160a01b0316611811565b610365600480360360a081101561077457600080fd5b506001600160a01b0381358116916020810135821691604082013581169160608101359091169060800135610ec8565b6102fd600480360360208110156107ba57600080fd5b50356001600160a01b0316611826565b6103ff61183b565b6102fd61184a565b610800600480360360208110156107f057600080fd5b50356001600160a01b031661185a565b6040805193151584526020840192909252151582820152519081900360600190f35b6102fd6004803603602081101561083857600080fd5b50351515611880565b6102fd6004803603604081101561085757600080fd5b506001600160a01b03813581169160200135166119b9565b6103e56119ec565b6103e56004803603602081101561088d57600080fd5b50356001600160a01b03166119f2565b6108c3600480360360208110156108b357600080fd5b50356001600160a01b0316611b40565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156108ff5781810151838201526020016108e7565b505050509050019250505060405180910390f35b6102fd611bc9565b6103ff611bd9565b6103e56004803603608081101561093957600080fd5b506001600160a01b03813581169160208101358216916040820135169060600135611be8565b6108c36004803603602081101561097557600080fd5b81019060208101813564010000000081111561099057600080fd5b8201836020820111156109a257600080fd5b803590602001918460208302840111640100000000831117156109c457600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550611c4a945050505050565b610a3860048036036060811015610a1857600080fd5b506001600160a01b03813581169160208101359091169060400135611ce1565b6040805192835260208301919091528051918290030190f35b6103e5600480360360a0811015610a6757600080fd5b506001600160a01b0381358116916020810135821691604082013581169160608101359091169060800135611f56565b6103e560048036036020811015610aad57600080fd5b50356120ed565b6103e560048036036060811015610aca57600080fd5b506001600160a01b03813581169160208101359091169060400135612156565b6103ff60048036036040811015610b0057600080fd5b506001600160a01b0381351690602001356123a3565b6103ff6123d8565b6103e560048036036040811015610b3457600080fd5b506001600160a01b0381351690602001356123e7565b6102fd612597565b6103e56125a7565b6103e560048036036060811015610b7057600080fd5b506001600160a01b038135811691602081013590911690604001356125ad565b6103e560048036036020811015610ba657600080fd5b50356001600160a01b03166125ba565b6103ff6128cd565b600181565b6001600160a01b03821660009081526009602052604081205460ff16610c1a5760405162461bcd60e51b81526004018080602001828103825260288152602001806134316028913960400191505060405180910390fd5b600a546001600160a01b0316331480610c3d57506000546001600160a01b031633145b610c785760405162461bcd60e51b81526004018080602001828103825260278152602001806134596027913960400191505060405180910390fd5b6000546001600160a01b0316331480610c9357506001821515145b610cdd576040805162461bcd60e51b81526020600482015260166024820152756f6e6c792061646d696e2063616e20756e706175736560501b604482015290519081900360640190fd5b6001600160a01b0383166000818152600c6020908152604091829020805486151560ff199091168117909155825193845283830152606090830181905260069083015265426f72726f7760d01b6080830152517f71aec636243f9709bb0007ae15e9afb8150ab01716d75fd7573be5cc096e03b09181900360a00190a150805b92915050565b806001600160a01b031663f851a4406040518163ffffffff1660e01b815260040160206040518083038186803b158015610d9c57600080fd5b505afa158015610db0573d6000803e3d6000fd5b505050506040513d6020811015610dc657600080fd5b50516001600160a01b03163314610e0e5760405162461bcd60e51b81526004018080602001828103825260278152602001806134a56027913960400191505060405180910390fd5b6000816001600160a01b031663c1e803346040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610e4b57600080fd5b505af1158015610e5f573d6000803e3d6000fd5b505050506040513d6020811015610e7557600080fd5b505190508015610ec4576040805162461bcd60e51b815260206004820152601560248201527418da185b99d9481b9bdd08185d5d1a1bdc9a5e9959605a1b604482015290519081900360640190fd5b5050565b5050505050565b6001600160a01b03841660009081526009602052604081205460ff16610ef757506009610efd565b60005b90505b949350505050565b600a546001600160a01b031681565b6001546001600160a01b031681565b600a546000906001600160a01b0316331480610f4957506000546001600160a01b031633145b610f845760405162461bcd60e51b81526004018080602001828103825260278152602001806134596027913960400191505060405180910390fd5b6000546001600160a01b0316331480610f9f57506001821515145b610fe9576040805162461bcd60e51b81526020600482015260166024820152756f6e6c792061646d696e2063616e20756e706175736560501b604482015290519081900360640190fd5b600a8054831515600160b81b810260ff60b81b1990921691909117909155604080516020810192909252808252600582820152645365697a6560d81b6060830152517fef159d9a32b2472e32b098f954f3ce62d232939f1c207070b584df1814de2de09181900360800190a150805b919050565b600080546001600160a01b031633146110835761107c600160046128dc565b9050611058565b61108b61336e565b5060408051602081019091528281526110a261336e565b50604080516020810190915266b1a2bc2ec5000081526110c28282612942565b156110db576110d26005806128dc565b92505050611058565b6110e361336e565b506040805160208101909152670c7d713b49da00008152611104818461294a565b1561111e576111146005806128dc565b9350505050611058565b6005805490869055604080518281526020810188905281517f3b9670cf975d26958e754b57098eaa2ac914d8d2a31b83257997b9f346110fd9929181900390910190a160005b9695505050505050565b6001600160a01b03821660009081526009602052604081205460ff166111c55760405162461bcd60e51b81526004018080602001828103825260288152602001806134316028913960400191505060405180910390fd5b600a546001600160a01b03163314806111e857506000546001600160a01b031633145b6112235760405162461bcd60e51b81526004018080602001828103825260278152602001806134596027913960400191505060405180910390fd5b6000546001600160a01b031633148061123e57506001821515145b611288576040805162461bcd60e51b81526020600482015260166024820152756f6e6c792061646d696e2063616e20756e706175736560501b604482015290519081900360640190fd5b6001600160a01b0383166000818152600b6020908152604091829020805486151560ff199091168117909155825193845283830152606090830181905260049083015263135a5b9d60e21b6080830152517f71aec636243f9709bb0007ae15e9afb8150ab01716d75fd7573be5cc096e03b09181900360a00190a150919050565b600a54600160a01b900460ff1681565b50505050565b505050505050565b60065481565b6000806000806000806113428a8a8a8a612951565b92509250925082601181111561135457fe5b95509093509150505b9450945094915050565b6001600160a01b0383166000908152600b602052604081205460ff16156113c6576040805162461bcd60e51b815260206004820152600e60248201526d1b5a5b9d081a5cc81c185d5cd95960921b604482015290519081900360640190fd5b6001600160a01b03841660009081526009602052604090205460ff166113f05760095b90506113f6565b60005b90505b9392505050565b600080546001600160a01b0316331461141c5761107c6001600b6128dc565b61142461336e565b50604080516020810190915282815261143b61336e565b506040805160208101909152670de0b6b3a7640000815261145c828261294a565b1561146d576110d26007600c6128dc565b61147561336e565b5060408051602081019091526714d1120d7b1600008152611496818461294a565b156114a7576111146007600c6128dc565b6006805490869055604080518281526020810188905281517faeba5a6c40a8ac138134bff1aaa65debf25971188a58804bad717f82f0ec1316929181900390910190a16000611164565b801580156114ff5750600082115b15611319576040805162461bcd60e51b815260206004820152601160248201527072656465656d546f6b656e73207a65726f60781b604482015290519081900360640190fd5b600080546001600160a01b031633146115645761107c600160106128dc565b600480546001600160a01b038481166001600160a01b0319831681179093556040805191909216808252602082019390935281517fd52b2b9b7e9ee655fcb95d2e5b9e0c9f69e7ef2b8e9d2d0ea78402d576d22e22929181900390910190a160009392505050565b505050565b6000806000806000806115e8876000806000612951565b9250925092508260118111156115fa57fe5b97919650945092505050565b600080546001600160a01b031633146116255761107c600160136128dc565b600a80546001600160a01b038481166001600160a01b0319831617928390556040805192821680845293909116602083015280517f0613b6ee6a04f0d09f390e4d9318894b9f6ac7fd83897cd8d18896ba579c401e9281900390910190a160006113f6565b6001600160a01b03851660009081526009602052604081205460ff1615806116cb57506001600160a01b03851660009081526009602052604090205460ff16155b156116da5760095b9050611808565b6000806116e685612d6c565b919350909150600090508260118111156116fc57fe5b146117165781601181111561170d57fe5b92505050611808565b8061172257600361170d565b6000886001600160a01b03166395dd9193876040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561177a57600080fd5b505afa15801561178e573d6000803e3d6000fd5b505050506040513d60208110156117a457600080fd5b50516040805160208101909152600554815290915060009081906117c89084612d8c565b909250905060008260038111156117db57fe5b146117ef57600b5b95505050505050611808565b808711156117fe5760116117e3565b6000955050505050505b95945050505050565b600c6020526000908152604090205460ff1681565b600b6020526000908152604090205460ff1681565b6004546001600160a01b031681565b600a54600160b01b900460ff1681565b60096020526000908152604090208054600182015460039092015460ff91821692911683565b600a546000906001600160a01b03163314806118a657506000546001600160a01b031633145b6118e15760405162461bcd60e51b81526004018080602001828103825260278152602001806134596027913960400191505060405180910390fd5b6000546001600160a01b03163314806118fc57506001821515145b611946576040805162461bcd60e51b81526020600482015260166024820152756f6e6c792061646d696e2063616e20756e706175736560501b604482015290519081900360640190fd5b600a8054831515600160b01b810260ff60b01b1990921691909117909155604080516020810192909252808252600882820152672a3930b739b332b960c11b6060830152517fef159d9a32b2472e32b098f954f3ce62d232939f1c207070b584df1814de2de09181900360800190a15090565b6001600160a01b038082166000908152600960209081526040808320938616835260029093019052205460ff1692915050565b60075481565b600080546001600160a01b03163314611a115761107c600160126128dc565b6001600160a01b03821660009081526009602052604090205460ff1615611a3e5761107c600a60116128dc565b816001600160a01b031663fe9c44ae6040518163ffffffff1660e01b815260040160206040518083038186803b158015611a7757600080fd5b505afa158015611a8b573d6000803e3d6000fd5b505050506040513d6020811015611aa157600080fd5b5050604080516060810182526001808252600060208381018281528486018381526001600160a01b03891680855260098452938790209551865490151560ff199182161787559151948601949094559251600390940180549415159490931693909317909155825190815291517fcf583bb0c569eb967f806b11601c4cb93c10310485c67add5f8362c2f212321f9281900390910190a1600092915050565b60608060086000846001600160a01b03166001600160a01b03168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015611bbc57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611b9e575b5093979650505050505050565b600a54600160b81b900460ff1681565b6002546001600160a01b031681565b600a54600090600160b01b900460ff1615611c3f576040805162461bcd60e51b81526020600482015260126024820152711d1c985b9cd9995c881a5cc81c185d5cd95960721b604482015290519081900360640190fd5b610efa858584612de0565b6060600082519050606081604051908082528060200260200182016040528015611c7e578160200160208202803883390190505b50905060005b82811015611cd9576000858281518110611c9a57fe5b60200260200101519050611cae8133612e4f565b6011811115611cb957fe5b838381518110611cc557fe5b602090810291909101015250600101611c84565b509392505050565b600480546040805163fc57d4df60e01b81526001600160a01b038781169482019490945290516000938493849391169163fc57d4df91602480820192602092909190829003018186803b158015611d3757600080fd5b505afa158015611d4b573d6000803e3d6000fd5b505050506040513d6020811015611d6157600080fd5b5051600480546040805163fc57d4df60e01b81526001600160a01b038a8116948201949094529051939450600093929091169163fc57d4df91602480820192602092909190829003018186803b158015611dba57600080fd5b505afa158015611dce573d6000803e3d6000fd5b505050506040513d6020811015611de457600080fd5b50519050811580611df3575080155b15611e0857600d935060009250611f4e915050565b6000866001600160a01b031663182df0f56040518163ffffffff1660e01b815260040160206040518083038186803b158015611e4357600080fd5b505afa158015611e57573d6000803e3d6000fd5b505050506040513d6020811015611e6d57600080fd5b505190506000611e7b61336e565b611e8361336e565b611e8b61336e565b6000611e9960065489612f70565b945090506000816003811115611eab57fe5b14611ec757600b5b995060009850611f4e975050505050505050565b611ed18787612f70565b935090506000816003811115611ee357fe5b14611eef57600b611eb3565b611ef98484612fab565b925090506000816003811115611f0b57fe5b14611f1757600b611eb3565b611f21828c612d8c565b955090506000816003811115611f3357fe5b14611f3f57600b611eb3565b60009950939750505050505050505b935093915050565b600a54600090600160b81b900460ff1615611faa576040805162461bcd60e51b815260206004820152600f60248201526e1cd95a5e99481a5cc81c185d5cd959608a1b604482015290519081900360640190fd5b6001600160a01b03861660009081526009602052604090205460ff161580611feb57506001600160a01b03851660009081526009602052604090205460ff16155b15611ff75760096116d3565b846001600160a01b0316635fe3b5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561203057600080fd5b505afa158015612044573d6000803e3d6000fd5b505050506040513d602081101561205a57600080fd5b505160408051635fe3b56760e01b815290516001600160a01b0392831692891691635fe3b567916004808301926020929190829003018186803b1580156120a057600080fd5b505afa1580156120b4573d6000803e3d6000fd5b505050506040513d60208110156120ca57600080fd5b50516001600160a01b0316146120e15760026116d3565b60009695505050505050565b600080546001600160a01b0316331461210c5761107c6001600d6128dc565b6007805490839055604080518281526020810185905281517f7093cf1eb653f749c3ff531d6df7f92764536a7fa0d13530cd26e070780c32ea929181900390910190a160006113f6565b6001600160a01b0383166000908152600c602052604081205460ff16156121b7576040805162461bcd60e51b815260206004820152601060248201526f189bdc9c9bddc81a5cc81c185d5cd95960821b604482015290519081900360640190fd5b6001600160a01b03841660009081526009602052604090205460ff166121de5760096113e9565b6001600160a01b038085166000908152600960209081526040808320938716835260029093019052205460ff166122ce57336001600160a01b03851614612264576040805162461bcd60e51b815260206004820152601560248201527439b2b73232b91036bab9ba1031329031aa37b5b2b760591b604482015290519081900360640190fd5b60006122703385612e4f565b9050600081601181111561228057fe5b146122995780601181111561229157fe5b9150506113f6565b6001600160a01b038086166000908152600960209081526040808320938816835260029093019052205460ff166122cc57fe5b505b600480546040805163fc57d4df60e01b81526001600160a01b03888116948201949094529051929091169163fc57d4df91602480820192602092909190829003018186803b15801561231f57600080fd5b505afa158015612333573d6000803e3d6000fd5b505050506040513d602081101561234957600080fd5b505161235657600d6113e9565b6000806123668587600087612951565b9193509091506000905082601181111561237c57fe5b146123965781601181111561238d57fe5b925050506113f6565b80156120e157600461238d565b600860205281600052604060002081815481106123bc57fe5b6000918252602090912001546001600160a01b03169150829050565b6003546001600160a01b031681565b600080546001600160a01b0316331461240d57612406600160066128dc565b9050610d5d565b6001600160a01b0383166000908152600960205260409020805460ff166124425761243a600960076128dc565b915050610d5d565b61244a61336e565b50604080516020810190915283815261246161336e565b506040805160208101909152670c7d713b49da00008152612482818361294a565b1561249d57612493600660086128dc565b9350505050610d5d565b84158015906125265750600480546040805163fc57d4df60e01b81526001600160a01b038a8116948201949094529051929091169163fc57d4df91602480820192602092909190829003018186803b1580156124f857600080fd5b505afa15801561250c573d6000803e3d6000fd5b505050506040513d602081101561252257600080fd5b5051155b1561253757612493600d60096128dc565b60018301805490869055604080516001600160a01b03891681526020810183905280820188905290517f70483e6592cd5182d45ac970e05bc62cdcc90e9d8ef2c2dbe686cf383bcd7fc59181900360600190a16000979650505050505050565b600a54600160a81b900460ff1681565b60055481565b60006113f3848484612de0565b6000808290506000806000836001600160a01b031663c37f68e2336040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060806040518083038186803b15801561261b57600080fd5b505afa15801561262f573d6000803e3d6000fd5b505050506040513d608081101561264557600080fd5b5080516020820151604090920151909450909250905082156126985760405162461bcd60e51b81526004018080602001828103825260258152602001806134806025913960400191505060405180910390fd5b80156126b5576126aa600c60026128dc565b945050505050611058565b60006126c2873385612de0565b905080156126e3576126d7600e600383612fc3565b95505050505050611058565b6001600160a01b0385166000908152600960209081526040808320338452600281019092529091205460ff166127225760009650505050505050611058565b3360009081526002820160209081526040808320805460ff19169055600882529182902080548351818402810184019094528084526060939283018282801561279457602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612776575b5050835193945083925060009150505b828110156127e957896001600160a01b03168482815181106127c257fe5b60200260200101516001600160a01b031614156127e1578091506127e9565b6001016127a4565b508181106127f357fe5b33600090815260086020526040902080548190600019810190811061281457fe5b9060005260206000200160009054906101000a90046001600160a01b031681838154811061283e57fe5b600091825260209091200180546001600160a01b0319166001600160a01b03929092169190911790558054612877826000198301613381565b50604080516001600160a01b038c16815233602082015281517fe699a64c18b07ac5b7301aa273f36a2287239eb9501d81950672794afba29a0d929181900390910190a160009c9b505050505050505050505050565b6000546001600160a01b031681565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa083601181111561290b57fe5b83601381111561291757fe5b604080519283526020830191909152600082820152519081900360600190a18260118111156113f657fe5b519051111590565b5190511090565b600080600061295e6133a5565b6001600160a01b0388166000908152600860209081526040808320805482518185028101850190935280835284936060939291908301828280156129cb57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116129ad575b50939450600093505050505b8151811015612d275760008282815181106129ee57fe5b60200260200101519050806001600160a01b031663c37f68e28e6040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060806040518083038186803b158015612a4e57600080fd5b505afa158015612a62573d6000803e3d6000fd5b505050506040513d6080811015612a7857600080fd5b508051602082015160408084015160609485015160808c0152938a01939093529188019190915294508415612abe5750600f97506000965086955061135d945050505050565b60408051602080820183526001600160a01b0380851660008181526009845285902060010154845260c08b01939093528351808301855260808b0151815260e08b015260048054855163fc57d4df60e01b815291820194909452935192169263fc57d4df9260248083019392829003018186803b158015612b3e57600080fd5b505afa158015612b52573d6000803e3d6000fd5b505050506040513d6020811015612b6857600080fd5b505160a08701819052612b8c5750600d97506000965086955061135d945050505050565b604080516020810190915260a08701518152610100870181905260c087015160e0880151612bb992613029565b61012088015293506000846003811115612bcf57fe5b14612beb5750600b97506000965086955061135d945050505050565b612c0386610120015187604001518860000151613081565b875293506000846003811115612c1557fe5b14612c315750600b97506000965086955061135d945050505050565b612c4986610100015187606001518860200151613081565b602088015293506000846003811115612c5e57fe5b14612c7a5750600b97506000965086955061135d945050505050565b8b6001600160a01b0316816001600160a01b03161415612d1e57612ca88661012001518c8860200151613081565b602088015293506000846003811115612cbd57fe5b14612cd95750600b97506000965086955061135d945050505050565b612ced8661010001518b8860200151613081565b602088015293506000846003811115612d0257fe5b14612d1e5750600b97506000965086955061135d945050505050565b506001016129d7565b50602084015184511115612d4e57505050602081015190516000945003915082905061135d565b505081516020909201516000955085945091909103915061135d9050565b6000806000612d7f846000806000612951565b9250925092509193909250565b6000806000612d9961336e565b612da386866130ce565b90925090506000826003811115612db657fe5b14612dc75750915060009050612dd9565b6000612dd282613136565b9350935050505b9250929050565b6001600160a01b03831660009081526009602052604081205460ff16612e075760096113e9565b6001600160a01b038085166000908152600960209081526040808320938716835260029093019052205460ff16612e3f5760006113e9565b6000806123668587866000612951565b6001600160a01b0382166000908152600960205260408120805460ff16612e7a576009915050610d5d565b6001600160a01b038316600090815260028201602052604090205460ff16151560011415612eac576000915050610d5d565b6007546001600160a01b03841660009081526008602052604090205410612ed7576010915050610d5d565b6001600160a01b0380841660008181526002840160209081526040808320805460ff19166001908117909155600883528184208054918201815584529282902090920180549489166001600160a01b031990951685179055815193845283019190915280517f3ab23ab0d51cccc0c3085aec51f99228625aa1a922b3a8ca89a26b0f2027a1a59281900390910190a15060009392505050565b6000612f7a61336e565b612fa0604051806020016040528086815250604051806020016040528086815250613145565b915091509250929050565b6000612fb561336e565b83518351612fa0919061322e565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0846011811115612ff257fe5b846013811115612ffe57fe5b604080519283526020830191909152818101859052519081900360600190a18360118111156113f357fe5b600061303361336e565b600061303d61336e565b6130478787613145565b9092509050600082600381111561305a57fe5b14613069579092509050611f4e565b6130738186613145565b935093505050935093915050565b600080600061308e61336e565b61309887876130ce565b909250905060008260038111156130ab57fe5b146130bc5750915060009050611f4e565b6130736130c882613136565b866132de565b60006130d861336e565b6000806130e9866000015186613304565b909250905060008260038111156130fc57fe5b1461311b57506040805160208101909152600081529092509050612dd9565b60408051602081019091529081526000969095509350505050565b51670de0b6b3a7640000900490565b600061314f61336e565b60008061316486600001518660000151613304565b9092509050600082600381111561317757fe5b1461319657506040805160208101909152600081529092509050612dd9565b6000806131ab6706f05b59d3b20000846132de565b909250905060008260038111156131be57fe5b146131e057506040805160208101909152600081529094509250612dd9915050565b6000806131f583670de0b6b3a7640000613343565b9092509050600082600381111561320857fe5b1461320f57fe5b604080516020810190915290815260009a909950975050505050505050565b600061323861336e565b60008061324d86670de0b6b3a7640000613304565b9092509050600082600381111561326057fe5b1461327f57506040805160208101909152600081529092509050612dd9565b60008061328c8388613343565b9092509050600082600381111561329f57fe5b146132c157506040805160208101909152600081529094509250612dd9915050565b604080516020810190915290815260009890975095505050505050565b6000808383018481106132f657600092509050612dd9565b506002915060009050612dd9565b6000808361331757506000905080612dd9565b8383028385828161332457fe5b041461333857506002915060009050612dd9565b600092509050612dd9565b600080826133575750600190506000612dd9565b600083858161336257fe5b04915091509250929050565b6040518060200160405280600081525090565b8154818355818111156115cc576000838152602090206115cc91810190830161340f565b6040518061014001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016133e361336e565b81526020016133f061336e565b81526020016133fd61336e565b815260200161340a61336e565b905290565b61342d91905b808211156134295760008155600101613415565b5090565b9056fe63616e6e6f742070617573652061206d61726b65742074686174206973206e6f74206c69737465646f6e6c7920706175736520677561726469616e20616e642061646d696e2063616e207061757365657869744d61726b65743a206765744163636f756e74536e617073686f74206661696c65646f6e6c7920756e6974726f6c6c65722061646d696e2063616e206368616e676520627261696e73a265627a7a72315820ff76109faddd19bfc4da5fd1bc3fee6bd3dc066bd275fe6ed58b4171504b2de364736f6c63430005100032", + "metadata": "{\"compiler\":{\"version\":\"0.5.16+commit.9c3226ce\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"action\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"pauseState\",\"type\":\"bool\"}],\"name\":\"ActionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"action\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"pauseState\",\"type\":\"bool\"}],\"name\":\"ActionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketEntered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketExited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"MarketListed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCloseFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCloseFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCollateralFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCollateralFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldLiquidationIncentiveMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"NewLiquidationIncentive\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMaxAssets\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMaxAssets\",\"type\":\"uint256\"}],\"name\":\"NewMaxAssets\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldPauseGuardian\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"NewPauseGuardian\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"oldPriceOracle\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"newPriceOracle\",\"type\":\"address\"}],\"name\":\"NewPriceOracle\",\"type\":\"event\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract Unitroller\",\"name\":\"unitroller\",\"type\":\"address\"}],\"name\":\"_become\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setBorrowPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCloseFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCollateralFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"_setLiquidationIncentive\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newMaxAssets\",\"type\":\"uint256\"}],\"name\":\"_setMaxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setMintPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"_setPauseGuardian\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"newOracle\",\"type\":\"address\"}],\"name\":\"_setPriceOracle\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setSeizePaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setTransferPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"_supportMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"checkMembership\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"enterMarkets\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenAddress\",\"type\":\"address\"}],\"name\":\"exitMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAssetsIn\",\"outputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenModify\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"getHypotheticalAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"isComptroller\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateCalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"liquidationIncentiveMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"markets\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isComped\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"mintAmount\",\"type\":\"uint256\"}],\"name\":\"mintAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualMintAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"mintTokens\",\"type\":\"uint256\"}],\"name\":\"mintVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"repayBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowerIndex\",\"type\":\"uint256\"}],\"name\":\"repayBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"seizeGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"transferGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Compound\",\"methods\":{\"_setCloseFactor(uint256)\":{\"details\":\"Admin function to set closeFactor\",\"params\":{\"newCloseFactorMantissa\":\"New close factor, scaled by 1e18\"},\"return\":\"uint 0=success, otherwise a failure. (See ErrorReporter for details)\"},\"_setCollateralFactor(address,uint256)\":{\"details\":\"Admin function to set per-market collateralFactor\",\"params\":{\"cToken\":\"The market to set the factor on\",\"newCollateralFactorMantissa\":\"The new collateral factor, scaled by 1e18\"},\"return\":\"uint 0=success, otherwise a failure. (See ErrorReporter for details)\"},\"_setLiquidationIncentive(uint256)\":{\"details\":\"Admin function to set liquidationIncentive\",\"params\":{\"newLiquidationIncentiveMantissa\":\"New liquidationIncentive scaled by 1e18\"},\"return\":\"uint 0=success, otherwise a failure. (See ErrorReporter for details)\"},\"_setMaxAssets(uint256)\":{\"details\":\"Admin function to set maxAssets\",\"params\":{\"newMaxAssets\":\"New max assets\"},\"return\":\"uint 0=success, otherwise a failure. (See ErrorReporter for details)\"},\"_setPauseGuardian(address)\":{\"params\":{\"newPauseGuardian\":\"The address of the new Pause Guardian\"},\"return\":\"uint 0=success, otherwise a failure. (See enum Error for details)\"},\"_setPriceOracle(address)\":{\"details\":\"Admin function to set a new price oracle\",\"return\":\"uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\"},\"_supportMarket(address)\":{\"details\":\"Admin function to set isListed and add support for the market\",\"params\":{\"cToken\":\"The address of the market (token) to list\"},\"return\":\"uint 0=success, otherwise a failure. (See enum Error for details)\"},\"borrowAllowed(address,address,uint256)\":{\"params\":{\"borrowAmount\":\"The amount of underlying the account would borrow\",\"borrower\":\"The account which would borrow the asset\",\"cToken\":\"The market to verify the borrow against\"},\"return\":\"0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"borrowVerify(address,address,uint256)\":{\"params\":{\"borrowAmount\":\"The amount of the underlying asset requested to borrow\",\"borrower\":\"The address borrowing the underlying\",\"cToken\":\"Asset whose underlying is being borrowed\"}},\"checkMembership(address,address)\":{\"params\":{\"account\":\"The address of the account to check\",\"cToken\":\"The cToken to check\"},\"return\":\"True if the account is in the asset, otherwise false.\"},\"enterMarkets(address[])\":{\"params\":{\"cTokens\":\"The list of addresses of the cToken markets to be enabled\"},\"return\":\"Success indicator for whether each corresponding market was entered\"},\"exitMarket(address)\":{\"details\":\"Sender must not have an outstanding borrow balance in the asset, or be providing neccessary collateral for an outstanding borrow.\",\"params\":{\"cTokenAddress\":\"The address of the asset to be removed\"},\"return\":\"Whether or not the account successfully exited the market\"},\"getAccountLiquidity(address)\":{\"return\":\"(possible error code (semi-opaque), account liquidity in excess of collateral requirements, account shortfall below collateral requirements)\"},\"getAssetsIn(address)\":{\"params\":{\"account\":\"The address of the account to pull assets for\"},\"return\":\"A dynamic list with the assets the account has entered\"},\"getHypotheticalAccountLiquidity(address,address,uint256,uint256)\":{\"params\":{\"account\":\"The account to determine liquidity for\",\"borrowAmount\":\"The amount of underlying to hypothetically borrow\",\"cTokenModify\":\"The market to hypothetically redeem/borrow in\",\"redeemTokens\":\"The number of tokens to hypothetically redeem\"},\"return\":\"(possible error code (semi-opaque), hypothetical account liquidity in excess of collateral requirements, hypothetical account shortfall below collateral requirements)\"},\"liquidateBorrowAllowed(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"repayAmount\":\"The amount of underlying being repaid\"}},\"liquidateBorrowVerify(address,address,address,address,uint256,uint256)\":{\"params\":{\"actualRepayAmount\":\"The amount of underlying being repaid\",\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\"}},\"liquidateCalculateSeizeTokens(address,address,uint256)\":{\"details\":\"Used in liquidation (called in cToken.liquidateBorrowFresh)\",\"params\":{\"actualRepayAmount\":\"The amount of cTokenBorrowed underlying to convert into cTokenCollateral tokens\",\"cTokenBorrowed\":\"The address of the borrowed cToken\",\"cTokenCollateral\":\"The address of the collateral cToken\"},\"return\":\"(errorCode, number of cTokenCollateral tokens to be seized in a liquidation)\"},\"mintAllowed(address,address,uint256)\":{\"params\":{\"cToken\":\"The market to verify the mint against\",\"mintAmount\":\"The amount of underlying being supplied to the market in exchange for tokens\",\"minter\":\"The account which would get the minted tokens\"},\"return\":\"0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"mintVerify(address,address,uint256,uint256)\":{\"params\":{\"actualMintAmount\":\"The amount of the underlying asset being minted\",\"cToken\":\"Asset being minted\",\"mintTokens\":\"The number of tokens being minted\",\"minter\":\"The address minting the tokens\"}},\"redeemAllowed(address,address,uint256)\":{\"params\":{\"cToken\":\"The market to verify the redeem against\",\"redeemTokens\":\"The number of cTokens to exchange for the underlying asset in the market\",\"redeemer\":\"The account which would redeem the tokens\"},\"return\":\"0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"redeemVerify(address,address,uint256,uint256)\":{\"params\":{\"cToken\":\"Asset being redeemed\",\"redeemAmount\":\"The amount of the underlying asset being redeemed\",\"redeemTokens\":\"The number of tokens being redeemed\",\"redeemer\":\"The address redeeming the tokens\"}},\"repayBorrowAllowed(address,address,address,uint256)\":{\"params\":{\"borrower\":\"The account which would borrowed the asset\",\"cToken\":\"The market to verify the repay against\",\"payer\":\"The account which would repay the asset\",\"repayAmount\":\"The amount of the underlying asset the account would repay\"},\"return\":\"0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"repayBorrowVerify(address,address,address,uint256,uint256)\":{\"params\":{\"actualRepayAmount\":\"The amount of underlying being repaid\",\"borrower\":\"The address of the borrower\",\"cToken\":\"Asset being repaid\",\"payer\":\"The address repaying the borrow\"}},\"seizeAllowed(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"seizeTokens\":\"The number of collateral tokens to seize\"}},\"seizeVerify(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"seizeTokens\":\"The number of collateral tokens to seize\"}},\"transferAllowed(address,address,address,uint256)\":{\"params\":{\"cToken\":\"The market to verify the transfer against\",\"dst\":\"The account which receives the tokens\",\"src\":\"The account which sources the tokens\",\"transferTokens\":\"The number of cTokens to transfer\"},\"return\":\"0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"transferVerify(address,address,address,uint256)\":{\"params\":{\"cToken\":\"Asset being transferred\",\"dst\":\"The account which receives the tokens\",\"src\":\"The account which sources the tokens\",\"transferTokens\":\"The number of cTokens to transfer\"}}},\"title\":\"Compound's Comptroller Contract\"},\"userdoc\":{\"methods\":{\"_setCloseFactor(uint256)\":{\"notice\":\"Sets the closeFactor used when liquidating borrows\"},\"_setCollateralFactor(address,uint256)\":{\"notice\":\"Sets the collateralFactor for a market\"},\"_setLiquidationIncentive(uint256)\":{\"notice\":\"Sets liquidationIncentive\"},\"_setMaxAssets(uint256)\":{\"notice\":\"Sets maxAssets which controls how many markets can be entered\"},\"_setPauseGuardian(address)\":{\"notice\":\"Admin function to change the Pause Guardian\"},\"_setPriceOracle(address)\":{\"notice\":\"Sets a new price oracle for the comptroller\"},\"_supportMarket(address)\":{\"notice\":\"Add the market to the markets mapping and set it as listed\"},\"borrowAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to borrow the underlying asset of the given market\"},\"borrowVerify(address,address,uint256)\":{\"notice\":\"Validates borrow and reverts on rejection. May emit logs.\"},\"checkMembership(address,address)\":{\"notice\":\"Returns whether the given account is entered in the given asset\"},\"enterMarkets(address[])\":{\"notice\":\"Add assets to be included in account liquidity calculation\"},\"exitMarket(address)\":{\"notice\":\"Removes asset from sender's account liquidity calculation\"},\"getAccountLiquidity(address)\":{\"notice\":\"Determine the current account liquidity wrt collateral requirements\"},\"getAssetsIn(address)\":{\"notice\":\"Returns the assets an account has entered\"},\"getHypotheticalAccountLiquidity(address,address,uint256,uint256)\":{\"notice\":\"Determine what the account liquidity would be if the given amounts were redeemed/borrowed\"},\"liquidateBorrowAllowed(address,address,address,address,uint256)\":{\"notice\":\"Checks if the liquidation should be allowed to occur\"},\"liquidateBorrowVerify(address,address,address,address,uint256,uint256)\":{\"notice\":\"Validates liquidateBorrow and reverts on rejection. May emit logs.\"},\"liquidateCalculateSeizeTokens(address,address,uint256)\":{\"notice\":\"Calculate number of tokens of collateral asset to seize given an underlying amount\"},\"mintAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to mint tokens in the given market\"},\"mintVerify(address,address,uint256,uint256)\":{\"notice\":\"Validates mint and reverts on rejection. May emit logs.\"},\"redeemAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to redeem tokens in the given market\"},\"redeemVerify(address,address,uint256,uint256)\":{\"notice\":\"Validates redeem and reverts on rejection. May emit logs.\"},\"repayBorrowAllowed(address,address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to repay a borrow in the given market\"},\"repayBorrowVerify(address,address,address,uint256,uint256)\":{\"notice\":\"Validates repayBorrow and reverts on rejection. May emit logs.\"},\"seizeAllowed(address,address,address,address,uint256)\":{\"notice\":\"Checks if the seizing of assets should be allowed to occur\"},\"seizeVerify(address,address,address,address,uint256)\":{\"notice\":\"Validates seize and reverts on rejection. May emit logs.\"},\"transferAllowed(address,address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to transfer tokens in the given market\"},\"transferVerify(address,address,address,uint256)\":{\"notice\":\"Validates transfer and reverts on rejection. May emit logs.\"}}}},\"settings\":{\"compilationTarget\":{\"contracts/ComptrollerG2.sol\":\"ComptrollerG2\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/CToken.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./CTokenInterfaces.sol\\\";\\nimport \\\"./ErrorReporter.sol\\\";\\nimport \\\"./Exponential.sol\\\";\\nimport \\\"./EIP20Interface.sol\\\";\\nimport \\\"./InterestRateModel.sol\\\";\\n\\n/**\\n * @title Compound's CToken Contract\\n * @notice Abstract base for CTokens\\n * @author Compound\\n */\\ncontract CToken is CTokenInterface, Exponential, TokenErrorReporter {\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_) public {\\n require(msg.sender == admin, \\\"only admin may initialize the market\\\");\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = getBlockNumber();\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Transfer `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = uint(-1);\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srcTokensNew;\\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, srcTokensNew) = 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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srcTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != uint(-1)) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n // unused function\\n // comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transfer(address dst, uint256 amount) external nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferFrom(address src, address dst, uint256 amount) external nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (-1 means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool) {\\n address src = msg.sender;\\n transferAllowances[src][spender] = amount;\\n emit Approval(src, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (-1 means infinite)\\n */\\n function allowance(address owner, address spender) external view returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external returns (uint) {\\n Exp memory exchangeRate = Exp({mantissa: exchangeRateCurrent()});\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n require(mErr == MathError.NO_ERROR, \\\"balance could not be calculated\\\");\\n return balance;\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view returns (uint, uint, uint, uint) {\\n uint cTokenBalance = accountTokens[account];\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), cTokenBalance, borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @dev Function to simply retrieve block number\\n * This exists mainly for inheriting test contracts to stub this result.\\n */\\n function getBlockNumber() internal view returns (uint) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this cToken\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view returns (uint) {\\n return interestRateModel.getBorrowRate(getCashPrior(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this cToken\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view returns (uint) {\\n return interestRateModel.getSupplyRate(getCashPrior(), totalBorrows, totalReserves, reserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n require(err == MathError.NO_ERROR, \\\"borrowBalanceStored: borrowBalanceStoredInternal failed\\\");\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return (error code, the calculated balance or 0 if error code is non-zero)\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the CToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n require(err == MathError.NO_ERROR, \\\"exchangeRateStored: exchangeRateStoredInternal failed\\\");\\n return result;\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the CToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return (error code, calculated exchange rate scaled by 1e18)\\n */\\n function exchangeRateStoredInternal() internal view returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows - totalReserves) / totalSupply\\n */\\n uint totalCash = getCashPrior();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Get cash balance of this cToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage.\\n */\\n function accrueInterest() public returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = getBlockNumber();\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = getCashPrior();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n require(mathErr == MathError.NO_ERROR, \\\"could not calculate block delta\\\");\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({mantissa: borrowRateMantissa}), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(Exp({mantissa: reserveFactorMantissa}), interestAccumulated, reservesPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives cTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n struct MintLocalVars {\\n Error err;\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives cTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, 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's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the cToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of cTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.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 cTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED\\\");\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\\");\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender redeems cTokens in exchange for the underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemTokens The number of cTokens to redeem into underlying\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemInternal(uint redeemTokens) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(msg.sender, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems cTokens in exchange for a specified amount of underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemAmount The amount of underlying to receive from redeeming cTokens\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemUnderlyingInternal(uint redeemAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(msg.sender, 0, redeemAmount);\\n }\\n\\n struct RedeemLocalVars {\\n Error err;\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n /**\\n * @notice User redeems cTokens in exchange for the underlying asset\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param redeemTokensIn The number of cTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming cTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemFresh(address payable redeemer, uint redeemTokensIn, uint redeemAmountIn) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr));\\n }\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(Exp({mantissa: vars.exchangeRateMantissa}), redeemTokensIn);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(redeemAmountIn, Exp({mantissa: vars.exchangeRateMantissa}));\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REDEEM_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDEEM_FRESHNESS_CHECK);\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDEEM_TRANSFER_OUT_NOT_POSSIBLE);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We invoke doTransferOut for the redeemer and the redeemAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(redeemer, vars.redeemAmount);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n /* We call the defense hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender borrows assets from the protocol to their own address\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function borrowInternal(uint borrowAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(msg.sender, borrowAmount);\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n /**\\n * @notice Users borrow assets from the protocol to their own address\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function borrowFresh(address payable borrower, uint borrowAmount) internal returns (uint) {\\n /* Fail if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.BORROW_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.BORROW_FRESHNESS_CHECK);\\n }\\n\\n /* Fail gracefully if protocol has insufficient underlying cash */\\n if (getCashPrior() < borrowAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.BORROW_CASH_NOT_AVAILABLE);\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We invoke doTransferOut for the borrower and the borrowAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(borrower, borrowAmount);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to borrower\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer the account paying off the borrow\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount the amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED\\\");\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED\\\");\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this cToken to be liquidated\\n * @param cTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) 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 = cTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, cTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this cToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param cTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowFresh(address liquidator, address borrower, uint repayAmount, CTokenInterface cTokenCollateral) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(address(this), address(cTokenCollateral), liquidator, borrower, repayAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify cTokenCollateral market's block number equals current block number */\\n if (cTokenCollateral.accrualBlockNumber() != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = -1 */\\n if (repayAmount == uint(-1)) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & 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(cTokenCollateral), actualRepayAmount);\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(cTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(cTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = cTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(cTokenCollateral), seizeTokens);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.liquidateBorrowVerify(address(this), address(cTokenCollateral), liquidator, borrower, actualRepayAmount, seizeTokens);\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another cToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed cToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of cTokens to seize\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function seize(address liquidator, address borrower, uint seizeTokens) external nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n struct SeizeInternalLocalVars {\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n uint liquidatorSeizeTokens;\\n uint protocolSeizeTokens;\\n uint protocolSeizeAmount;\\n uint exchangeRateMantissa;\\n uint totalReservesNew;\\n uint totalSupplyNew;\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another CToken.\\n * Its absolutely critical to use msg.sender as the seizer cToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed cToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of cTokens to seize\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function seizeInternal(address seizerToken, address liquidator, address borrower, uint seizeTokens) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n SeizeInternalLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (vars.mathErr, vars.borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(vars.mathErr));\\n }\\n\\n vars.protocolSeizeTokens = mul_(seizeTokens, Exp({mantissa: protocolSeizeShareMantissa}));\\n vars.liquidatorSeizeTokens = sub_(seizeTokens, vars.protocolSeizeTokens);\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n require(vars.mathErr == MathError.NO_ERROR, \\\"exchange rate math error\\\");\\n\\n vars.protocolSeizeAmount = mul_ScalarTruncate(Exp({mantissa: vars.exchangeRateMantissa}), vars.protocolSeizeTokens);\\n\\n vars.totalReservesNew = add_(totalReserves, vars.protocolSeizeAmount);\\n vars.totalSupplyNew = sub_(totalSupply, vars.protocolSeizeTokens);\\n\\n (vars.mathErr, vars.liquidatorTokensNew) = addUInt(accountTokens[liquidator], vars.liquidatorSeizeTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(vars.mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n totalReserves = vars.totalReservesNew;\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[borrower] = vars.borrowerTokensNew;\\n accountTokens[liquidator] = vars.liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, vars.liquidatorSeizeTokens);\\n emit Transfer(borrower, address(this), vars.protocolSeizeTokens);\\n emit ReservesAdded(address(this), vars.protocolSeizeAmount, vars.totalReservesNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n\\n /*** Admin Functions ***/\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPendingAdmin(address payable newPendingAdmin) external returns (uint) {\\n // Check caller = admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\\n }\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptAdmin() external returns (uint) {\\n // Check caller is pendingAdmin and pendingAdmin \\u2260 address(0)\\n if (msg.sender != pendingAdmin || msg.sender == address(0)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = address(0);\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setComptroller(ComptrollerInterface newComptroller) public returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_COMPTROLLER_OWNER_CHECK);\\n }\\n\\n ComptrollerInterface oldComptroller = comptroller;\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(oldComptroller, newComptroller);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh\\n * @dev Admin function to accrue interest and set a new reserve factor\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setReserveFactor(uint newReserveFactorMantissa) external nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\\n * @dev Admin function to set a new reserve factor\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_RESERVE_FACTOR_ADMIN_CHECK);\\n }\\n\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring from msg.sender\\n * @param addAmount Amount of addition to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to admin\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _reduceReserves(uint reduceAmount) external nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to admin\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _reduceReservesFresh(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's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n totalReservesNew = totalReserves - reduceAmount;\\n // We checked reduceAmount <= totalReserves above, so this should never revert.\\n require(totalReservesNew <= 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't be sure if side effects occurred.\\n doTransferOut(admin, reduceAmount);\\n\\n emit ReservesReduced(admin, reduceAmount, totalReservesNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Admin function to accrue interest and update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel);\\n }\\n\\n /**\\n * @notice updates the interest rate model (*requires fresh interest accrual)\\n * @dev Admin function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal returns (uint) {\\n\\n // Used to store old model for use in the event that is emitted on success\\n InterestRateModel oldInterestRateModel;\\n\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_INTEREST_RATE_MODEL_OWNER_CHECK);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Track the market's current interest rate model\\n oldInterestRateModel = interestRateModel;\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view returns (uint);\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure tather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal;\\n\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n}\\n\",\"keccak256\":\"0x436ec2e309682995f8a82dfdd9e8f75928599c10a9a680dddbee6c275014008d\"},\"contracts/CTokenInterfaces.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./InterestRateModel.sol\\\";\\nimport \\\"./EIP20NonStandardInterface.sol\\\";\\n\\ncontract CTokenStorage {\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-cToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModel public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first CTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping (address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping (address => mapping (address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Share of seized collateral that is added to reserves\\n */\\n uint public constant protocolSeizeShareMantissa = 2.8e16; //2.8%\\n\\n}\\n\\ncontract CTokenInterface is CTokenStorage {\\n /**\\n * @notice Indicator that this is a CToken contract (for inspection)\\n */\\n bool public constant isCToken = true;\\n\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(address liquidator, address borrower, uint repayAmount, address cTokenCollateral, uint seizeTokens);\\n\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin is updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(InterestRateModel oldInterestRateModel, InterestRateModel newInterestRateModel);\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address admin, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Failure event\\n */\\n event Failure(uint error, uint info, uint detail);\\n\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external returns (bool);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function approve(address spender, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function balanceOfUnderlying(address owner) external returns (uint);\\n function getAccountSnapshot(address account) external view returns (uint, uint, uint, uint);\\n function borrowRatePerBlock() external view returns (uint);\\n function supplyRatePerBlock() external view returns (uint);\\n function totalBorrowsCurrent() external returns (uint);\\n function borrowBalanceCurrent(address account) external returns (uint);\\n function borrowBalanceStored(address account) public view returns (uint);\\n function exchangeRateCurrent() public returns (uint);\\n function exchangeRateStored() public view returns (uint);\\n function getCash() external view returns (uint);\\n function accrueInterest() public returns (uint);\\n function seize(address liquidator, address borrower, uint seizeTokens) external returns (uint);\\n\\n\\n /*** Admin Functions ***/\\n\\n function _setPendingAdmin(address payable newPendingAdmin) external returns (uint);\\n function _acceptAdmin() external returns (uint);\\n function _setComptroller(ComptrollerInterface newComptroller) public returns (uint);\\n function _setReserveFactor(uint newReserveFactorMantissa) external returns (uint);\\n function _reduceReserves(uint reduceAmount) external returns (uint);\\n function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint);\\n}\\n\\ncontract CErc20Storage {\\n /**\\n * @notice Underlying asset for this CToken\\n */\\n address public underlying;\\n}\\n\\ncontract CErc20Interface is CErc20Storage {\\n\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n function redeem(uint redeemTokens) external returns (uint);\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n function borrow(uint borrowAmount) external returns (uint);\\n function repayBorrow(uint repayAmount) external returns (uint);\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n function liquidateBorrow(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) external returns (uint);\\n function sweepToken(EIP20NonStandardInterface token) external;\\n\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ncontract CDelegationStorage {\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n}\\n\\ncontract CDelegatorInterface is CDelegationStorage {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(address implementation_, bool allowResign, bytes memory becomeImplementationData) public;\\n}\\n\\ncontract CDelegateInterface is CDelegationStorage {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) public;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() public;\\n}\\n\",\"keccak256\":\"0x963bbf60b4c0b76900b3fcb2db8c8be634934b37b4113f1055e57a308197d21a\"},\"contracts/CarefulMath.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Careful Math\\n * @author Compound\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c = a * b;\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n return (MathError.NO_ERROR, a - b);\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c = a + b;\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\",\"keccak256\":\"0x0647348f27e41d22555d99eebd217dee02a4d737df6accd7cce5347a7487c7de\"},\"contracts/ComptrollerG2.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.sol\\\";\\nimport \\\"./ErrorReporter.sol\\\";\\nimport \\\"./Exponential.sol\\\";\\nimport \\\"./PriceOracle.sol\\\";\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./ComptrollerStorage.sol\\\";\\nimport \\\"./Unitroller.sol\\\";\\n\\n/**\\n * @title Compound's Comptroller Contract\\n * @author Compound\\n */\\ncontract ComptrollerG2 is ComptrollerV2Storage, ComptrollerInterface, ComptrollerErrorReporter, Exponential {\\n /**\\n * @notice Emitted when an admin supports a market\\n */\\n event MarketListed(CToken cToken);\\n\\n /**\\n * @notice Emitted when an account enters a market\\n */\\n event MarketEntered(CToken cToken, address account);\\n\\n /**\\n * @notice Emitted when an account exits a market\\n */\\n event MarketExited(CToken cToken, address account);\\n\\n /**\\n * @notice Emitted when close factor is changed by admin\\n */\\n event NewCloseFactor(uint oldCloseFactorMantissa, uint newCloseFactorMantissa);\\n\\n /**\\n * @notice Emitted when a collateral factor is changed by admin\\n */\\n event NewCollateralFactor(CToken cToken, uint oldCollateralFactorMantissa, uint newCollateralFactorMantissa);\\n\\n /**\\n * @notice Emitted when liquidation incentive is changed by admin\\n */\\n event NewLiquidationIncentive(uint oldLiquidationIncentiveMantissa, uint newLiquidationIncentiveMantissa);\\n\\n /**\\n * @notice Emitted when maxAssets is changed by admin\\n */\\n event NewMaxAssets(uint oldMaxAssets, uint newMaxAssets);\\n\\n /**\\n * @notice Emitted when price oracle is changed\\n */\\n event NewPriceOracle(PriceOracle oldPriceOracle, PriceOracle newPriceOracle);\\n\\n /**\\n * @notice Emitted when pause guardian is changed\\n */\\n event NewPauseGuardian(address oldPauseGuardian, address newPauseGuardian);\\n\\n /**\\n * @notice Emitted when an action is paused globally\\n */\\n event ActionPaused(string action, bool pauseState);\\n\\n /**\\n * @notice Emitted when an action is paused on a market\\n */\\n event ActionPaused(CToken cToken, string action, bool pauseState);\\n\\n // closeFactorMantissa must be strictly greater than this value\\n uint internal constant closeFactorMinMantissa = 0.05e18; // 0.05\\n\\n // closeFactorMantissa must not exceed this value\\n uint internal constant closeFactorMaxMantissa = 0.9e18; // 0.9\\n\\n // No collateralFactorMantissa may exceed this value\\n uint internal constant collateralFactorMaxMantissa = 0.9e18; // 0.9\\n\\n // liquidationIncentiveMantissa must be no less than this value\\n uint internal constant liquidationIncentiveMinMantissa = 1.0e18; // 1.0\\n\\n // liquidationIncentiveMantissa must be no greater than this value\\n uint internal constant liquidationIncentiveMaxMantissa = 1.5e18; // 1.5\\n\\n constructor() public {\\n admin = msg.sender;\\n }\\n\\n /*** Assets You Are In ***/\\n\\n /**\\n * @notice Returns the assets an account has entered\\n * @param account The address of the account to pull assets for\\n * @return A dynamic list with the assets the account has entered\\n */\\n function getAssetsIn(address account) external view returns (CToken[] memory) {\\n CToken[] memory assetsIn = accountAssets[account];\\n\\n return assetsIn;\\n }\\n\\n /**\\n * @notice Returns whether the given account is entered in the given asset\\n * @param account The address of the account to check\\n * @param cToken The cToken to check\\n * @return True if the account is in the asset, otherwise false.\\n */\\n function checkMembership(address account, CToken cToken) external view returns (bool) {\\n return markets[address(cToken)].accountMembership[account];\\n }\\n\\n /**\\n * @notice Add assets to be included in account liquidity calculation\\n * @param cTokens The list of addresses of the cToken markets to be enabled\\n * @return Success indicator for whether each corresponding market was entered\\n */\\n function enterMarkets(address[] memory cTokens) public returns (uint[] memory) {\\n uint len = cTokens.length;\\n\\n uint[] memory results = new uint[](len);\\n for (uint i = 0; i < len; i++) {\\n CToken cToken = CToken(cTokens[i]);\\n\\n results[i] = uint(addToMarketInternal(cToken, msg.sender));\\n }\\n\\n return results;\\n }\\n\\n /**\\n * @notice Add the market to the borrower's \\\"assets in\\\" for liquidity calculations\\n * @param cToken The market to enter\\n * @param borrower The address of the account to modify\\n * @return Success indicator for whether the market was entered\\n */\\n function addToMarketInternal(CToken cToken, address borrower) internal returns (Error) {\\n Market storage marketToJoin = markets[address(cToken)];\\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 if (accountAssets[borrower].length >= maxAssets) {\\n // no space, cannot join\\n return Error.TOO_MANY_ASSETS;\\n }\\n\\n // survived the gauntlet, add to list\\n // NOTE: we store these somewhat redundantly as a significant optimization\\n // this avoids having to iterate through the list for the most common use cases\\n // that is, only when we need to perform liquidity checks\\n // and not whenever we want to check if an account is in a particular market\\n marketToJoin.accountMembership[borrower] = true;\\n accountAssets[borrower].push(cToken);\\n\\n emit MarketEntered(cToken, borrower);\\n\\n return Error.NO_ERROR;\\n }\\n\\n /**\\n * @notice Removes asset from sender's account liquidity calculation\\n * @dev Sender must not have an outstanding borrow balance in the asset,\\n * or be providing neccessary collateral for an outstanding borrow.\\n * @param cTokenAddress The address of the asset to be removed\\n * @return Whether or not the account successfully exited the market\\n */\\n function exitMarket(address cTokenAddress) external returns (uint) {\\n CToken cToken = CToken(cTokenAddress);\\n /* Get sender tokensHeld and amountOwed underlying from the cToken */\\n (uint oErr, uint tokensHeld, uint amountOwed, ) = cToken.getAccountSnapshot(msg.sender);\\n require(oErr == 0, \\\"exitMarket: getAccountSnapshot failed\\\"); // semi-opaque error code\\n\\n /* Fail if the sender has a borrow balance */\\n if (amountOwed != 0) {\\n return fail(Error.NONZERO_BORROW_BALANCE, FailureInfo.EXIT_MARKET_BALANCE_OWED);\\n }\\n\\n /* Fail if the sender is not permitted to redeem all of their tokens */\\n uint allowed = redeemAllowedInternal(cTokenAddress, msg.sender, tokensHeld);\\n if (allowed != 0) {\\n return failOpaque(Error.REJECTION, FailureInfo.EXIT_MARKET_REJECTION, allowed);\\n }\\n\\n Market storage marketToExit = markets[address(cToken)];\\n\\n /* Return true if the sender is not already \\u2018in\\u2019 the market */\\n if (!marketToExit.accountMembership[msg.sender]) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Set cToken account membership to false */\\n delete marketToExit.accountMembership[msg.sender];\\n\\n /* Delete cToken from the account\\u2019s list of assets */\\n // load into memory for faster iteration\\n CToken[] memory userAssetList = accountAssets[msg.sender];\\n uint len = userAssetList.length;\\n uint assetIndex = len;\\n for (uint i = 0; i < len; i++) {\\n if (userAssetList[i] == cToken) {\\n assetIndex = i;\\n break;\\n }\\n }\\n\\n // We *must* have found the asset in the list or our redundant data structure is broken\\n assert(assetIndex < len);\\n\\n // copy last item in list to location of item to be removed, reduce length by 1\\n CToken[] storage storedList = accountAssets[msg.sender];\\n storedList[assetIndex] = storedList[storedList.length - 1];\\n storedList.length--;\\n\\n emit MarketExited(cToken, 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 cToken The market to verify the mint against\\n * @param minter The account which would get the minted tokens\\n * @param mintAmount The amount of underlying being supplied to the market in exchange for tokens\\n * @return 0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function mintAllowed(address cToken, address minter, uint mintAmount) external returns (uint) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n require(!mintGuardianPaused[cToken], \\\"mint is paused\\\");\\n\\n // Shh - currently unused\\n minter;\\n mintAmount;\\n\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n // *may include Policy Hook-type checks\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates mint and reverts on rejection. May emit logs.\\n * @param cToken Asset being minted\\n * @param minter The address minting the tokens\\n * @param actualMintAmount The amount of the underlying asset being minted\\n * @param mintTokens The number of tokens being minted\\n */\\n function mintVerify(address cToken, address minter, uint actualMintAmount, uint mintTokens) external {\\n // Shh - currently unused\\n cToken;\\n minter;\\n actualMintAmount;\\n mintTokens;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to redeem tokens in the given market\\n * @param cToken The market to verify the redeem against\\n * @param redeemer The account which would redeem the tokens\\n * @param redeemTokens The number of cTokens to exchange for the underlying asset in the market\\n * @return 0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function redeemAllowed(address cToken, address redeemer, uint redeemTokens) external returns (uint) {\\n return redeemAllowedInternal(cToken, redeemer, redeemTokens);\\n }\\n\\n function redeemAllowedInternal(address cToken, address redeemer, uint redeemTokens) internal view returns (uint) {\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n // *may include Policy Hook-type checks\\n\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!markets[cToken].accountMembership[redeemer]) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n (Error err, , uint shortfall) = getHypotheticalAccountLiquidityInternal(redeemer, CToken(cToken), redeemTokens, 0);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n if (shortfall > 0) {\\n return uint(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates redeem and reverts on rejection. May emit logs.\\n * @param cToken Asset being redeemed\\n * @param redeemer The address redeeming the tokens\\n * @param redeemAmount The amount of the underlying asset being redeemed\\n * @param redeemTokens The number of tokens being redeemed\\n */\\n function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) external {\\n // Shh - currently unused\\n cToken;\\n redeemer;\\n\\n // Require tokens is zero or amount is also zero\\n if (redeemTokens == 0 && redeemAmount > 0) {\\n revert(\\\"redeemTokens zero\\\");\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to borrow the underlying asset of the given market\\n * @param cToken The market to verify the borrow against\\n * @param borrower The account which would borrow the asset\\n * @param borrowAmount The amount of underlying the account would borrow\\n * @return 0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function borrowAllowed(address cToken, address borrower, uint borrowAmount) external returns (uint) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n require(!borrowGuardianPaused[cToken], \\\"borrow is paused\\\");\\n\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n // *may include Policy Hook-type checks\\n\\n if (!markets[cToken].accountMembership[borrower]) {\\n // only cTokens may call borrowAllowed if borrower not in market\\n require(msg.sender == cToken, \\\"sender must be cToken\\\");\\n\\n // attempt to add borrower to the market\\n Error err = addToMarketInternal(CToken(msg.sender), borrower);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n\\n // it should be impossible to break the important invariant\\n assert(markets[cToken].accountMembership[borrower]);\\n }\\n\\n if (oracle.getUnderlyingPrice(CToken(cToken)) == 0) {\\n return uint(Error.PRICE_ERROR);\\n }\\n\\n (Error err, , uint shortfall) = getHypotheticalAccountLiquidityInternal(borrower, CToken(cToken), 0, borrowAmount);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n if (shortfall > 0) {\\n return uint(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates borrow and reverts on rejection. May emit logs.\\n * @param cToken Asset whose underlying is being borrowed\\n * @param borrower The address borrowing the underlying\\n * @param borrowAmount The amount of the underlying asset requested to borrow\\n */\\n function borrowVerify(address cToken, address borrower, uint borrowAmount) external {\\n // Shh - currently unused\\n cToken;\\n borrower;\\n borrowAmount;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to repay a borrow in the given market\\n * @param cToken The market to verify the repay against\\n * @param payer The account which would repay the asset\\n * @param borrower The account which would borrowed the asset\\n * @param repayAmount The amount of the underlying asset the account would repay\\n * @return 0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function repayBorrowAllowed(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount) external returns (uint) {\\n // Shh - currently unused\\n payer;\\n borrower;\\n repayAmount;\\n\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n // *may include Policy Hook-type checks\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates repayBorrow and reverts on rejection. May emit logs.\\n * @param cToken Asset being repaid\\n * @param payer The address repaying the borrow\\n * @param borrower The address of the borrower\\n * @param actualRepayAmount The amount of underlying being repaid\\n */\\n function repayBorrowVerify(\\n address cToken,\\n address payer,\\n address borrower,\\n uint actualRepayAmount,\\n uint borrowerIndex) external {\\n // Shh - currently unused\\n cToken;\\n payer;\\n borrower;\\n actualRepayAmount;\\n borrowerIndex;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the liquidation should be allowed to occur\\n * @param cTokenBorrowed Asset which was borrowed by the borrower\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param repayAmount The amount of underlying being repaid\\n */\\n function liquidateBorrowAllowed(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount) external returns (uint) {\\n // Shh - currently unused\\n liquidator;\\n\\n if (!markets[cTokenBorrowed].isListed || !markets[cTokenCollateral].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n // *may include Policy Hook-type checks\\n\\n /* The borrower must have shortfall in order to be liquidatable */\\n (Error err, , uint shortfall) = getAccountLiquidityInternal(borrower);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n if (shortfall == 0) {\\n return uint(Error.INSUFFICIENT_SHORTFALL);\\n }\\n\\n /* The liquidator may not repay more than what is allowed by the closeFactor */\\n uint borrowBalance = CToken(cTokenBorrowed).borrowBalanceStored(borrower);\\n (MathError mathErr, uint maxClose) = mulScalarTruncate(Exp({mantissa: closeFactorMantissa}), borrowBalance);\\n if (mathErr != MathError.NO_ERROR) {\\n return uint(Error.MATH_ERROR);\\n }\\n if (repayAmount > 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 cTokenBorrowed Asset which was borrowed by the borrower\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param actualRepayAmount The amount of underlying being repaid\\n */\\n function liquidateBorrowVerify(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint actualRepayAmount,\\n uint seizeTokens) external {\\n // Shh - currently unused\\n cTokenBorrowed;\\n cTokenCollateral;\\n liquidator;\\n borrower;\\n actualRepayAmount;\\n seizeTokens;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the seizing of assets should be allowed to occur\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param cTokenBorrowed Asset which was borrowed by the borrower\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param seizeTokens The number of collateral tokens to seize\\n */\\n function seizeAllowed(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external returns (uint) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n require(!seizeGuardianPaused, \\\"seize is paused\\\");\\n\\n // Shh - currently unused\\n liquidator;\\n borrower;\\n seizeTokens;\\n\\n if (!markets[cTokenCollateral].isListed || !markets[cTokenBorrowed].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n if (CToken(cTokenCollateral).comptroller() != CToken(cTokenBorrowed).comptroller()) {\\n return uint(Error.COMPTROLLER_MISMATCH);\\n }\\n\\n // *may include Policy Hook-type checks\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates seize and reverts on rejection. May emit logs.\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param cTokenBorrowed Asset which was borrowed by the borrower\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param seizeTokens The number of collateral tokens to seize\\n */\\n function seizeVerify(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external {\\n // Shh - currently unused\\n cTokenCollateral;\\n cTokenBorrowed;\\n liquidator;\\n borrower;\\n seizeTokens;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to transfer tokens in the given market\\n * @param cToken The market to verify the transfer against\\n * @param src The account which sources the tokens\\n * @param dst The account which receives the tokens\\n * @param transferTokens The number of cTokens to transfer\\n * @return 0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function transferAllowed(address cToken, address src, address dst, uint transferTokens) external returns (uint) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n require(!transferGuardianPaused, \\\"transfer is paused\\\");\\n\\n // Shh - currently unused\\n dst;\\n\\n // *may include Policy Hook-type checks\\n\\n // Currently the only consideration is whether or not\\n // the src is allowed to redeem this many tokens\\n return redeemAllowedInternal(cToken, src, transferTokens);\\n }\\n\\n /**\\n * @notice Validates transfer and reverts on rejection. May emit logs.\\n * @param cToken Asset being transferred\\n * @param src The account which sources the tokens\\n * @param dst The account which receives the tokens\\n * @param transferTokens The number of cTokens to transfer\\n */\\n function transferVerify(address cToken, address src, address dst, uint transferTokens) external {\\n // Shh - currently unused\\n cToken;\\n src;\\n dst;\\n transferTokens;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n /**\\n * @dev Local vars for avoiding stack-depth limits in calculating account liquidity.\\n * Note that `cTokenBalance` is the number of cTokens the account owns in the market,\\n * whereas `borrowBalance` is the amount of underlying that the account has borrowed.\\n */\\n struct AccountLiquidityLocalVars {\\n uint sumCollateral;\\n uint sumBorrowPlusEffects;\\n uint cTokenBalance;\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n uint oraclePriceMantissa;\\n Exp collateralFactor;\\n Exp exchangeRate;\\n Exp oraclePrice;\\n Exp tokensToEther;\\n }\\n\\n /**\\n * @notice Determine the current account liquidity wrt collateral requirements\\n * @return (possible error code (semi-opaque),\\n account liquidity in excess of collateral requirements,\\n * account shortfall below collateral requirements)\\n */\\n function getAccountLiquidity(address account) public view returns (uint, uint, uint) {\\n (Error err, uint liquidity, uint shortfall) = getHypotheticalAccountLiquidityInternal(account, CToken(0), 0, 0);\\n\\n return (uint(err), liquidity, shortfall);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity wrt collateral requirements\\n * @return (possible error code,\\n account liquidity in excess of collateral requirements,\\n * account shortfall below collateral requirements)\\n */\\n function getAccountLiquidityInternal(address account) internal view returns (Error, uint, uint) {\\n return getHypotheticalAccountLiquidityInternal(account, CToken(0), 0, 0);\\n }\\n\\n /**\\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\\n * @param cTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @return (possible error code (semi-opaque),\\n hypothetical account liquidity in excess of collateral requirements,\\n * hypothetical account shortfall below collateral requirements)\\n */\\n function getHypotheticalAccountLiquidity(\\n address account,\\n address cTokenModify,\\n uint redeemTokens,\\n uint borrowAmount) public view returns (uint, uint, uint) {\\n (Error err, uint liquidity, uint shortfall) = getHypotheticalAccountLiquidityInternal(account, CToken(cTokenModify), 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 cTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @dev Note that we calculate the exchangeRateStored for each collateral cToken using stored data,\\n * without calculating accumulated interest.\\n * @return (possible error code,\\n hypothetical account liquidity in excess of collateral requirements,\\n * hypothetical account shortfall below collateral requirements)\\n */\\n function getHypotheticalAccountLiquidityInternal(\\n address account,\\n CToken cTokenModify,\\n uint redeemTokens,\\n uint borrowAmount) internal view returns (Error, uint, uint) {\\n\\n AccountLiquidityLocalVars memory vars; // Holds all our calculation results\\n uint oErr;\\n MathError mErr;\\n\\n // For each asset the account is in\\n CToken[] memory assets = accountAssets[account];\\n for (uint i = 0; i < assets.length; i++) {\\n CToken asset = assets[i];\\n\\n // Read the balances and exchange rate from the cToken\\n (oErr, vars.cTokenBalance, vars.borrowBalance, vars.exchangeRateMantissa) = asset.getAccountSnapshot(account);\\n if (oErr != 0) { // semi-opaque error code, we assume NO_ERROR == 0 is invariant between upgrades\\n return (Error.SNAPSHOT_ERROR, 0, 0);\\n }\\n vars.collateralFactor = Exp({mantissa: markets[address(asset)].collateralFactorMantissa});\\n vars.exchangeRate = Exp({mantissa: vars.exchangeRateMantissa});\\n\\n // Get the normalized price of the asset\\n vars.oraclePriceMantissa = oracle.getUnderlyingPrice(asset);\\n if (vars.oraclePriceMantissa == 0) {\\n return (Error.PRICE_ERROR, 0, 0);\\n }\\n vars.oraclePrice = Exp({mantissa: vars.oraclePriceMantissa});\\n\\n // Pre-compute a conversion factor from tokens -> ether (normalized price value)\\n (mErr, vars.tokensToEther) = mulExp3(vars.collateralFactor, vars.exchangeRate, vars.oraclePrice);\\n if (mErr != MathError.NO_ERROR) {\\n return (Error.MATH_ERROR, 0, 0);\\n }\\n\\n // sumCollateral += tokensToEther * cTokenBalance\\n (mErr, vars.sumCollateral) = mulScalarTruncateAddUInt(vars.tokensToEther, vars.cTokenBalance, 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 cTokenModify\\n if (asset == cTokenModify) {\\n // redeem effect\\n // sumBorrowPlusEffects += tokensToEther * redeemTokens\\n (mErr, vars.sumBorrowPlusEffects) = mulScalarTruncateAddUInt(vars.tokensToEther, redeemTokens, vars.sumBorrowPlusEffects);\\n if (mErr != MathError.NO_ERROR) {\\n return (Error.MATH_ERROR, 0, 0);\\n }\\n\\n // borrow effect\\n // sumBorrowPlusEffects += oraclePrice * borrowAmount\\n (mErr, vars.sumBorrowPlusEffects) = mulScalarTruncateAddUInt(vars.oraclePrice, borrowAmount, vars.sumBorrowPlusEffects);\\n if (mErr != MathError.NO_ERROR) {\\n return (Error.MATH_ERROR, 0, 0);\\n }\\n }\\n }\\n\\n // These are safe, as the underflow condition is checked first\\n if (vars.sumCollateral > vars.sumBorrowPlusEffects) {\\n return (Error.NO_ERROR, vars.sumCollateral - vars.sumBorrowPlusEffects, 0);\\n } else {\\n return (Error.NO_ERROR, 0, vars.sumBorrowPlusEffects - vars.sumCollateral);\\n }\\n }\\n\\n /**\\n * @notice Calculate number of tokens of collateral asset to seize given an underlying amount\\n * @dev Used in liquidation (called in cToken.liquidateBorrowFresh)\\n * @param cTokenBorrowed The address of the borrowed cToken\\n * @param cTokenCollateral The address of the collateral cToken\\n * @param actualRepayAmount The amount of cTokenBorrowed underlying to convert into cTokenCollateral tokens\\n * @return (errorCode, number of cTokenCollateral tokens to be seized in a liquidation)\\n */\\n function liquidateCalculateSeizeTokens(address cTokenBorrowed, address cTokenCollateral, uint actualRepayAmount) external view returns (uint, uint) {\\n /* Read oracle prices for borrowed and collateral markets */\\n uint priceBorrowedMantissa = oracle.getUnderlyingPrice(CToken(cTokenBorrowed));\\n uint priceCollateralMantissa = oracle.getUnderlyingPrice(CToken(cTokenCollateral));\\n if (priceBorrowedMantissa == 0 || priceCollateralMantissa == 0) {\\n return (uint(Error.PRICE_ERROR), 0);\\n }\\n\\n /*\\n * Get the exchange rate and calculate the number of collateral tokens to seize:\\n * seizeAmount = actualRepayAmount * liquidationIncentive * priceBorrowed / priceCollateral\\n * seizeTokens = seizeAmount / exchangeRate\\n * = actualRepayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate)\\n */\\n uint exchangeRateMantissa = CToken(cTokenCollateral).exchangeRateStored(); // Note: reverts on error\\n uint seizeTokens;\\n Exp memory numerator;\\n Exp memory denominator;\\n Exp memory ratio;\\n MathError mathErr;\\n\\n (mathErr, numerator) = mulExp(liquidationIncentiveMantissa, priceBorrowedMantissa);\\n if (mathErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0);\\n }\\n\\n (mathErr, denominator) = mulExp(priceCollateralMantissa, exchangeRateMantissa);\\n if (mathErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0);\\n }\\n\\n (mathErr, ratio) = divExp(numerator, denominator);\\n if (mathErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0);\\n }\\n\\n (mathErr, seizeTokens) = mulScalarTruncate(ratio, actualRepayAmount);\\n if (mathErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0);\\n }\\n\\n return (uint(Error.NO_ERROR), seizeTokens);\\n }\\n\\n /*** Admin Functions ***/\\n\\n /**\\n * @notice Sets a new price oracle for the comptroller\\n * @dev Admin function to set a new price oracle\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPriceOracle(PriceOracle newOracle) public returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PRICE_ORACLE_OWNER_CHECK);\\n }\\n\\n // Track the old oracle for the comptroller\\n PriceOracle oldOracle = oracle;\\n\\n // Set comptroller's oracle to newOracle\\n oracle = newOracle;\\n\\n // Emit NewPriceOracle(oldOracle, newOracle)\\n emit NewPriceOracle(oldOracle, newOracle);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets the closeFactor used when liquidating borrows\\n * @dev Admin function to set closeFactor\\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\\n * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function _setCloseFactor(uint newCloseFactorMantissa) external returns (uint256) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_CLOSE_FACTOR_OWNER_CHECK);\\n }\\n\\n Exp memory newCloseFactorExp = Exp({mantissa: newCloseFactorMantissa});\\n Exp memory lowLimit = Exp({mantissa: closeFactorMinMantissa});\\n if (lessThanOrEqualExp(newCloseFactorExp, lowLimit)) {\\n return fail(Error.INVALID_CLOSE_FACTOR, FailureInfo.SET_CLOSE_FACTOR_VALIDATION);\\n }\\n\\n Exp memory highLimit = Exp({mantissa: closeFactorMaxMantissa});\\n if (lessThanExp(highLimit, newCloseFactorExp)) {\\n return fail(Error.INVALID_CLOSE_FACTOR, FailureInfo.SET_CLOSE_FACTOR_VALIDATION);\\n }\\n\\n uint oldCloseFactorMantissa = closeFactorMantissa;\\n closeFactorMantissa = newCloseFactorMantissa;\\n emit NewCloseFactor(oldCloseFactorMantissa, closeFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets the collateralFactor for a market\\n * @dev Admin function to set per-market collateralFactor\\n * @param cToken The market to set the factor on\\n * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18\\n * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function _setCollateralFactor(CToken cToken, uint newCollateralFactorMantissa) external returns (uint256) {\\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(cToken)];\\n if (!market.isListed) {\\n return fail(Error.MARKET_NOT_LISTED, FailureInfo.SET_COLLATERAL_FACTOR_NO_EXISTS);\\n }\\n\\n Exp memory newCollateralFactorExp = Exp({mantissa: newCollateralFactorMantissa});\\n\\n // Check collateral factor <= 0.9\\n Exp memory highLimit = Exp({mantissa: collateralFactorMaxMantissa});\\n if (lessThanExp(highLimit, newCollateralFactorExp)) {\\n return fail(Error.INVALID_COLLATERAL_FACTOR, FailureInfo.SET_COLLATERAL_FACTOR_VALIDATION);\\n }\\n\\n // If collateral factor != 0, fail if price == 0\\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(cToken) == 0) {\\n return fail(Error.PRICE_ERROR, FailureInfo.SET_COLLATERAL_FACTOR_WITHOUT_PRICE);\\n }\\n\\n // Set market's collateral factor to new collateral factor, remember old value\\n uint oldCollateralFactorMantissa = market.collateralFactorMantissa;\\n market.collateralFactorMantissa = newCollateralFactorMantissa;\\n\\n // Emit event with asset, old collateral factor, and new collateral factor\\n emit NewCollateralFactor(cToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets maxAssets which controls how many markets can be entered\\n * @dev Admin function to set maxAssets\\n * @param newMaxAssets New max assets\\n * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function _setMaxAssets(uint newMaxAssets) external returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_MAX_ASSETS_OWNER_CHECK);\\n }\\n\\n uint oldMaxAssets = maxAssets;\\n maxAssets = newMaxAssets;\\n emit NewMaxAssets(oldMaxAssets, newMaxAssets);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets liquidationIncentive\\n * @dev Admin function to set liquidationIncentive\\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\\n * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function _setLiquidationIncentive(uint newLiquidationIncentiveMantissa) external returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_LIQUIDATION_INCENTIVE_OWNER_CHECK);\\n }\\n\\n // Check de-scaled min <= newLiquidationIncentive <= max\\n Exp memory newLiquidationIncentive = Exp({mantissa: newLiquidationIncentiveMantissa});\\n Exp memory minLiquidationIncentive = Exp({mantissa: liquidationIncentiveMinMantissa});\\n if (lessThanExp(newLiquidationIncentive, minLiquidationIncentive)) {\\n return fail(Error.INVALID_LIQUIDATION_INCENTIVE, FailureInfo.SET_LIQUIDATION_INCENTIVE_VALIDATION);\\n }\\n\\n Exp memory maxLiquidationIncentive = Exp({mantissa: liquidationIncentiveMaxMantissa});\\n if (lessThanExp(maxLiquidationIncentive, newLiquidationIncentive)) {\\n return fail(Error.INVALID_LIQUIDATION_INCENTIVE, FailureInfo.SET_LIQUIDATION_INCENTIVE_VALIDATION);\\n }\\n\\n // Save current value for use in log\\n uint oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa;\\n\\n // Set liquidation incentive to new incentive\\n liquidationIncentiveMantissa = newLiquidationIncentiveMantissa;\\n\\n // Emit event with old incentive, new incentive\\n emit NewLiquidationIncentive(oldLiquidationIncentiveMantissa, newLiquidationIncentiveMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Add the market to the markets mapping and set it as listed\\n * @dev Admin function to set isListed and add support for the market\\n * @param cToken The address of the market (token) to list\\n * @return uint 0=success, otherwise a failure. (See enum Error for details)\\n */\\n function _supportMarket(CToken cToken) external returns (uint) {\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SUPPORT_MARKET_OWNER_CHECK);\\n }\\n\\n if (markets[address(cToken)].isListed) {\\n return fail(Error.MARKET_ALREADY_LISTED, FailureInfo.SUPPORT_MARKET_EXISTS);\\n }\\n\\n cToken.isCToken(); // Sanity check to make sure its really a CToken\\n\\n markets[address(cToken)] = Market({isListed: true, isComped: false, collateralFactorMantissa: 0});\\n emit MarketListed(cToken);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Admin function to change the Pause Guardian\\n * @param newPauseGuardian The address of the new Pause Guardian\\n * @return uint 0=success, otherwise a failure. (See enum Error for details)\\n */\\n function _setPauseGuardian(address newPauseGuardian) public returns (uint) {\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PAUSE_GUARDIAN_OWNER_CHECK);\\n }\\n\\n // Save current value for inclusion in log\\n address oldPauseGuardian = pauseGuardian;\\n\\n // Store pauseGuardian with value newPauseGuardian\\n pauseGuardian = newPauseGuardian;\\n\\n // Emit NewPauseGuardian(OldPauseGuardian, NewPauseGuardian)\\n emit NewPauseGuardian(oldPauseGuardian, pauseGuardian);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n function _setMintPaused(CToken cToken, bool state) public returns (bool) {\\n require(markets[address(cToken)].isListed, \\\"cannot pause a market that is not listed\\\");\\n require(msg.sender == pauseGuardian || msg.sender == admin, \\\"only pause guardian and admin can pause\\\");\\n require(msg.sender == admin || state == true, \\\"only admin can unpause\\\");\\n\\n mintGuardianPaused[address(cToken)] = state;\\n emit ActionPaused(cToken, \\\"Mint\\\", state);\\n return state;\\n }\\n\\n function _setBorrowPaused(CToken cToken, bool state) public returns (bool) {\\n require(markets[address(cToken)].isListed, \\\"cannot pause a market that is not listed\\\");\\n require(msg.sender == pauseGuardian || msg.sender == admin, \\\"only pause guardian and admin can pause\\\");\\n require(msg.sender == admin || state == true, \\\"only admin can unpause\\\");\\n\\n borrowGuardianPaused[address(cToken)] = state;\\n emit ActionPaused(cToken, \\\"Borrow\\\", state);\\n return state;\\n }\\n\\n function _setTransferPaused(bool state) public returns (bool) {\\n require(msg.sender == pauseGuardian || msg.sender == admin, \\\"only pause guardian and admin can pause\\\");\\n require(msg.sender == admin || state == true, \\\"only admin can unpause\\\");\\n\\n transferGuardianPaused = state;\\n emit ActionPaused(\\\"Transfer\\\", state);\\n return state;\\n }\\n\\n function _setSeizePaused(bool state) public returns (bool) {\\n require(msg.sender == pauseGuardian || msg.sender == admin, \\\"only pause guardian and admin can pause\\\");\\n require(msg.sender == admin || state == true, \\\"only admin can unpause\\\");\\n\\n seizeGuardianPaused = state;\\n emit ActionPaused(\\\"Seize\\\", state);\\n return state;\\n }\\n\\n function _become(Unitroller unitroller) public {\\n require(msg.sender == unitroller.admin(), \\\"only unitroller admin can change brains\\\");\\n\\n uint changeStatus = unitroller._acceptImplementation();\\n require(changeStatus == 0, \\\"change not authorized\\\");\\n }\\n}\\n\",\"keccak256\":\"0xc65f8c07e0f55cc119be511c5c108b3f78d319daba3b2b54e3bc7fbcdbe89380\"},\"contracts/ComptrollerInterface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\ncontract ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n bool public constant isComptroller = true;\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata cTokens) external returns (uint[] memory);\\n function exitMarket(address cToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address cToken, address minter, uint mintAmount) external returns (uint);\\n function mintVerify(address cToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address cToken, address redeemer, uint redeemTokens) external returns (uint);\\n function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address cToken, address borrower, uint borrowAmount) external returns (uint);\\n function borrowVerify(address cToken, address borrower, uint borrowAmount) external;\\n\\n function repayBorrowAllowed(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount) external returns (uint);\\n function repayBorrowVerify(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex) external;\\n\\n function liquidateBorrowAllowed(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount) external returns (uint);\\n function liquidateBorrowVerify(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens) external;\\n\\n function seizeAllowed(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external returns (uint);\\n function seizeVerify(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external;\\n\\n function transferAllowed(address cToken, address src, address dst, uint transferTokens) external returns (uint);\\n function transferVerify(address cToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n uint repayAmount) external view returns (uint, uint);\\n}\\n\",\"keccak256\":\"0xede7670d2dd7b25d0187aecd2c28b7b5ca7d7c1bdac144fbedecf5d4bdd92a6b\"},\"contracts/ComptrollerStorage.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.sol\\\";\\nimport \\\"./PriceOracle.sol\\\";\\n\\ncontract UnitrollerAdminStorage {\\n /**\\n * @notice Administrator for this contract\\n */\\n address public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address public pendingAdmin;\\n\\n /**\\n * @notice Active brains of Unitroller\\n */\\n address public comptrollerImplementation;\\n\\n /**\\n * @notice Pending brains of Unitroller\\n */\\n address public pendingComptrollerImplementation;\\n}\\n\\ncontract ComptrollerV1Storage is UnitrollerAdminStorage {\\n\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n PriceOracle public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives\\n */\\n uint public liquidationIncentiveMantissa;\\n\\n /**\\n * @notice Max number of assets a single account can participate in (borrow or use as collateral)\\n */\\n uint public maxAssets;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\\n */\\n mapping(address => CToken[]) public accountAssets;\\n\\n}\\n\\ncontract ComptrollerV2Storage is ComptrollerV1Storage {\\n struct Market {\\n /// @notice Whether or not this market is listed\\n bool isListed;\\n\\n /**\\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\\n * For instance, 0.9 to allow borrowing 90% of collateral value.\\n * Must be between 0 and 1, and stored as a mantissa.\\n */\\n uint collateralFactorMantissa;\\n\\n /// @notice Per-market mapping of \\\"accounts in this asset\\\"\\n mapping(address => bool) accountMembership;\\n\\n /// @notice Whether or not this market receives COMP\\n bool isComped;\\n }\\n\\n /**\\n * @notice Official mapping of cTokens -> Market metadata\\n * @dev Used e.g. to determine if a market is supported\\n */\\n mapping(address => Market) public markets;\\n\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n * Actions which allow users to remove their own assets cannot be paused.\\n * Liquidation / seizing / transfer can only be paused globally, not by market.\\n */\\n address public pauseGuardian;\\n bool public _mintGuardianPaused;\\n bool public _borrowGuardianPaused;\\n bool public transferGuardianPaused;\\n bool public seizeGuardianPaused;\\n mapping(address => bool) public mintGuardianPaused;\\n mapping(address => bool) public borrowGuardianPaused;\\n}\\n\\ncontract ComptrollerV3Storage is ComptrollerV2Storage {\\n struct CompMarketState {\\n /// @notice The market's last updated compBorrowIndex or compSupplyIndex\\n uint224 index;\\n\\n /// @notice The block number the index was last updated at\\n uint32 block;\\n }\\n\\n /// @notice A list of all markets\\n CToken[] public allMarkets;\\n\\n /// @notice The rate at which the flywheel distributes COMP, per block\\n uint public compRate;\\n\\n /// @notice The portion of compRate that each market currently receives\\n mapping(address => uint) public compSpeeds;\\n\\n /// @notice The COMP market supply state for each market\\n mapping(address => CompMarketState) public compSupplyState;\\n\\n /// @notice The COMP market borrow state for each market\\n mapping(address => CompMarketState) public compBorrowState;\\n\\n /// @notice The COMP borrow index for each market for each supplier as of the last time they accrued COMP\\n mapping(address => mapping(address => uint)) public compSupplierIndex;\\n\\n /// @notice The COMP borrow index for each market for each borrower as of the last time they accrued COMP\\n mapping(address => mapping(address => uint)) public compBorrowerIndex;\\n\\n /// @notice The COMP accrued but not yet transferred to each user\\n mapping(address => uint) public compAccrued;\\n}\\n\\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\\n // @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\\n address public borrowCapGuardian;\\n\\n // @notice Borrow caps enforced by borrowAllowed for each cToken address. Defaults to zero which corresponds to unlimited borrowing.\\n mapping(address => uint) public borrowCaps;\\n}\\n\\ncontract ComptrollerV5Storage is ComptrollerV4Storage {\\n /// @notice The portion of COMP that each contributor receives per block\\n mapping(address => uint) public compContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's COMP rewards have been allocated\\n mapping(address => uint) public lastContributorBlock;\\n}\\n\",\"keccak256\":\"0x5db970485549f493618b5e36bfd4d799d4f8701a136bf71ed6e0117e1ed8c254\"},\"contracts/EIP20Interface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title ERC 20 Token Standard Interface\\n * https://eips.ethereum.org/EIPS/eip-20\\n */\\ninterface EIP20Interface {\\n function name() external view returns (string memory);\\n function symbol() external view returns (string memory);\\n function decimals() external view returns (uint8);\\n\\n /**\\n * @notice Get the total number of tokens in circulation\\n * @return The supply of tokens\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @notice Gets the balance of the specified address\\n * @param owner The address from which the balance will be retrieved\\n * @return The balance\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transfer(address dst, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferFrom(address src, address dst, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (-1 means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (-1 means infinite)\\n */\\n function allowance(address owner, address spender) external view returns (uint256 remaining);\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n}\\n\",\"keccak256\":\"0xfd8ed2eac6d0b4d9ee6b32628ba68bae17544b66f190a5f7ce0c6ad024579dc8\"},\"contracts/EIP20NonStandardInterface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title EIP20NonStandardInterface\\n * @dev Version of ERC20 with no return values for `transfer` and `transferFrom`\\n * See https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\\n */\\ninterface EIP20NonStandardInterface {\\n\\n /**\\n * @notice Get the total number of tokens in circulation\\n * @return The supply of tokens\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @notice Gets the balance of the specified address\\n * @param owner The address from which the balance will be retrieved\\n * @return The balance\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n ///\\n /// !!!!!!!!!!!!!!\\n /// !!! NOTICE !!! `transfer` does not return a value, in violation of the ERC-20 specification\\n /// !!!!!!!!!!!!!!\\n ///\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n */\\n function transfer(address dst, uint256 amount) external;\\n\\n ///\\n /// !!!!!!!!!!!!!!\\n /// !!! NOTICE !!! `transferFrom` does not return a value, in violation of the ERC-20 specification\\n /// !!!!!!!!!!!!!!\\n ///\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n */\\n function transferFrom(address src, address dst, uint256 amount) external;\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent\\n */\\n function allowance(address owner, address spender) external view returns (uint256 remaining);\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n}\\n\",\"keccak256\":\"0x9719f12e4b80b51147ac195553a198cf8b0c516e7e4d04fc324a23ed15cbafb2\"},\"contracts/ErrorReporter.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\ncontract ComptrollerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\",\"keccak256\":\"0x5179afb1071c0fd555e5c1f1d2565f72dbe1740cc3dd02f6e52037f150afc5c9\"},\"contracts/Exponential.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CarefulMath.sol\\\";\\nimport \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @dev Legacy contract for compatibility reasons with existing contracts that still use MathError\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: rational}));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({mantissa: result}));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({mantissa: result}));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: scaledMantissa}));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: descaledMantissa}));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) pure internal returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({mantissa: 0}));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({mantissa: product}));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) pure internal returns (MathError, Exp memory) {\\n return mulExp(Exp({mantissa: a}), Exp({mantissa: b}));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) pure internal returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6ff054d65a0289dbb43c9f437d6909f9cf1207c9b8f984b3cb8e97a9de76a434\"},\"contracts/ExponentialNoError.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\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 Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) pure internal returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) pure internal returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) pure internal returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) pure internal returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) pure internal returns (uint224) {\\n require(n < 2**224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) pure internal returns (uint32) {\\n require(n < 2**32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: add_(a.mantissa, b.mantissa)});\\n }\\n\\n function add_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: add_(a.mantissa, b.mantissa)});\\n }\\n\\n function add_(uint a, uint b) pure internal returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: sub_(a.mantissa, b.mantissa)});\\n }\\n\\n function sub_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: sub_(a.mantissa, b.mantissa)});\\n }\\n\\n function sub_(uint a, uint b) pure internal returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: mul_(a.mantissa, b.mantissa) / expScale});\\n }\\n\\n function mul_(Exp memory a, uint b) pure internal returns (Exp memory) {\\n return Exp({mantissa: mul_(a.mantissa, b)});\\n }\\n\\n function mul_(uint a, Exp memory b) pure internal returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: mul_(a.mantissa, b.mantissa) / doubleScale});\\n }\\n\\n function mul_(Double memory a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: mul_(a.mantissa, b)});\\n }\\n\\n function mul_(uint a, Double memory b) pure internal returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) pure internal returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) pure internal 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) pure internal returns (Exp memory) {\\n return Exp({mantissa: div_(mul_(a.mantissa, expScale), b.mantissa)});\\n }\\n\\n function div_(Exp memory a, uint b) pure internal returns (Exp memory) {\\n return Exp({mantissa: div_(a.mantissa, b)});\\n }\\n\\n function div_(uint a, Exp memory b) pure internal returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa)});\\n }\\n\\n function div_(Double memory a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(a.mantissa, b)});\\n }\\n\\n function div_(uint a, Double memory b) pure internal returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) pure internal returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(mul_(a, doubleScale), b)});\\n }\\n}\\n\",\"keccak256\":\"0x7cb184b7cee71a5e707053dfba7eebbd46f11974004028100510ccce19b6694d\"},\"contracts/InterestRateModel.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Compound's InterestRateModel Interface\\n * @author Compound\\n */\\ncontract InterestRateModel {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint cash, uint borrows, uint reserves) external view returns (uint);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) external view returns (uint);\\n\\n}\\n\",\"keccak256\":\"0x929282d73c79e6d700ebe79f9fafc1e414b3848acff5a56d6740afd1dc908678\"},\"contracts/PriceOracle.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.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 cToken asset\\n * @param cToken The cToken to get the underlying price of\\n * @return The underlying asset price mantissa (scaled by 1e18).\\n * Zero means the price is unavailable.\\n */\\n function getUnderlyingPrice(CToken cToken) external view returns (uint);\\n}\\n\",\"keccak256\":\"0xe79ebc23bba508eb2479e7b3340abf566da1ab62131f106aee1aac3dc53816ef\"},\"contracts/Unitroller.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ErrorReporter.sol\\\";\\nimport \\\"./ComptrollerStorage.sol\\\";\\n/**\\n * @title ComptrollerCore\\n * @dev Storage for the comptroller is at this address, while execution is delegated to the `comptrollerImplementation`.\\n * CTokens should reference this contract as their comptroller.\\n */\\ncontract Unitroller is UnitrollerAdminStorage, ComptrollerErrorReporter {\\n\\n /**\\n * @notice Emitted when pendingComptrollerImplementation is changed\\n */\\n event NewPendingImplementation(address oldPendingImplementation, address newPendingImplementation);\\n\\n /**\\n * @notice Emitted when pendingComptrollerImplementation is accepted, which means comptroller implementation is updated\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Emitted when pendingAdmin is accepted, which means admin is updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n constructor() public {\\n // Set admin to caller\\n admin = msg.sender;\\n }\\n\\n /*** Admin Functions ***/\\n function _setPendingImplementation(address newPendingImplementation) public returns (uint) {\\n\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_IMPLEMENTATION_OWNER_CHECK);\\n }\\n\\n address oldPendingImplementation = pendingComptrollerImplementation;\\n\\n pendingComptrollerImplementation = newPendingImplementation;\\n\\n emit NewPendingImplementation(oldPendingImplementation, pendingComptrollerImplementation);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts new implementation of comptroller. msg.sender must be pendingImplementation\\n * @dev Admin function for new implementation to accept it's role as implementation\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptImplementation() public returns (uint) {\\n // Check caller is pendingImplementation and pendingImplementation \\u2260 address(0)\\n if (msg.sender != pendingComptrollerImplementation || pendingComptrollerImplementation == address(0)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldImplementation = comptrollerImplementation;\\n address oldPendingImplementation = pendingComptrollerImplementation;\\n\\n comptrollerImplementation = pendingComptrollerImplementation;\\n\\n pendingComptrollerImplementation = address(0);\\n\\n emit NewImplementation(oldImplementation, comptrollerImplementation);\\n emit NewPendingImplementation(oldPendingImplementation, pendingComptrollerImplementation);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPendingAdmin(address newPendingAdmin) public returns (uint) {\\n // Check caller = admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\\n }\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptAdmin() public returns (uint) {\\n // Check caller is pendingAdmin and pendingAdmin \\u2260 address(0)\\n if (msg.sender != pendingAdmin || msg.sender == address(0)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = address(0);\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return 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 () payable external {\\n // delegate all other functions to current implementation\\n (bool success, ) = comptrollerImplementation.delegatecall(msg.data);\\n\\n assembly {\\n let free_mem_ptr := mload(0x40)\\n returndatacopy(free_mem_ptr, 0, returndatasize)\\n\\n switch success\\n case 0 { revert(free_mem_ptr, returndatasize) }\\n default { return(free_mem_ptr, returndatasize) }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x51f81451eab9d5c4849507e724f2b2c53e41f54e5359fdbeae89432a727c16df\"}},\"version\":1}" + }, + "contracts/ComptrollerG3.sol:ComptrollerG3": { + "abi": "[{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"action\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"pauseState\",\"type\":\"bool\"}],\"name\":\"ActionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"action\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"pauseState\",\"type\":\"bool\"}],\"name\":\"ActionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSpeed\",\"type\":\"uint256\"}],\"name\":\"CompSpeedUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compBorrowIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedBorrowerComp\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"supplier\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compSupplyIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedSupplierComp\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isComped\",\"type\":\"bool\"}],\"name\":\"MarketComped\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketEntered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketExited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"MarketListed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCloseFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCloseFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCollateralFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCollateralFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCompRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCompRate\",\"type\":\"uint256\"}],\"name\":\"NewCompRate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldLiquidationIncentiveMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"NewLiquidationIncentive\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMaxAssets\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMaxAssets\",\"type\":\"uint256\"}],\"name\":\"NewMaxAssets\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldPauseGuardian\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"NewPauseGuardian\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"oldPriceOracle\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"newPriceOracle\",\"type\":\"address\"}],\"name\":\"NewPriceOracle\",\"type\":\"event\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"_addCompMarkets\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract Unitroller\",\"name\":\"unitroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"compRate_\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"compMarketsToAdd\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"otherMarketsToAdd\",\"type\":\"address[]\"}],\"name\":\"_become\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"compRate_\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"compMarketsToAdd\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"otherMarketsToAdd\",\"type\":\"address[]\"}],\"name\":\"_becomeG3\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"_dropCompMarket\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setBorrowPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCloseFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCollateralFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"compRate_\",\"type\":\"uint256\"}],\"name\":\"_setCompRate\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"_setLiquidationIncentive\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newMaxAssets\",\"type\":\"uint256\"}],\"name\":\"_setMaxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setMintPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"_setPauseGuardian\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"newOracle\",\"type\":\"address\"}],\"name\":\"_setPriceOracle\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setSeizePaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setTransferPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"_supportMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allMarkets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"checkMembership\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"},{\"internalType\":\"contract CToken[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"holders\",\"type\":\"address[]\"},{\"internalType\":\"contract CToken[]\",\"name\":\"cTokens\",\"type\":\"address[]\"},{\"internalType\":\"bool\",\"name\":\"borrowers\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"suppliers\",\"type\":\"bool\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compAccrued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compBorrowState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compBorrowerIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compClaimThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compInitialIndex\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSupplierIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSupplyState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"enterMarkets\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenAddress\",\"type\":\"address\"}],\"name\":\"exitMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getAllMarkets\",\"outputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAssetsIn\",\"outputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getCompAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenModify\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"getHypotheticalAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"isComptroller\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateCalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"liquidationIncentiveMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"markets\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isComped\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"mintAmount\",\"type\":\"uint256\"}],\"name\":\"mintAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualMintAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"mintTokens\",\"type\":\"uint256\"}],\"name\":\"mintVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"refreshCompSpeeds\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"repayBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowerIndex\",\"type\":\"uint256\"}],\"name\":\"repayBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"seizeGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"transferGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + "bin": "608060405234801561001057600080fd5b50600080546001600160a01b03191633179055615e9980620000336000396000f3fe608060405234801561001057600080fd5b50600436106104275760003560e01c8063747026c91161022b578063bdcdc25811610130578063dce15449116100b8578063e875544611610087578063e875544614611311578063e9af029214611319578063eabe7d911461133f578063ede4edd014611375578063f851a4401461139b57610427565b8063dce15449146112a9578063dcfbc0c7146112d5578063e4028eee146112dd578063e6653f3d1461130957610427565b8063cc7ebdc4116100ff578063cc7ebdc414611149578063ce485c5e1461116f578063d02f735114611210578063d9226ced14611256578063da3d454c1461127357610427565b8063bdcdc25814610fef578063c29982381461102b578063c488847b146110cc578063ca0af0431461111b57610427565b80639d1b5a0a116101b3578063abfceffc11610182578063abfceffc14610f33578063ac0b0bb714610fa9578063b0772d0b14610fb1578063b21be7fd14610fb9578063bb82aa5e14610fe757610427565b80639d1b5a0a14610ed9578063a76b3fda14610ee1578063a7f0e23114610f07578063aa90075414610f2b57610427565b80638e8f294b116101fa5780638e8f294b14610d045780638ebf636414610d4c578063929fe9a114610d6b57806394b2294b14610d99578063992c529414610da157610427565b8063747026c914610cc65780637dc0d1d014610cce57806387f7630314610cd65780638c57804e14610cde57610427565b80634d8e5037116103315780635f5af1aa116102b95780636a56947e116102885780636a56947e14610baa5780636b79c38d14610be65780636d154ea514610c345780636d35bf9114610c5a578063731f0c2b14610ca057610427565b80635f5af1aa146109f55780635fc7e71e14610a1b5780636810dfa614610a615780636a49111214610b8d57610427565b806351dff9891161030057806351dff9891461091a57806352d84d1e1461095657806355ee1fe1146109735780635c778605146109995780635ec88c79146109cf57610427565b80634d8e5037146108655780634e79238f1461086d5780634ef4c3e1146108c75780634fd42e17146108fd57610427565b80632d70db78116103b45780633c94786f116103835780633c94786f146107c557806341c728b9146107cd57806342cbb15c1461080957806347ef3b3b146108115780634ada90af1461085d57610427565b80632d70db7814610735578063317b0b77146107545780633aa729b4146107715780633bcf7ec11461079757610427565b80631ededc91116103fb5780631ededc91146105615780632327c7df146105a357806324008a62146106cd57806324a3d62214610709578063267822471461072d57610427565b80627e3dd21461042c57806318c882a5146104485780631c3db2e0146104765780631d7b33d714610529575b600080fd5b6104346113a3565b604080519115158252519081900360200190f35b6104346004803603604081101561045e57600080fd5b506001600160a01b03813516906020013515156113a8565b6105276004803603604081101561048c57600080fd5b6001600160a01b038235169190810190604081016020820135600160201b8111156104b657600080fd5b8201836020820111156104c857600080fd5b803590602001918460208302840111600160201b831117156104e957600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550611548945050505050565b005b61054f6004803603602081101561053f57600080fd5b50356001600160a01b03166115aa565b60408051918252519081900360200190f35b610527600480360360a081101561057757600080fd5b506001600160a01b038135811691602081013582169160408201351690606081013590608001356115bc565b610527600480360360608110156105b957600080fd5b81359190810190604081016020820135600160201b8111156105da57600080fd5b8201836020820111156105ec57600080fd5b803590602001918460208302840111600160201b8311171561060d57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b81111561065c57600080fd5b82018360208201111561066e57600080fd5b803590602001918460208302840111600160201b8311171561068f57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295506115c3945050505050565b61054f600480360360808110156106e357600080fd5b506001600160a01b03813581169160208101358216916040820135169060600135611689565b610711611752565b604080516001600160a01b039092168252519081900360200190f35b610711611761565b6104346004803603602081101561074b57600080fd5b50351515611770565b61054f6004803603602081101561076a57600080fd5b50356118aa565b6105276004803603602081101561078757600080fd5b50356001600160a01b03166119bb565b610434600480360360408110156107ad57600080fd5b506001600160a01b0381351690602001351515611aec565b610434611c87565b610527600480360360808110156107e357600080fd5b506001600160a01b03813581169160208101359091169060408101359060600135611c97565b61054f611c9d565b610527600480360360c081101561082757600080fd5b506001600160a01b0381358116916020810135821691604082013581169160608101359091169060808101359060a00135611ca2565b61054f611caa565b610527611cb0565b6108a96004803603608081101561088357600080fd5b506001600160a01b03813581169160208101359091169060408101359060600135612102565b60408051938452602084019290925282820152519081900360600190f35b61054f600480360360608110156108dd57600080fd5b506001600160a01b0381358116916020810135909116906040013561213c565b61054f6004803603602081101561091357600080fd5b50356121e7565b6105276004803603608081101561093057600080fd5b506001600160a01b038135811691602081013590911690604081013590606001356122db565b6107116004803603602081101561096c57600080fd5b503561232f565b61054f6004803603602081101561098957600080fd5b50356001600160a01b0316612356565b610527600480360360608110156109af57600080fd5b506001600160a01b038135811691602081013590911690604001356123dd565b6108a9600480360360208110156109e557600080fd5b50356001600160a01b03166123e2565b61054f60048036036020811015610a0b57600080fd5b50356001600160a01b0316612417565b61054f600480360360a0811015610a3157600080fd5b506001600160a01b038135811691602081013582169160408201358116916060810135909116906080013561249b565b61052760048036036080811015610a7757600080fd5b810190602081018135600160201b811115610a9157600080fd5b820183602082011115610aa357600080fd5b803590602001918460208302840111600160201b83111715610ac457600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b811115610b1357600080fd5b820183602082011115610b2557600080fd5b803590602001918460208302840111600160201b83111715610b4657600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550505050803515159150602001351515612622565b61052760048036036020811015610ba357600080fd5b50356127cb565b61052760048036036080811015610bc057600080fd5b506001600160a01b03813581169160208101358216916040820135169060600135611c97565b610c0c60048036036020811015610bfc57600080fd5b50356001600160a01b031661286f565b604080516001600160e01b03909316835263ffffffff90911660208301528051918290030190f35b61043460048036036020811015610c4a57600080fd5b50356001600160a01b0316612899565b610527600480360360a0811015610c7057600080fd5b506001600160a01b03813581169160208101358216916040820135811691606081013590911690608001356115bc565b61043460048036036020811015610cb657600080fd5b50356001600160a01b03166128ae565b61054f6128c3565b6107116128ce565b6104346128dd565b610c0c60048036036020811015610cf457600080fd5b50356001600160a01b03166128ed565b610d2a60048036036020811015610d1a57600080fd5b50356001600160a01b0316612917565b6040805193151584526020840192909252151582820152519081900360600190f35b61043460048036036020811015610d6257600080fd5b5035151561293d565b61043460048036036040811015610d8157600080fd5b506001600160a01b0381358116916020013516612a76565b61054f612aa9565b61052760048036036080811015610db757600080fd5b6001600160a01b0382351691602081013591810190606081016040820135600160201b811115610de657600080fd5b820183602082011115610df857600080fd5b803590602001918460208302840111600160201b83111715610e1957600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b811115610e6857600080fd5b820183602082011115610e7a57600080fd5b803590602001918460208302840111600160201b83111715610e9b57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550612aaf945050505050565b610711612cfb565b61054f60048036036020811015610ef757600080fd5b50356001600160a01b0316612d13565b610f0f612e70565b604080516001600160e01b039092168252519081900360200190f35b61054f612e83565b610f5960048036036020811015610f4957600080fd5b50356001600160a01b0316612e89565b60408051602080825283518183015283519192839290830191858101910280838360005b83811015610f95578181015183820152602001610f7d565b505050509050019250505060405180910390f35b610434612f12565b610f59612f22565b61054f60048036036040811015610fcf57600080fd5b506001600160a01b0381358116916020013516612f84565b610711612fa1565b61054f6004803603608081101561100557600080fd5b506001600160a01b03813581169160208101358216916040820135169060600135612fb0565b610f596004803603602081101561104157600080fd5b810190602081018135600160201b81111561105b57600080fd5b82018360208201111561106d57600080fd5b803590602001918460208302840111600160201b8311171561108e57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550613044945050505050565b611102600480360360608110156110e257600080fd5b506001600160a01b038135811691602081013590911690604001356130db565b6040805192835260208301919091528051918290030190f35b61054f6004803603604081101561113157600080fd5b506001600160a01b0381358116916020013516613350565b61054f6004803603602081101561115f57600080fd5b50356001600160a01b031661336d565b6105276004803603602081101561118557600080fd5b810190602081018135600160201b81111561119f57600080fd5b8201836020820111156111b157600080fd5b803590602001918460208302840111600160201b831117156111d257600080fd5b91908080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525092955061337f945050505050565b61054f600480360360a081101561122657600080fd5b506001600160a01b0381358116916020810135821691604082013581169160608101359091169060800135613414565b61054f6004803603602081101561126c57600080fd5b50356135cc565b61054f6004803603606081101561128957600080fd5b506001600160a01b03813581169160208101359091169060400135613635565b610711600480360360408110156112bf57600080fd5b506001600160a01b038135169060200135613922565b610711613957565b61054f600480360360408110156112f357600080fd5b506001600160a01b038135169060200135613966565b610434613b16565b61054f613b26565b6105276004803603602081101561132f57600080fd5b50356001600160a01b0316613b2c565b61054f6004803603606081101561135557600080fd5b506001600160a01b03813581169160208101359091169060400135613b90565b61054f6004803603602081101561138b57600080fd5b50356001600160a01b0316613bcd565b610711613ee0565b600181565b6001600160a01b03821660009081526009602052604081205460ff166113ff5760405162461bcd60e51b8152600401808060200182810382526028815260200180615daa6028913960400191505060405180910390fd5b600a546001600160a01b031633148061142257506000546001600160a01b031633145b61145d5760405162461bcd60e51b8152600401808060200182810382526027815260200180615dd26027913960400191505060405180910390fd5b6000546001600160a01b031633148061147857506001821515145b6114c2576040805162461bcd60e51b81526020600482015260166024820152756f6e6c792061646d696e2063616e20756e706175736560501b604482015290519081900360640190fd5b6001600160a01b0383166000818152600c6020908152604091829020805486151560ff199091168117909155825193845283830152606090830181905260069083015265426f72726f7760d01b6080830152517f71aec636243f9709bb0007ae15e9afb8150ab01716d75fd7573be5cc096e03b09181900360a00190a150805b92915050565b60408051600180825281830190925260609160208083019080388339019050509050828160008151811061157857fe5b60200260200101906001600160a01b031690816001600160a01b0316815250506115a58183600180612622565b505050565b600f6020526000908152604090205481565b5050505050565b6002546001600160a01b03163314611622576040805162461bcd60e51b815260206004820152601d60248201527f6f6e6c7920627261696e732063616e206265636f6d6520697473656c66000000604482015290519081900360640190fd5b60005b82518110156116525761164a83828151811061163d57fe5b6020026020010151613eef565b600101611625565b5060005b81518110156116765761166e82828151811061163d57fe5b600101611656565b50611680836127cb565b6115a58261337f565b6001600160a01b03841660009081526009602052604081205460ff166116b15750600961174a565b6116b9615cea565b6040518060200160405280876001600160a01b031663aa5af0fd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156116fd57600080fd5b505afa158015611711573d6000803e3d6000fd5b505050506040513d602081101561172757600080fd5b5051905290506117378682613fcd565b6117448685836000614255565b60009150505b949350505050565b600a546001600160a01b031681565b6001546001600160a01b031681565b600a546000906001600160a01b031633148061179657506000546001600160a01b031633145b6117d15760405162461bcd60e51b8152600401808060200182810382526027815260200180615dd26027913960400191505060405180910390fd5b6000546001600160a01b03163314806117ec57506001821515145b611836576040805162461bcd60e51b81526020600482015260166024820152756f6e6c792061646d696e2063616e20756e706175736560501b604482015290519081900360640190fd5b600a8054831515600160b81b810260ff60b81b1990921691909117909155604080516020810192909252808252600582820152645365697a6560d81b6060830152517fef159d9a32b2472e32b098f954f3ce62d232939f1c207070b584df1814de2de09181900360800190a150805b919050565b600080546001600160a01b031633146118d0576118c960016004614440565b90506118a5565b6118d8615cea565b5060408051602081019091528281526118ef615cea565b50604080516020810190915266b1a2bc2ec50000815261190f82826144a6565b156119285761191f600580614440565b925050506118a5565b611930615cea565b506040805160208101909152670c7d713b49da0000815261195181846144ae565b1561196b57611961600580614440565b93505050506118a5565b6005805490869055604080518281526020810188905281517f3b9670cf975d26958e754b57098eaa2ac914d8d2a31b83257997b9f346110fd9929181900390910190a160005b9695505050505050565b6000546001600160a01b03163314611a1a576040805162461bcd60e51b815260206004820152601f60248201527f6f6e6c792061646d696e2063616e2064726f7020636f6d70206d61726b657400604482015290519081900360640190fd5b6001600160a01b0381166000908152600960205260409020600381015460ff161515600114611a90576040805162461bcd60e51b815260206004820152601b60248201527f6d61726b6574206973206e6f74206120636f6d70206d61726b65740000000000604482015290519081900360640190fd5b60038101805460ff19169055604080516001600160a01b03841681526000602082015281517f93c1f3e36ed71139f466a4ce8c9751790e2e33f5afb2df0dcfb3aeabe55d5aa2929181900390910190a1611ae8611cb0565b5050565b6001600160a01b03821660009081526009602052604081205460ff16611b435760405162461bcd60e51b8152600401808060200182810382526028815260200180615daa6028913960400191505060405180910390fd5b600a546001600160a01b0316331480611b6657506000546001600160a01b031633145b611ba15760405162461bcd60e51b8152600401808060200182810382526027815260200180615dd26027913960400191505060405180910390fd5b6000546001600160a01b0316331480611bbc57506001821515145b611c06576040805162461bcd60e51b81526020600482015260166024820152756f6e6c792061646d696e2063616e20756e706175736560501b604482015290519081900360640190fd5b6001600160a01b0383166000818152600b6020908152604091829020805486151560ff199091168117909155825193845283830152606090830181905260049083015263135a5b9d60e21b6080830152517f71aec636243f9709bb0007ae15e9afb8150ab01716d75fd7573be5cc096e03b09181900360a00190a150919050565b600a54600160a01b900460ff1681565b50505050565b435b90565b505050505050565b60065481565b6060600d805480602002602001604051908101604052809291908181526020018280548015611d0857602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611cea575b50939450600093505050505b8151811015611dce576000828281518110611d2b57fe5b60200260200101519050611d3d615cea565b6040518060200160405280836001600160a01b031663aa5af0fd6040518163ffffffff1660e01b815260040160206040518083038186803b158015611d8157600080fd5b505afa158015611d95573d6000803e3d6000fd5b505050506040513d6020811015611dab57600080fd5b505190529050611dba826144b5565b611dc48282613fcd565b5050600101611d14565b50611dd7615cea565b60405180602001604052806000815250905060608251604051908082528060200260200182016040528015611e2657816020015b611e13615cea565b815260200190600190039081611e0b5790505b50905060005b8351811015612039576000848281518110611e4357fe5b6020908102919091018101516001600160a01b0381166000908152600990925260409091206003015490915060ff161561203057611e7f615cea565b60408051602080820180845260045463fc57d4df60e01b9091526001600160a01b03868116602485015293519293849391169163fc57d4df916044808601929190818703018186803b158015611ed457600080fd5b505afa158015611ee8573d6000803e3d6000fd5b505050506040513d6020811015611efe57600080fd5b505190529050611f0c615cea565b611ff26040518060200160405280856001600160a01b031663f8f9da286040518163ffffffff1660e01b815260040160206040518083038186803b158015611f5357600080fd5b505afa158015611f67573d6000803e3d6000fd5b505050506040513d6020811015611f7d57600080fd5b50519052604080516308f7a6e360e31b815290516001600160a01b038716916347bd3718916004808301926020929190829003018186803b158015611fc157600080fd5b505afa158015611fd5573d6000803e3d6000fd5b505050506040513d6020811015611feb57600080fd5b5051614733565b9050611ffc615cea565b612006828461475d565b90508086868151811061201557fe5b602002602001018190525061202a878261479c565b96505050505b50600101611e2c565b5060005b8351811015611c97576000600d828154811061205557fe5b600091825260208220015485516001600160a01b03909116925061207a5760006120a2565b6120a2600e5461209d86868151811061208f57fe5b6020026020010151886147c1565b6147f4565b6001600160a01b0383166000818152600f60209081526040918290208490558151848152915193945091927f2ab93f65628379309f36cb125e90d7c902454a545c4f8b8cb0794af75c24b807929181900390910190a2505060010161203d565b6000806000806000806121178a8a8a8a61481c565b92509250925082601181111561212957fe5b95509093509150505b9450945094915050565b6001600160a01b0383166000908152600b602052604081205460ff161561219b576040805162461bcd60e51b815260206004820152600e60248201526d1b5a5b9d081a5cc81c185d5cd95960921b604482015290519081900360640190fd5b6001600160a01b03841660009081526009602052604090205460ff166121c55760095b90506121e0565b6121ce846144b5565b6121da84846000614c37565b60005b90505b9392505050565b600080546001600160a01b03163314612206576118c96001600b614440565b61220e615cea565b506040805160208101909152828152612225615cea565b506040805160208101909152670de0b6b3a7640000815261224682826144ae565b156122575761191f6007600c614440565b61225f615cea565b5060408051602081019091526714d1120d7b160000815261228081846144ae565b15612291576119616007600c614440565b6006805490869055604080518281526020810188905281517faeba5a6c40a8ac138134bff1aaa65debf25971188a58804bad717f82f0ec1316929181900390910190a160006119b1565b801580156122e95750600082115b15611c97576040805162461bcd60e51b815260206004820152601160248201527072656465656d546f6b656e73207a65726f60781b604482015290519081900360640190fd5b600d818154811061233c57fe5b6000918252602090912001546001600160a01b0316905081565b600080546001600160a01b03163314612375576118c960016010614440565b600480546001600160a01b038481166001600160a01b0319831681179093556040805191909216808252602082019390935281517fd52b2b9b7e9ee655fcb95d2e5b9e0c9f69e7ef2b8e9d2d0ea78402d576d22e22929181900390910190a160009392505050565b6115a5565b6000806000806000806123f987600080600061481c565b92509250925082601181111561240b57fe5b97919650945092505050565b600080546001600160a01b03163314612436576118c960016013614440565b600a80546001600160a01b038481166001600160a01b0319831617928390556040805192821680845293909116602083015280517f0613b6ee6a04f0d09f390e4d9318894b9f6ac7fd83897cd8d18896ba579c401e9281900390910190a160006121e0565b6001600160a01b03851660009081526009602052604081205460ff1615806124dc57506001600160a01b03851660009081526009602052604090205460ff16155b156124eb5760095b9050612619565b6000806124f785614e2f565b9193509091506000905082601181111561250d57fe5b146125275781601181111561251e57fe5b92505050612619565b8061253357600361251e565b6000886001600160a01b03166395dd9193876040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561258b57600080fd5b505afa15801561259f573d6000803e3d6000fd5b505050506040513d60208110156125b557600080fd5b50516040805160208101909152600554815290915060009081906125d99084614e4f565b909250905060008260038111156125ec57fe5b1461260057600b5b95505050505050612619565b8087111561260f5760116125f4565b6000955050505050505b95945050505050565b60005b83518110156115bc57600084828151811061263c57fe5b6020908102919091018101516001600160a01b0381166000908152600990925260409091205490915060ff166126b1576040805162461bcd60e51b81526020600482015260156024820152741b585c9ad95d081b5d5cdd081899481b1a5cdd1959605a1b604482015290519081900360640190fd5b60018415151415612779576126c4615cea565b6040518060200160405280836001600160a01b031663aa5af0fd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561270857600080fd5b505afa15801561271c573d6000803e3d6000fd5b505050506040513d602081101561273257600080fd5b5051905290506127428282613fcd565b60005b87518110156127765761276e8389838151811061275e57fe5b6020026020010151846001614255565b600101612745565b50505b600183151514156127c25761278d816144b5565b60005b86518110156127c0576127b8828883815181106127a957fe5b60200260200101516001614c37565b600101612790565b505b50600101612625565b6127d3614ea3565b612824576040805162461bcd60e51b815260206004820152601f60248201527f6f6e6c792061646d696e2063616e206368616e676520636f6d70207261746500604482015290519081900360640190fd5b600e805490829055604080518281526020810184905281517fc227c9272633c3a307d9845bf2bc2509cefb20d655b5f3c1002d8e1e3f22c8b0929181900390910190a1611ae8611cb0565b6010602052600090815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b600c6020526000908152604090205460ff1681565b600b6020526000908152604090205460ff1681565b66038d7ea4c6800081565b6004546001600160a01b031681565b600a54600160b01b900460ff1681565b6011602052600090815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b60096020526000908152604090208054600182015460039092015460ff91821692911683565b600a546000906001600160a01b031633148061296357506000546001600160a01b031633145b61299e5760405162461bcd60e51b8152600401808060200182810382526027815260200180615dd26027913960400191505060405180910390fd5b6000546001600160a01b03163314806129b957506001821515145b612a03576040805162461bcd60e51b81526020600482015260166024820152756f6e6c792061646d696e2063616e20756e706175736560501b604482015290519081900360640190fd5b600a8054831515600160b01b810260ff60b01b1990921691909117909155604080516020810192909252808252600882820152672a3930b739b332b960c11b6060830152517fef159d9a32b2472e32b098f954f3ce62d232939f1c207070b584df1814de2de09181900360800190a15090565b6001600160a01b038082166000908152600960209081526040808320938616835260029093019052205460ff1692915050565b60075481565b836001600160a01b031663f851a4406040518163ffffffff1660e01b815260040160206040518083038186803b158015612ae857600080fd5b505afa158015612afc573d6000803e3d6000fd5b505050506040513d6020811015612b1257600080fd5b50516001600160a01b03163314612b5a5760405162461bcd60e51b8152600401808060200182810382526027815260200180615e3e6027913960400191505060405180910390fd5b836001600160a01b031663c1e803346040518163ffffffff1660e01b8152600401602060405180830381600087803b158015612b9557600080fd5b505af1158015612ba9573d6000803e3d6000fd5b505050506040513d6020811015612bbf57600080fd5b505115612c0b576040805162461bcd60e51b815260206004820152601560248201527418da185b99d9481b9bdd08185d5d1a1bdc9a5e9959605a1b604482015290519081900360640190fd5b836001600160a01b0316632327c7df8484846040518463ffffffff1660e01b8152600401808481526020018060200180602001838103835285818151815260200191508051906020019060200280838360005b83811015612c76578181015183820152602001612c5e565b50505050905001838103825284818151815260200191508051906020019060200280838360005b83811015612cb5578181015183820152602001612c9d565b5050505090500195505050505050600060405180830381600087803b158015612cdd57600080fd5b505af1158015612cf1573d6000803e3d6000fd5b5050505050505050565b73c00e94cb662c3520282e6f5717214004a7f2688890565b600080546001600160a01b03163314612d32576118c960016012614440565b6001600160a01b03821660009081526009602052604090205460ff1615612d5f576118c9600a6011614440565b816001600160a01b031663fe9c44ae6040518163ffffffff1660e01b815260040160206040518083038186803b158015612d9857600080fd5b505afa158015612dac573d6000803e3d6000fd5b505050506040513d6020811015612dc257600080fd5b5050604080516060810182526001808252600060208381018281528486018381526001600160a01b03891684526009909252949091209251835490151560ff19918216178455935191830191909155516003909101805491151591909216179055612e2c82613eef565b604080516001600160a01b038416815290517fcf583bb0c569eb967f806b11601c4cb93c10310485c67add5f8362c2f212321f9181900360200190a1600092915050565b6ec097ce7bc90715b34b9f100000000081565b600e5481565b60608060086000846001600160a01b03166001600160a01b03168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015612f0557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612ee7575b5093979650505050505050565b600a54600160b81b900460ff1681565b6060600d805480602002602001604051908101604052809291908181526020018280548015612f7a57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612f5c575b5050505050905090565b601260209081526000928352604080842090915290825290205481565b6002546001600160a01b031681565b600a54600090600160b01b900460ff1615613007576040805162461bcd60e51b81526020600482015260126024820152711d1c985b9cd9995c881a5cc81c185d5cd95960721b604482015290519081900360640190fd5b6000613014868685614ecc565b9050801561302357905061174a565b61302c866144b5565b61303886866000614c37565b61174486856000614c37565b6060600082519050606081604051908082528060200260200182016040528015613078578160200160208202803883390190505b50905060005b828110156130d357600085828151811061309457fe5b602002602001015190506130a88133614f6f565b60118111156130b357fe5b8383815181106130bf57fe5b60209081029190910101525060010161307e565b509392505050565b600480546040805163fc57d4df60e01b81526001600160a01b038781169482019490945290516000938493849391169163fc57d4df91602480820192602092909190829003018186803b15801561313157600080fd5b505afa158015613145573d6000803e3d6000fd5b505050506040513d602081101561315b57600080fd5b5051600480546040805163fc57d4df60e01b81526001600160a01b038a8116948201949094529051939450600093929091169163fc57d4df91602480820192602092909190829003018186803b1580156131b457600080fd5b505afa1580156131c8573d6000803e3d6000fd5b505050506040513d60208110156131de57600080fd5b505190508115806131ed575080155b1561320257600d935060009250613348915050565b6000866001600160a01b031663182df0f56040518163ffffffff1660e01b815260040160206040518083038186803b15801561323d57600080fd5b505afa158015613251573d6000803e3d6000fd5b505050506040513d602081101561326757600080fd5b505190506000613275615cea565b61327d615cea565b613285615cea565b600061329360065489615090565b9450905060008160038111156132a557fe5b146132c157600b5b995060009850613348975050505050505050565b6132cb8787615090565b9350905060008160038111156132dd57fe5b146132e957600b6132ad565b6132f384846150cb565b92509050600081600381111561330557fe5b1461331157600b6132ad565b61331b828c614e4f565b95509050600081600381111561332d57fe5b1461333957600b6132ad565b60009950939750505050505050505b935093915050565b601360209081526000928352604080842090915290825290205481565b60146020526000908152604090205481565b613387614ea3565b6133d8576040805162461bcd60e51b815260206004820152601e60248201527f6f6e6c792061646d696e2063616e2061646420636f6d70206d61726b65740000604482015290519081900360640190fd5b60005b8151811015613408576134008282815181106133f357fe5b60200260200101516150e3565b6001016133db565b50613411611cb0565b50565b600a54600090600160b81b900460ff1615613468576040805162461bcd60e51b815260206004820152600f60248201526e1cd95a5e99481a5cc81c185d5cd959608a1b604482015290519081900360640190fd5b6001600160a01b03861660009081526009602052604090205460ff1615806134a957506001600160a01b03851660009081526009602052604090205460ff16155b156134b55760096124e4565b846001600160a01b0316635fe3b5676040518163ffffffff1660e01b815260040160206040518083038186803b1580156134ee57600080fd5b505afa158015613502573d6000803e3d6000fd5b505050506040513d602081101561351857600080fd5b505160408051635fe3b56760e01b815290516001600160a01b0392831692891691635fe3b567916004808301926020929190829003018186803b15801561355e57600080fd5b505afa158015613572573d6000803e3d6000fd5b505050506040513d602081101561358857600080fd5b50516001600160a01b03161461359f5760026124e4565b6135a8866144b5565b6135b486846000614c37565b6135c086856000614c37565b60009695505050505050565b600080546001600160a01b031633146135eb576118c96001600d614440565b6007805490839055604080518281526020810185905281517f7093cf1eb653f749c3ff531d6df7f92764536a7fa0d13530cd26e070780c32ea929181900390910190a160006121e0565b6001600160a01b0383166000908152600c602052604081205460ff1615613696576040805162461bcd60e51b815260206004820152601060248201526f189bdc9c9bddc81a5cc81c185d5cd95960821b604482015290519081900360640190fd5b6001600160a01b03841660009081526009602052604090205460ff166136bd5760096121be565b6001600160a01b038085166000908152600960209081526040808320938716835260029093019052205460ff166137ad57336001600160a01b03851614613743576040805162461bcd60e51b815260206004820152601560248201527439b2b73232b91036bab9ba1031329031aa37b5b2b760591b604482015290519081900360640190fd5b600061374f3385614f6f565b9050600081601181111561375f57fe5b146137785780601181111561377057fe5b9150506121e0565b6001600160a01b038086166000908152600960209081526040808320938816835260029093019052205460ff166137ab57fe5b505b600480546040805163fc57d4df60e01b81526001600160a01b03888116948201949094529051929091169163fc57d4df91602480820192602092909190829003018186803b1580156137fe57600080fd5b505afa158015613812573d6000803e3d6000fd5b505050506040513d602081101561382857600080fd5b505161383557600d6121be565b600080613845858760008761481c565b9193509091506000905082601181111561385b57fe5b146138755781601181111561386c57fe5b925050506121e0565b801561388257600461386c565b61388a615cea565b6040518060200160405280886001600160a01b031663aa5af0fd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156138ce57600080fd5b505afa1580156138e2573d6000803e3d6000fd5b505050506040513d60208110156138f857600080fd5b5051905290506139088782613fcd565b6139158787836000614255565b6000979650505050505050565b6008602052816000526040600020818154811061393b57fe5b6000918252602090912001546001600160a01b03169150829050565b6003546001600160a01b031681565b600080546001600160a01b0316331461398c5761398560016006614440565b9050611542565b6001600160a01b0383166000908152600960205260409020805460ff166139c1576139b960096007614440565b915050611542565b6139c9615cea565b5060408051602081019091528381526139e0615cea565b506040805160208101909152670c7d713b49da00008152613a0181836144ae565b15613a1c57613a1260066008614440565b9350505050611542565b8415801590613aa55750600480546040805163fc57d4df60e01b81526001600160a01b038a8116948201949094529051929091169163fc57d4df91602480820192602092909190829003018186803b158015613a7757600080fd5b505afa158015613a8b573d6000803e3d6000fd5b505050506040513d6020811015613aa157600080fd5b5051155b15613ab657613a12600d6009614440565b60018301805490869055604080516001600160a01b03891681526020810183905280820188905290517f70483e6592cd5182d45ac970e05bc62cdcc90e9d8ef2c2dbe686cf383bcd7fc59181900360600190a16000979650505050505050565b600a54600160a81b900460ff1681565b60055481565b61341181600d805480602002602001604051908101604052809291908181526020018280548015613b8657602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311613b68575b5050505050611548565b600080613b9e858585614ecc565b90508015613bad5790506121e0565b613bb6856144b5565b613bc285856000614c37565b600095945050505050565b6000808290506000806000836001600160a01b031663c37f68e2336040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060806040518083038186803b158015613c2e57600080fd5b505afa158015613c42573d6000803e3d6000fd5b505050506040513d6080811015613c5857600080fd5b508051602082015160409092015190945090925090508215613cab5760405162461bcd60e51b8152600401808060200182810382526025815260200180615df96025913960400191505060405180910390fd5b8015613cc857613cbd600c6002614440565b9450505050506118a5565b6000613cd5873385614ecc565b90508015613cf657613cea600e6003836153fe565b955050505050506118a5565b6001600160a01b0385166000908152600960209081526040808320338452600281019092529091205460ff16613d3557600096505050505050506118a5565b3360009081526002820160209081526040808320805460ff191690556008825291829020805483518184028101840190945280845260609392830182828015613da757602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311613d89575b5050835193945083925060009150505b82811015613dfc57896001600160a01b0316848281518110613dd557fe5b60200260200101516001600160a01b03161415613df457809150613dfc565b600101613db7565b50818110613e0657fe5b336000908152600860205260409020805481906000198101908110613e2757fe5b9060005260206000200160009054906101000a90046001600160a01b0316818381548110613e5157fe5b600091825260209091200180546001600160a01b0319166001600160a01b03929092169190911790558054613e8a826000198301615cfd565b50604080516001600160a01b038c16815233602082015281517fe699a64c18b07ac5b7301aa273f36a2287239eb9501d81950672794afba29a0d929181900390910190a160009c9b505050505050505050505050565b6000546001600160a01b031681565b60005b600d54811015613f7a57816001600160a01b0316600d8281548110613f1357fe5b6000918252602090912001546001600160a01b03161415613f72576040805162461bcd60e51b81526020600482015260146024820152731b585c9ad95d08185b1c9958591e48185919195960621b604482015290519081900360640190fd5b600101613ef2565b50600d80546001810182556000919091527fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb50180546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0382166000908152601160209081526040808320600f9092528220549091613ffa611c9d565b835490915060009061401a908390600160e01b900463ffffffff16615464565b905060008111801561402c5750600083115b156141fb5760006140a1876001600160a01b03166347bd37186040518163ffffffff1660e01b815260040160206040518083038186803b15801561406f57600080fd5b505afa158015614083573d6000803e3d6000fd5b505050506040513d602081101561409957600080fd5b50518761549e565b905060006140af83866154bc565b90506140b9615cea565b600083116140d657604051806020016040528060008152506140e0565b6140e082846154fe565b90506140ea615cea565b604080516020810190915288546001600160e01b0316815261410c908361479c565b9050604051806040016040528061415c83600001516040518060400160405280601a81526020017f6e657720696e6465782065786365656473203232342062697473000000000000815250615533565b6001600160e01b03168152602001614197886040518060400160405280601c8152602001600080516020615e1e8339815191528152506155cd565b63ffffffff9081169091526001600160a01b038c166000908152601160209081526040909120835181549490920151909216600160e01b026001600160e01b039182166001600160e01b0319909416939093171691909117905550611ca292505050565b8015611ca25761422e826040518060400160405280601c8152602001600080516020615e1e8339815191528152506155cd565b845463ffffffff91909116600160e01b026001600160e01b03909116178455505050505050565b6001600160a01b0384166000908152601160205260409020614275615cea565b50604080516020810190915281546001600160e01b03168152614296615cea565b5060408051602080820183526001600160a01b03808a16600090815260138352848120918a1680825282845294812080548552865195909152915291909155805115614437576142e4615cea565b6142ee8383615622565b9050600061437d896001600160a01b03166395dd91938a6040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561434b57600080fd5b505afa15801561435f573d6000803e3d6000fd5b505050506040513d602081101561437557600080fd5b50518861549e565b9050600061438b8284615647565b6001600160a01b038a16600090815260146020526040812054919250906143b29083615667565b90506143d38a828a6143cb5766038d7ea4c680006143ce565b60005b61569d565b6001600160a01b03808c1660008181526014602090815260409182902094909455895181518781529485015280519193928f16927f1fc3ecc087d8d2d15e23d0032af5a47059c3892d003d8e139fdcb6bb327c99a6929081900390910190a3505050505b50505050505050565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa083601181111561446f57fe5b83601381111561447b57fe5b604080519283526020830191909152600082820152519081900360600190a18260118111156121e057fe5b519051111590565b5190511090565b6001600160a01b0381166000908152601060209081526040808320600f90925282205490916144e2611c9d565b8354909150600090614502908390600160e01b900463ffffffff16615464565b90506000811180156145145750600083115b156146da576000856001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561455457600080fd5b505afa158015614568573d6000803e3d6000fd5b505050506040513d602081101561457e57600080fd5b50519050600061458e83866154bc565b9050614598615cea565b600083116145b557604051806020016040528060008152506145bf565b6145bf82846154fe565b90506145c9615cea565b604080516020810190915288546001600160e01b031681526145eb908361479c565b9050604051806040016040528061463b83600001516040518060400160405280601a81526020017f6e657720696e6465782065786365656473203232342062697473000000000000815250615533565b6001600160e01b03168152602001614676886040518060400160405280601c8152602001600080516020615e1e8339815191528152506155cd565b63ffffffff9081169091526001600160a01b038b166000908152601060209081526040909120835181549490920151909216600160e01b026001600160e01b039182166001600160e01b03199094169390931716919091179055506115bc92505050565b80156115bc5761470d826040518060400160405280601c8152602001600080516020615e1e8339815191528152506155cd565b845463ffffffff91909116600160e01b026001600160e01b039091161784555050505050565b61473b615cea565b60405180602001604052806147548560000151856154bc565b90529392505050565b614765615cea565b6040518060200160405280670de0b6b3a764000061478b866000015186600001516154bc565b8161479257fe5b0490529392505050565b6147a4615cea565b604051806020016040528061475485600001518560000151615667565b6147c9615cea565b60405180602001604052806147546147ed8660000151670de0b6b3a76400006154bc565b85516157e2565b6000670de0b6b3a764000061480d8484600001516154bc565b8161481457fe5b049392505050565b6000806000614829615d21565b6001600160a01b03881660009081526008602090815260408083208054825181850281018501909352808352849360609392919083018282801561489657602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311614878575b50939450600093505050505b8151811015614bf25760008282815181106148b957fe5b60200260200101519050806001600160a01b031663c37f68e28e6040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060806040518083038186803b15801561491957600080fd5b505afa15801561492d573d6000803e3d6000fd5b505050506040513d608081101561494357600080fd5b508051602082015160408084015160609485015160808c0152938a019390935291880191909152945084156149895750600f975060009650869550612132945050505050565b60408051602080820183526001600160a01b0380851660008181526009845285902060010154845260c08b01939093528351808301855260808b0151815260e08b015260048054855163fc57d4df60e01b815291820194909452935192169263fc57d4df9260248083019392829003018186803b158015614a0957600080fd5b505afa158015614a1d573d6000803e3d6000fd5b505050506040513d6020811015614a3357600080fd5b505160a08701819052614a575750600d975060009650869550612132945050505050565b604080516020810190915260a08701518152610100870181905260c087015160e0880151614a8492615815565b61012088015293506000846003811115614a9a57fe5b14614ab65750600b975060009650869550612132945050505050565b614ace8661012001518760400151886000015161586d565b875293506000846003811115614ae057fe5b14614afc5750600b975060009650869550612132945050505050565b614b148661010001518760600151886020015161586d565b602088015293506000846003811115614b2957fe5b14614b455750600b975060009650869550612132945050505050565b8b6001600160a01b0316816001600160a01b03161415614be957614b738661012001518c886020015161586d565b602088015293506000846003811115614b8857fe5b14614ba45750600b975060009650869550612132945050505050565b614bb88661010001518b886020015161586d565b602088015293506000846003811115614bcd57fe5b14614be95750600b975060009650869550612132945050505050565b506001016148a2565b50602084015184511115614c19575050506020810151905160009450039150829050612132565b50508151602090920151600095508594509190910391506121329050565b6001600160a01b0383166000908152601060205260409020614c57615cea565b50604080516020810190915281546001600160e01b03168152614c78615cea565b5060408051602080820183526001600160a01b03808916600090815260128352848120918916808252828452948120805485528651959091529152919091558051158015614cc65750815115155b15614cde576ec097ce7bc90715b34b9f100000000081525b614ce6615cea565b614cf08383615622565b90506000876001600160a01b03166370a08231886040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015614d4a57600080fd5b505afa158015614d5e573d6000803e3d6000fd5b505050506040513d6020811015614d7457600080fd5b505190506000614d848284615647565b6001600160a01b03891660009081526014602052604081205491925090614dab9083615667565b9050614dc489828a6143cb5766038d7ea4c680006143ce565b6001600160a01b03808b1660008181526014602090815260409182902094909455895181518781529485015280519193928e16927f2caecd17d02f56fa897705dcc740da2d237c373f70686f4e0d9bd3bf0400ea7a929081900390910190a350505050505050505050565b6000806000614e4284600080600061481c565b9250925092509193909250565b6000806000614e5c615cea565b614e6686866158ba565b90925090506000826003811115614e7957fe5b14614e8a5750915060009050614e9c565b6000614e9582615922565b9350935050505b9250929050565b600080546001600160a01b0316331480614ec757506002546001600160a01b031633145b905090565b6001600160a01b03831660009081526009602052604081205460ff16614ef35760096121be565b6001600160a01b038085166000908152600960209081526040808320938716835260029093019052205460ff16614f2b5760006121be565b600080614f3b858786600061481c565b91935090915060009050826011811115614f5157fe5b14614f625781601181111561386c57fe5b80156135c057600461386c565b6001600160a01b0382166000908152600960205260408120805460ff16614f9a576009915050611542565b6001600160a01b038316600090815260028201602052604090205460ff16151560011415614fcc576000915050611542565b6007546001600160a01b03841660009081526008602052604090205410614ff7576010915050611542565b6001600160a01b0380841660008181526002840160209081526040808320805460ff19166001908117909155600883528184208054918201815584529282902090920180549489166001600160a01b031990951685179055815193845283019190915280517f3ab23ab0d51cccc0c3085aec51f99228625aa1a922b3a8ca89a26b0f2027a1a59281900390910190a15060009392505050565b600061509a615cea565b6150c0604051806020016040528086815250604051806020016040528086815250615931565b915091509250929050565b60006150d5615cea565b835183516150c09190615a1a565b6001600160a01b0381166000908152600960205260409020805460ff161515600114615156576040805162461bcd60e51b815260206004820152601960248201527f636f6d70206d61726b6574206973206e6f74206c697374656400000000000000604482015290519081900360640190fd5b600381015460ff16156151b0576040805162461bcd60e51b815260206004820152601960248201527f636f6d70206d61726b657420616c726561647920616464656400000000000000604482015290519081900360640190fd5b60038101805460ff19166001908117909155604080516001600160a01b0385168152602081019290925280517f93c1f3e36ed71139f466a4ce8c9751790e2e33f5afb2df0dcfb3aeabe55d5aa29281900390910190a16001600160a01b0382166000908152601060205260409020546001600160e01b031615801561525857506001600160a01b038216600090815260106020526040902054600160e01b900463ffffffff16155b156153155760405180604001604052806ec097ce7bc90715b34b9f10000000006001600160e01b031681526020016152ba615291611c9d565b6040518060400160405280601c8152602001600080516020615e1e8339815191528152506155cd565b63ffffffff9081169091526001600160a01b0384166000908152601060209081526040909120835181549490920151909216600160e01b026001600160e01b039182166001600160e01b031990941693909317169190911790555b6001600160a01b0382166000908152601160205260409020546001600160e01b031615801561536757506001600160a01b038216600090815260116020526040902054600160e01b900463ffffffff16155b15611ae85760405180604001604052806ec097ce7bc90715b34b9f10000000006001600160e01b031681526020016153a0615291611c9d565b63ffffffff9081169091526001600160a01b0384166000908152601160209081526040909120835181549490920151909216600160e01b026001600160e01b039182166001600160e01b031990941693909317169190911790555050565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa084601181111561542d57fe5b84601381111561543957fe5b604080519283526020830191909152818101859052519081900360600190a18360118111156121dd57fe5b60006121e08383604051806040016040528060158152602001747375627472616374696f6e20756e646572666c6f7760581b815250615aca565b60006121e06154b584670de0b6b3a76400006154bc565b83516157e2565b60006121e083836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f77000000000000000000815250615b24565b615506615cea565b604051806020016040528061475461552d866ec097ce7bc90715b34b9f10000000006154bc565b856157e2565b600081600160e01b84106155c55760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561558a578181015183820152602001615572565b50505050905090810190601f1680156155b75780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b509192915050565b600081600160201b84106155c55760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561558a578181015183820152602001615572565b61562a615cea565b604051806020016040528061475485600001518560000151615464565b60006ec097ce7bc90715b34b9f100000000061480d8484600001516154bc565b60006121e08383604051806040016040528060118152602001706164646974696f6e206f766572666c6f7760781b815250615ba3565b60008183101580156156af5750600083115b156157da5760006156be612cfb565b604080516370a0823160e01b815230600482015290519192506000916001600160a01b038416916370a08231916024808301926020929190829003018186803b15801561570a57600080fd5b505afa15801561571e573d6000803e3d6000fd5b505050506040513d602081101561573457600080fd5b505190508085116157d757816001600160a01b031663a9059cbb87876040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561579f57600080fd5b505af11580156157b3573d6000803e3d6000fd5b505050506040513d60208110156157c957600080fd5b50600093506121e092505050565b50505b509092915050565b60006121e083836040518060400160405280600e81526020016d646976696465206279207a65726f60901b815250615bf8565b600061581f615cea565b6000615829615cea565b6158338787615931565b9092509050600082600381111561584657fe5b14615855579092509050613348565b61585f8186615931565b935093505050935093915050565b600080600061587a615cea565b61588487876158ba565b9092509050600082600381111561589757fe5b146158a85750915060009050613348565b61585f6158b482615922565b86615c5a565b60006158c4615cea565b6000806158d5866000015186615c80565b909250905060008260038111156158e857fe5b1461590757506040805160208101909152600081529092509050614e9c565b60408051602081019091529081526000969095509350505050565b51670de0b6b3a7640000900490565b600061593b615cea565b60008061595086600001518660000151615c80565b9092509050600082600381111561596357fe5b1461598257506040805160208101909152600081529092509050614e9c565b6000806159976706f05b59d3b2000084615c5a565b909250905060008260038111156159aa57fe5b146159cc57506040805160208101909152600081529094509250614e9c915050565b6000806159e183670de0b6b3a7640000615cbf565b909250905060008260038111156159f457fe5b146159fb57fe5b604080516020810190915290815260009a909950975050505050505050565b6000615a24615cea565b600080615a3986670de0b6b3a7640000615c80565b90925090506000826003811115615a4c57fe5b14615a6b57506040805160208101909152600081529092509050614e9c565b600080615a788388615cbf565b90925090506000826003811115615a8b57fe5b14615aad57506040805160208101909152600081529094509250614e9c915050565b604080516020810190915290815260009890975095505050505050565b60008184841115615b1c5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561558a578181015183820152602001615572565b505050900390565b6000831580615b31575082155b15615b3e575060006121e0565b83830283858281615b4b57fe5b04148390615b9a5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561558a578181015183820152602001615572565b50949350505050565b60008383018285821015615b9a5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561558a578181015183820152602001615572565b60008183615c475760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561558a578181015183820152602001615572565b50828481615c5157fe5b04949350505050565b600080838301848110615c7257600092509050614e9c565b506002915060009050614e9c565b60008083615c9357506000905080614e9c565b83830283858281615ca057fe5b0414615cb457506002915060009050614e9c565b600092509050614e9c565b60008082615cd35750600190506000614e9c565b6000838581615cde57fe5b04915091509250929050565b6040518060200160405280600081525090565b8154818355818111156115a5576000838152602090206115a5918101908301615d8b565b604051806101400160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001615d5f615cea565b8152602001615d6c615cea565b8152602001615d79615cea565b8152602001615d86615cea565b905290565b611c9f91905b80821115615da55760008155600101615d91565b509056fe63616e6e6f742070617573652061206d61726b65742074686174206973206e6f74206c69737465646f6e6c7920706175736520677561726469616e20616e642061646d696e2063616e207061757365657869744d61726b65743a206765744163636f756e74536e617073686f74206661696c6564626c6f636b206e756d62657220657863656564732033322062697473000000006f6e6c7920756e6974726f6c6c65722061646d696e2063616e206368616e676520627261696e73a265627a7a723158204c00e406dddf2a81c9d4d6677fa90b67b440e11d03781fac45266c2ebc83602264736f6c63430005100032", + "metadata": "{\"compiler\":{\"version\":\"0.5.16+commit.9c3226ce\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"action\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"pauseState\",\"type\":\"bool\"}],\"name\":\"ActionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"action\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"pauseState\",\"type\":\"bool\"}],\"name\":\"ActionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSpeed\",\"type\":\"uint256\"}],\"name\":\"CompSpeedUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compBorrowIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedBorrowerComp\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"supplier\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compSupplyIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedSupplierComp\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isComped\",\"type\":\"bool\"}],\"name\":\"MarketComped\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketEntered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketExited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"MarketListed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCloseFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCloseFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCollateralFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCollateralFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCompRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCompRate\",\"type\":\"uint256\"}],\"name\":\"NewCompRate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldLiquidationIncentiveMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"NewLiquidationIncentive\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMaxAssets\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMaxAssets\",\"type\":\"uint256\"}],\"name\":\"NewMaxAssets\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldPauseGuardian\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"NewPauseGuardian\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"oldPriceOracle\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"newPriceOracle\",\"type\":\"address\"}],\"name\":\"NewPriceOracle\",\"type\":\"event\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"_addCompMarkets\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract Unitroller\",\"name\":\"unitroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"compRate_\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"compMarketsToAdd\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"otherMarketsToAdd\",\"type\":\"address[]\"}],\"name\":\"_become\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"compRate_\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"compMarketsToAdd\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"otherMarketsToAdd\",\"type\":\"address[]\"}],\"name\":\"_becomeG3\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"_dropCompMarket\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setBorrowPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCloseFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCollateralFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"compRate_\",\"type\":\"uint256\"}],\"name\":\"_setCompRate\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"_setLiquidationIncentive\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newMaxAssets\",\"type\":\"uint256\"}],\"name\":\"_setMaxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setMintPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"_setPauseGuardian\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"newOracle\",\"type\":\"address\"}],\"name\":\"_setPriceOracle\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setSeizePaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setTransferPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"_supportMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allMarkets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"checkMembership\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"},{\"internalType\":\"contract CToken[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"holders\",\"type\":\"address[]\"},{\"internalType\":\"contract CToken[]\",\"name\":\"cTokens\",\"type\":\"address[]\"},{\"internalType\":\"bool\",\"name\":\"borrowers\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"suppliers\",\"type\":\"bool\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compAccrued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compBorrowState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compBorrowerIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compClaimThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compInitialIndex\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSupplierIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSupplyState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"enterMarkets\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenAddress\",\"type\":\"address\"}],\"name\":\"exitMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getAllMarkets\",\"outputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAssetsIn\",\"outputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getCompAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenModify\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"getHypotheticalAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"isComptroller\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateCalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"liquidationIncentiveMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"markets\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isComped\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"mintAmount\",\"type\":\"uint256\"}],\"name\":\"mintAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualMintAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"mintTokens\",\"type\":\"uint256\"}],\"name\":\"mintVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"refreshCompSpeeds\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"repayBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowerIndex\",\"type\":\"uint256\"}],\"name\":\"repayBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"seizeGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"transferGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Compound\",\"methods\":{\"_addCompMarkets(address[])\":{\"params\":{\"cTokens\":\"The addresses of the markets to add\"}},\"_dropCompMarket(address)\":{\"params\":{\"cToken\":\"The address of the market to drop\"}},\"_setCloseFactor(uint256)\":{\"details\":\"Admin function to set closeFactor\",\"params\":{\"newCloseFactorMantissa\":\"New close factor, scaled by 1e18\"},\"return\":\"uint 0=success, otherwise a failure. (See ErrorReporter for details)\"},\"_setCollateralFactor(address,uint256)\":{\"details\":\"Admin function to set per-market collateralFactor\",\"params\":{\"cToken\":\"The market to set the factor on\",\"newCollateralFactorMantissa\":\"The new collateral factor, scaled by 1e18\"},\"return\":\"uint 0=success, otherwise a failure. (See ErrorReporter for details)\"},\"_setCompRate(uint256)\":{\"params\":{\"compRate_\":\"The amount of COMP wei per block to distribute\"}},\"_setLiquidationIncentive(uint256)\":{\"details\":\"Admin function to set liquidationIncentive\",\"params\":{\"newLiquidationIncentiveMantissa\":\"New liquidationIncentive scaled by 1e18\"},\"return\":\"uint 0=success, otherwise a failure. (See ErrorReporter for details)\"},\"_setMaxAssets(uint256)\":{\"details\":\"Admin function to set maxAssets\",\"params\":{\"newMaxAssets\":\"New max assets\"},\"return\":\"uint 0=success, otherwise a failure. (See ErrorReporter for details)\"},\"_setPauseGuardian(address)\":{\"params\":{\"newPauseGuardian\":\"The address of the new Pause Guardian\"},\"return\":\"uint 0=success, otherwise a failure. (See enum Error for details)\"},\"_setPriceOracle(address)\":{\"details\":\"Admin function to set a new price oracle\",\"return\":\"uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\"},\"_supportMarket(address)\":{\"details\":\"Admin function to set isListed and add support for the market\",\"params\":{\"cToken\":\"The address of the market (token) to list\"},\"return\":\"uint 0=success, otherwise a failure. (See enum Error for details)\"},\"borrowAllowed(address,address,uint256)\":{\"params\":{\"borrowAmount\":\"The amount of underlying the account would borrow\",\"borrower\":\"The account which would borrow the asset\",\"cToken\":\"The market to verify the borrow against\"},\"return\":\"0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"borrowVerify(address,address,uint256)\":{\"params\":{\"borrowAmount\":\"The amount of the underlying asset requested to borrow\",\"borrower\":\"The address borrowing the underlying\",\"cToken\":\"Asset whose underlying is being borrowed\"}},\"checkMembership(address,address)\":{\"params\":{\"account\":\"The address of the account to check\",\"cToken\":\"The cToken to check\"},\"return\":\"True if the account is in the asset, otherwise false.\"},\"claimComp(address)\":{\"params\":{\"holder\":\"The address to claim COMP for\"}},\"claimComp(address,address[])\":{\"params\":{\"cTokens\":\"The list of markets to claim COMP in\",\"holder\":\"The address to claim COMP for\"}},\"claimComp(address[],address[],bool,bool)\":{\"params\":{\"borrowers\":\"Whether or not to claim COMP earned by borrowing\",\"cTokens\":\"The list of markets to claim COMP in\",\"holders\":\"The addresses to claim COMP for\",\"suppliers\":\"Whether or not to claim COMP earned by supplying\"}},\"enterMarkets(address[])\":{\"params\":{\"cTokens\":\"The list of addresses of the cToken markets to be enabled\"},\"return\":\"Success indicator for whether each corresponding market was entered\"},\"exitMarket(address)\":{\"details\":\"Sender must not have an outstanding borrow balance in the asset, or be providing neccessary collateral for an outstanding borrow.\",\"params\":{\"cTokenAddress\":\"The address of the asset to be removed\"},\"return\":\"Whether or not the account successfully exited the market\"},\"getAccountLiquidity(address)\":{\"return\":\"(possible error code (semi-opaque), account liquidity in excess of collateral requirements, account shortfall below collateral requirements)\"},\"getAllMarkets()\":{\"details\":\"The automatic getter may be used to access an individual market.\",\"return\":\"The list of market addresses\"},\"getAssetsIn(address)\":{\"params\":{\"account\":\"The address of the account to pull assets for\"},\"return\":\"A dynamic list with the assets the account has entered\"},\"getCompAddress()\":{\"return\":\"The address of COMP\"},\"getHypotheticalAccountLiquidity(address,address,uint256,uint256)\":{\"params\":{\"account\":\"The account to determine liquidity for\",\"borrowAmount\":\"The amount of underlying to hypothetically borrow\",\"cTokenModify\":\"The market to hypothetically redeem/borrow in\",\"redeemTokens\":\"The number of tokens to hypothetically redeem\"},\"return\":\"(possible error code (semi-opaque), hypothetical account liquidity in excess of collateral requirements, hypothetical account shortfall below collateral requirements)\"},\"liquidateBorrowAllowed(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"repayAmount\":\"The amount of underlying being repaid\"}},\"liquidateBorrowVerify(address,address,address,address,uint256,uint256)\":{\"params\":{\"actualRepayAmount\":\"The amount of underlying being repaid\",\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\"}},\"liquidateCalculateSeizeTokens(address,address,uint256)\":{\"details\":\"Used in liquidation (called in cToken.liquidateBorrowFresh)\",\"params\":{\"actualRepayAmount\":\"The amount of cTokenBorrowed underlying to convert into cTokenCollateral tokens\",\"cTokenBorrowed\":\"The address of the borrowed cToken\",\"cTokenCollateral\":\"The address of the collateral cToken\"},\"return\":\"(errorCode, number of cTokenCollateral tokens to be seized in a liquidation)\"},\"mintAllowed(address,address,uint256)\":{\"params\":{\"cToken\":\"The market to verify the mint against\",\"mintAmount\":\"The amount of underlying being supplied to the market in exchange for tokens\",\"minter\":\"The account which would get the minted tokens\"},\"return\":\"0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"mintVerify(address,address,uint256,uint256)\":{\"params\":{\"actualMintAmount\":\"The amount of the underlying asset being minted\",\"cToken\":\"Asset being minted\",\"mintTokens\":\"The number of tokens being minted\",\"minter\":\"The address minting the tokens\"}},\"redeemAllowed(address,address,uint256)\":{\"params\":{\"cToken\":\"The market to verify the redeem against\",\"redeemTokens\":\"The number of cTokens to exchange for the underlying asset in the market\",\"redeemer\":\"The account which would redeem the tokens\"},\"return\":\"0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"redeemVerify(address,address,uint256,uint256)\":{\"params\":{\"cToken\":\"Asset being redeemed\",\"redeemAmount\":\"The amount of the underlying asset being redeemed\",\"redeemTokens\":\"The number of tokens being redeemed\",\"redeemer\":\"The address redeeming the tokens\"}},\"repayBorrowAllowed(address,address,address,uint256)\":{\"params\":{\"borrower\":\"The account which would borrowed the asset\",\"cToken\":\"The market to verify the repay against\",\"payer\":\"The account which would repay the asset\",\"repayAmount\":\"The amount of the underlying asset the account would repay\"},\"return\":\"0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"repayBorrowVerify(address,address,address,uint256,uint256)\":{\"params\":{\"actualRepayAmount\":\"The amount of underlying being repaid\",\"borrower\":\"The address of the borrower\",\"cToken\":\"Asset being repaid\",\"payer\":\"The address repaying the borrow\"}},\"seizeAllowed(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"seizeTokens\":\"The number of collateral tokens to seize\"}},\"seizeVerify(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"seizeTokens\":\"The number of collateral tokens to seize\"}},\"transferAllowed(address,address,address,uint256)\":{\"params\":{\"cToken\":\"The market to verify the transfer against\",\"dst\":\"The account which receives the tokens\",\"src\":\"The account which sources the tokens\",\"transferTokens\":\"The number of cTokens to transfer\"},\"return\":\"0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"transferVerify(address,address,address,uint256)\":{\"params\":{\"cToken\":\"Asset being transferred\",\"dst\":\"The account which receives the tokens\",\"src\":\"The account which sources the tokens\",\"transferTokens\":\"The number of cTokens to transfer\"}}},\"title\":\"Compound's Comptroller Contract\"},\"userdoc\":{\"methods\":{\"_addCompMarkets(address[])\":{\"notice\":\"Add markets to compMarkets, allowing them to earn COMP in the flywheel\"},\"_dropCompMarket(address)\":{\"notice\":\"Remove a market from compMarkets, preventing it from earning COMP in the flywheel\"},\"_setCloseFactor(uint256)\":{\"notice\":\"Sets the closeFactor used when liquidating borrows\"},\"_setCollateralFactor(address,uint256)\":{\"notice\":\"Sets the collateralFactor for a market\"},\"_setCompRate(uint256)\":{\"notice\":\"Set the amount of COMP distributed per block\"},\"_setLiquidationIncentive(uint256)\":{\"notice\":\"Sets liquidationIncentive\"},\"_setMaxAssets(uint256)\":{\"notice\":\"Sets maxAssets which controls how many markets can be entered\"},\"_setPauseGuardian(address)\":{\"notice\":\"Admin function to change the Pause Guardian\"},\"_setPriceOracle(address)\":{\"notice\":\"Sets a new price oracle for the comptroller\"},\"_supportMarket(address)\":{\"notice\":\"Add the market to the markets mapping and set it as listed\"},\"borrowAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to borrow the underlying asset of the given market\"},\"borrowVerify(address,address,uint256)\":{\"notice\":\"Validates borrow and reverts on rejection. May emit logs.\"},\"checkMembership(address,address)\":{\"notice\":\"Returns whether the given account is entered in the given asset\"},\"claimComp(address)\":{\"notice\":\"Claim all the comp accrued by holder in all markets\"},\"claimComp(address,address[])\":{\"notice\":\"Claim all the comp accrued by holder in the specified markets\"},\"claimComp(address[],address[],bool,bool)\":{\"notice\":\"Claim all comp accrued by the holders\"},\"enterMarkets(address[])\":{\"notice\":\"Add assets to be included in account liquidity calculation\"},\"exitMarket(address)\":{\"notice\":\"Removes asset from sender's account liquidity calculation\"},\"getAccountLiquidity(address)\":{\"notice\":\"Determine the current account liquidity wrt collateral requirements\"},\"getAllMarkets()\":{\"notice\":\"Return all of the markets\"},\"getAssetsIn(address)\":{\"notice\":\"Returns the assets an account has entered\"},\"getCompAddress()\":{\"notice\":\"Return the address of the COMP token\"},\"getHypotheticalAccountLiquidity(address,address,uint256,uint256)\":{\"notice\":\"Determine what the account liquidity would be if the given amounts were redeemed/borrowed\"},\"liquidateBorrowAllowed(address,address,address,address,uint256)\":{\"notice\":\"Checks if the liquidation should be allowed to occur\"},\"liquidateBorrowVerify(address,address,address,address,uint256,uint256)\":{\"notice\":\"Validates liquidateBorrow and reverts on rejection. May emit logs.\"},\"liquidateCalculateSeizeTokens(address,address,uint256)\":{\"notice\":\"Calculate number of tokens of collateral asset to seize given an underlying amount\"},\"mintAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to mint tokens in the given market\"},\"mintVerify(address,address,uint256,uint256)\":{\"notice\":\"Validates mint and reverts on rejection. May emit logs.\"},\"redeemAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to redeem tokens in the given market\"},\"redeemVerify(address,address,uint256,uint256)\":{\"notice\":\"Validates redeem and reverts on rejection. May emit logs.\"},\"refreshCompSpeeds()\":{\"notice\":\"Recalculate and update COMP speeds for all COMP markets\"},\"repayBorrowAllowed(address,address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to repay a borrow in the given market\"},\"repayBorrowVerify(address,address,address,uint256,uint256)\":{\"notice\":\"Validates repayBorrow and reverts on rejection. May emit logs.\"},\"seizeAllowed(address,address,address,address,uint256)\":{\"notice\":\"Checks if the seizing of assets should be allowed to occur\"},\"seizeVerify(address,address,address,address,uint256)\":{\"notice\":\"Validates seize and reverts on rejection. May emit logs.\"},\"transferAllowed(address,address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to transfer tokens in the given market\"},\"transferVerify(address,address,address,uint256)\":{\"notice\":\"Validates transfer and reverts on rejection. May emit logs.\"}}}},\"settings\":{\"compilationTarget\":{\"contracts/ComptrollerG3.sol\":\"ComptrollerG3\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/CToken.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./CTokenInterfaces.sol\\\";\\nimport \\\"./ErrorReporter.sol\\\";\\nimport \\\"./Exponential.sol\\\";\\nimport \\\"./EIP20Interface.sol\\\";\\nimport \\\"./InterestRateModel.sol\\\";\\n\\n/**\\n * @title Compound's CToken Contract\\n * @notice Abstract base for CTokens\\n * @author Compound\\n */\\ncontract CToken is CTokenInterface, Exponential, TokenErrorReporter {\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_) public {\\n require(msg.sender == admin, \\\"only admin may initialize the market\\\");\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = getBlockNumber();\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Transfer `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = uint(-1);\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srcTokensNew;\\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, srcTokensNew) = 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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srcTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != uint(-1)) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n // unused function\\n // comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transfer(address dst, uint256 amount) external nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferFrom(address src, address dst, uint256 amount) external nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (-1 means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool) {\\n address src = msg.sender;\\n transferAllowances[src][spender] = amount;\\n emit Approval(src, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (-1 means infinite)\\n */\\n function allowance(address owner, address spender) external view returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external returns (uint) {\\n Exp memory exchangeRate = Exp({mantissa: exchangeRateCurrent()});\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n require(mErr == MathError.NO_ERROR, \\\"balance could not be calculated\\\");\\n return balance;\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view returns (uint, uint, uint, uint) {\\n uint cTokenBalance = accountTokens[account];\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), cTokenBalance, borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @dev Function to simply retrieve block number\\n * This exists mainly for inheriting test contracts to stub this result.\\n */\\n function getBlockNumber() internal view returns (uint) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this cToken\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view returns (uint) {\\n return interestRateModel.getBorrowRate(getCashPrior(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this cToken\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view returns (uint) {\\n return interestRateModel.getSupplyRate(getCashPrior(), totalBorrows, totalReserves, reserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n require(err == MathError.NO_ERROR, \\\"borrowBalanceStored: borrowBalanceStoredInternal failed\\\");\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return (error code, the calculated balance or 0 if error code is non-zero)\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the CToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n require(err == MathError.NO_ERROR, \\\"exchangeRateStored: exchangeRateStoredInternal failed\\\");\\n return result;\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the CToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return (error code, calculated exchange rate scaled by 1e18)\\n */\\n function exchangeRateStoredInternal() internal view returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows - totalReserves) / totalSupply\\n */\\n uint totalCash = getCashPrior();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Get cash balance of this cToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage.\\n */\\n function accrueInterest() public returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = getBlockNumber();\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = getCashPrior();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n require(mathErr == MathError.NO_ERROR, \\\"could not calculate block delta\\\");\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({mantissa: borrowRateMantissa}), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(Exp({mantissa: reserveFactorMantissa}), interestAccumulated, reservesPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives cTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n struct MintLocalVars {\\n Error err;\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives cTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, 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's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the cToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of cTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.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 cTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED\\\");\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\\");\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender redeems cTokens in exchange for the underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemTokens The number of cTokens to redeem into underlying\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemInternal(uint redeemTokens) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(msg.sender, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems cTokens in exchange for a specified amount of underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemAmount The amount of underlying to receive from redeeming cTokens\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemUnderlyingInternal(uint redeemAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(msg.sender, 0, redeemAmount);\\n }\\n\\n struct RedeemLocalVars {\\n Error err;\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n /**\\n * @notice User redeems cTokens in exchange for the underlying asset\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param redeemTokensIn The number of cTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming cTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemFresh(address payable redeemer, uint redeemTokensIn, uint redeemAmountIn) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr));\\n }\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(Exp({mantissa: vars.exchangeRateMantissa}), redeemTokensIn);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(redeemAmountIn, Exp({mantissa: vars.exchangeRateMantissa}));\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REDEEM_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDEEM_FRESHNESS_CHECK);\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDEEM_TRANSFER_OUT_NOT_POSSIBLE);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We invoke doTransferOut for the redeemer and the redeemAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(redeemer, vars.redeemAmount);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n /* We call the defense hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender borrows assets from the protocol to their own address\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function borrowInternal(uint borrowAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(msg.sender, borrowAmount);\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n /**\\n * @notice Users borrow assets from the protocol to their own address\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function borrowFresh(address payable borrower, uint borrowAmount) internal returns (uint) {\\n /* Fail if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.BORROW_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.BORROW_FRESHNESS_CHECK);\\n }\\n\\n /* Fail gracefully if protocol has insufficient underlying cash */\\n if (getCashPrior() < borrowAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.BORROW_CASH_NOT_AVAILABLE);\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We invoke doTransferOut for the borrower and the borrowAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(borrower, borrowAmount);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to borrower\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer the account paying off the borrow\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount the amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED\\\");\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED\\\");\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this cToken to be liquidated\\n * @param cTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) 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 = cTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, cTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this cToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param cTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowFresh(address liquidator, address borrower, uint repayAmount, CTokenInterface cTokenCollateral) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(address(this), address(cTokenCollateral), liquidator, borrower, repayAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify cTokenCollateral market's block number equals current block number */\\n if (cTokenCollateral.accrualBlockNumber() != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = -1 */\\n if (repayAmount == uint(-1)) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & 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(cTokenCollateral), actualRepayAmount);\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(cTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(cTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = cTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(cTokenCollateral), seizeTokens);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.liquidateBorrowVerify(address(this), address(cTokenCollateral), liquidator, borrower, actualRepayAmount, seizeTokens);\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another cToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed cToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of cTokens to seize\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function seize(address liquidator, address borrower, uint seizeTokens) external nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n struct SeizeInternalLocalVars {\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n uint liquidatorSeizeTokens;\\n uint protocolSeizeTokens;\\n uint protocolSeizeAmount;\\n uint exchangeRateMantissa;\\n uint totalReservesNew;\\n uint totalSupplyNew;\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another CToken.\\n * Its absolutely critical to use msg.sender as the seizer cToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed cToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of cTokens to seize\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function seizeInternal(address seizerToken, address liquidator, address borrower, uint seizeTokens) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n SeizeInternalLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (vars.mathErr, vars.borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(vars.mathErr));\\n }\\n\\n vars.protocolSeizeTokens = mul_(seizeTokens, Exp({mantissa: protocolSeizeShareMantissa}));\\n vars.liquidatorSeizeTokens = sub_(seizeTokens, vars.protocolSeizeTokens);\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n require(vars.mathErr == MathError.NO_ERROR, \\\"exchange rate math error\\\");\\n\\n vars.protocolSeizeAmount = mul_ScalarTruncate(Exp({mantissa: vars.exchangeRateMantissa}), vars.protocolSeizeTokens);\\n\\n vars.totalReservesNew = add_(totalReserves, vars.protocolSeizeAmount);\\n vars.totalSupplyNew = sub_(totalSupply, vars.protocolSeizeTokens);\\n\\n (vars.mathErr, vars.liquidatorTokensNew) = addUInt(accountTokens[liquidator], vars.liquidatorSeizeTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(vars.mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n totalReserves = vars.totalReservesNew;\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[borrower] = vars.borrowerTokensNew;\\n accountTokens[liquidator] = vars.liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, vars.liquidatorSeizeTokens);\\n emit Transfer(borrower, address(this), vars.protocolSeizeTokens);\\n emit ReservesAdded(address(this), vars.protocolSeizeAmount, vars.totalReservesNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n\\n /*** Admin Functions ***/\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPendingAdmin(address payable newPendingAdmin) external returns (uint) {\\n // Check caller = admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\\n }\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptAdmin() external returns (uint) {\\n // Check caller is pendingAdmin and pendingAdmin \\u2260 address(0)\\n if (msg.sender != pendingAdmin || msg.sender == address(0)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = address(0);\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setComptroller(ComptrollerInterface newComptroller) public returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_COMPTROLLER_OWNER_CHECK);\\n }\\n\\n ComptrollerInterface oldComptroller = comptroller;\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(oldComptroller, newComptroller);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh\\n * @dev Admin function to accrue interest and set a new reserve factor\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setReserveFactor(uint newReserveFactorMantissa) external nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\\n * @dev Admin function to set a new reserve factor\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_RESERVE_FACTOR_ADMIN_CHECK);\\n }\\n\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring from msg.sender\\n * @param addAmount Amount of addition to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to admin\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _reduceReserves(uint reduceAmount) external nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to admin\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _reduceReservesFresh(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's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n totalReservesNew = totalReserves - reduceAmount;\\n // We checked reduceAmount <= totalReserves above, so this should never revert.\\n require(totalReservesNew <= 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't be sure if side effects occurred.\\n doTransferOut(admin, reduceAmount);\\n\\n emit ReservesReduced(admin, reduceAmount, totalReservesNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Admin function to accrue interest and update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel);\\n }\\n\\n /**\\n * @notice updates the interest rate model (*requires fresh interest accrual)\\n * @dev Admin function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal returns (uint) {\\n\\n // Used to store old model for use in the event that is emitted on success\\n InterestRateModel oldInterestRateModel;\\n\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_INTEREST_RATE_MODEL_OWNER_CHECK);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Track the market's current interest rate model\\n oldInterestRateModel = interestRateModel;\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view returns (uint);\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure tather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal;\\n\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n}\\n\",\"keccak256\":\"0x436ec2e309682995f8a82dfdd9e8f75928599c10a9a680dddbee6c275014008d\"},\"contracts/CTokenInterfaces.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./InterestRateModel.sol\\\";\\nimport \\\"./EIP20NonStandardInterface.sol\\\";\\n\\ncontract CTokenStorage {\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-cToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModel public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first CTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping (address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping (address => mapping (address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Share of seized collateral that is added to reserves\\n */\\n uint public constant protocolSeizeShareMantissa = 2.8e16; //2.8%\\n\\n}\\n\\ncontract CTokenInterface is CTokenStorage {\\n /**\\n * @notice Indicator that this is a CToken contract (for inspection)\\n */\\n bool public constant isCToken = true;\\n\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(address liquidator, address borrower, uint repayAmount, address cTokenCollateral, uint seizeTokens);\\n\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin is updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(InterestRateModel oldInterestRateModel, InterestRateModel newInterestRateModel);\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address admin, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Failure event\\n */\\n event Failure(uint error, uint info, uint detail);\\n\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external returns (bool);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function approve(address spender, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function balanceOfUnderlying(address owner) external returns (uint);\\n function getAccountSnapshot(address account) external view returns (uint, uint, uint, uint);\\n function borrowRatePerBlock() external view returns (uint);\\n function supplyRatePerBlock() external view returns (uint);\\n function totalBorrowsCurrent() external returns (uint);\\n function borrowBalanceCurrent(address account) external returns (uint);\\n function borrowBalanceStored(address account) public view returns (uint);\\n function exchangeRateCurrent() public returns (uint);\\n function exchangeRateStored() public view returns (uint);\\n function getCash() external view returns (uint);\\n function accrueInterest() public returns (uint);\\n function seize(address liquidator, address borrower, uint seizeTokens) external returns (uint);\\n\\n\\n /*** Admin Functions ***/\\n\\n function _setPendingAdmin(address payable newPendingAdmin) external returns (uint);\\n function _acceptAdmin() external returns (uint);\\n function _setComptroller(ComptrollerInterface newComptroller) public returns (uint);\\n function _setReserveFactor(uint newReserveFactorMantissa) external returns (uint);\\n function _reduceReserves(uint reduceAmount) external returns (uint);\\n function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint);\\n}\\n\\ncontract CErc20Storage {\\n /**\\n * @notice Underlying asset for this CToken\\n */\\n address public underlying;\\n}\\n\\ncontract CErc20Interface is CErc20Storage {\\n\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n function redeem(uint redeemTokens) external returns (uint);\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n function borrow(uint borrowAmount) external returns (uint);\\n function repayBorrow(uint repayAmount) external returns (uint);\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n function liquidateBorrow(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) external returns (uint);\\n function sweepToken(EIP20NonStandardInterface token) external;\\n\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ncontract CDelegationStorage {\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n}\\n\\ncontract CDelegatorInterface is CDelegationStorage {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(address implementation_, bool allowResign, bytes memory becomeImplementationData) public;\\n}\\n\\ncontract CDelegateInterface is CDelegationStorage {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) public;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() public;\\n}\\n\",\"keccak256\":\"0x963bbf60b4c0b76900b3fcb2db8c8be634934b37b4113f1055e57a308197d21a\"},\"contracts/CarefulMath.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Careful Math\\n * @author Compound\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c = a * b;\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n return (MathError.NO_ERROR, a - b);\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c = a + b;\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\",\"keccak256\":\"0x0647348f27e41d22555d99eebd217dee02a4d737df6accd7cce5347a7487c7de\"},\"contracts/ComptrollerG3.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.sol\\\";\\nimport \\\"./ErrorReporter.sol\\\";\\nimport \\\"./Exponential.sol\\\";\\nimport \\\"./PriceOracle.sol\\\";\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./ComptrollerStorage.sol\\\";\\nimport \\\"./Unitroller.sol\\\";\\nimport \\\"./Governance/Comp.sol\\\";\\n\\n/**\\n * @title Compound's Comptroller Contract\\n * @author Compound\\n */\\ncontract ComptrollerG3 is ComptrollerV3Storage, ComptrollerInterface, ComptrollerErrorReporter, Exponential {\\n /// @notice Emitted when an admin supports a market\\n event MarketListed(CToken cToken);\\n\\n /// @notice Emitted when an account enters a market\\n event MarketEntered(CToken cToken, address account);\\n\\n /// @notice Emitted when an account exits a market\\n event MarketExited(CToken cToken, 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(CToken cToken, 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 maxAssets is changed by admin\\n event NewMaxAssets(uint oldMaxAssets, uint newMaxAssets);\\n\\n /// @notice Emitted when price oracle is changed\\n event NewPriceOracle(PriceOracle oldPriceOracle, PriceOracle newPriceOracle);\\n\\n /// @notice Emitted when pause guardian is changed\\n event NewPauseGuardian(address oldPauseGuardian, address newPauseGuardian);\\n\\n /// @notice Emitted when an action is paused globally\\n event ActionPaused(string action, bool pauseState);\\n\\n /// @notice Emitted when an action is paused on a market\\n event ActionPaused(CToken cToken, string action, bool pauseState);\\n\\n /// @notice Emitted when market comped status is changed\\n event MarketComped(CToken cToken, bool isComped);\\n\\n /// @notice Emitted when COMP rate is changed\\n event NewCompRate(uint oldCompRate, uint newCompRate);\\n\\n /// @notice Emitted when a new COMP speed is calculated for a market\\n event CompSpeedUpdated(CToken indexed cToken, uint newSpeed);\\n\\n /// @notice Emitted when COMP is distributed to a supplier\\n event DistributedSupplierComp(CToken indexed cToken, address indexed supplier, uint compDelta, uint compSupplyIndex);\\n\\n /// @notice Emitted when COMP is distributed to a borrower\\n event DistributedBorrowerComp(CToken indexed cToken, address indexed borrower, uint compDelta, uint compBorrowIndex);\\n\\n /// @notice The threshold above which the flywheel transfers COMP, in wei\\n uint public constant compClaimThreshold = 0.001e18;\\n\\n /// @notice The initial COMP index for a market\\n uint224 public constant compInitialIndex = 1e36;\\n\\n // closeFactorMantissa must be strictly greater than this value\\n uint internal constant closeFactorMinMantissa = 0.05e18; // 0.05\\n\\n // closeFactorMantissa must not exceed this value\\n uint internal constant closeFactorMaxMantissa = 0.9e18; // 0.9\\n\\n // No collateralFactorMantissa may exceed this value\\n uint internal constant collateralFactorMaxMantissa = 0.9e18; // 0.9\\n\\n // liquidationIncentiveMantissa must be no less than this value\\n uint internal constant liquidationIncentiveMinMantissa = 1.0e18; // 1.0\\n\\n // liquidationIncentiveMantissa must be no greater than this value\\n uint internal constant liquidationIncentiveMaxMantissa = 1.5e18; // 1.5\\n\\n constructor() public {\\n admin = msg.sender;\\n }\\n\\n /*** Assets You Are In ***/\\n\\n /**\\n * @notice Returns the assets an account has entered\\n * @param account The address of the account to pull assets for\\n * @return A dynamic list with the assets the account has entered\\n */\\n function getAssetsIn(address account) external view returns (CToken[] memory) {\\n CToken[] memory assetsIn = accountAssets[account];\\n\\n return assetsIn;\\n }\\n\\n /**\\n * @notice Returns whether the given account is entered in the given asset\\n * @param account The address of the account to check\\n * @param cToken The cToken to check\\n * @return True if the account is in the asset, otherwise false.\\n */\\n function checkMembership(address account, CToken cToken) external view returns (bool) {\\n return markets[address(cToken)].accountMembership[account];\\n }\\n\\n /**\\n * @notice Add assets to be included in account liquidity calculation\\n * @param cTokens The list of addresses of the cToken markets to be enabled\\n * @return Success indicator for whether each corresponding market was entered\\n */\\n function enterMarkets(address[] memory cTokens) public returns (uint[] memory) {\\n uint len = cTokens.length;\\n\\n uint[] memory results = new uint[](len);\\n for (uint i = 0; i < len; i++) {\\n CToken cToken = CToken(cTokens[i]);\\n\\n results[i] = uint(addToMarketInternal(cToken, msg.sender));\\n }\\n\\n return results;\\n }\\n\\n /**\\n * @notice Add the market to the borrower's \\\"assets in\\\" for liquidity calculations\\n * @param cToken The market to enter\\n * @param borrower The address of the account to modify\\n * @return Success indicator for whether the market was entered\\n */\\n function addToMarketInternal(CToken cToken, address borrower) internal returns (Error) {\\n Market storage marketToJoin = markets[address(cToken)];\\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 if (accountAssets[borrower].length >= maxAssets) {\\n // no space, cannot join\\n return Error.TOO_MANY_ASSETS;\\n }\\n\\n // survived the gauntlet, add to list\\n // NOTE: we store these somewhat redundantly as a significant optimization\\n // this avoids having to iterate through the list for the most common use cases\\n // that is, only when we need to perform liquidity checks\\n // and not whenever we want to check if an account is in a particular market\\n marketToJoin.accountMembership[borrower] = true;\\n accountAssets[borrower].push(cToken);\\n\\n emit MarketEntered(cToken, borrower);\\n\\n return Error.NO_ERROR;\\n }\\n\\n /**\\n * @notice Removes asset from sender's account liquidity calculation\\n * @dev Sender must not have an outstanding borrow balance in the asset,\\n * or be providing neccessary collateral for an outstanding borrow.\\n * @param cTokenAddress The address of the asset to be removed\\n * @return Whether or not the account successfully exited the market\\n */\\n function exitMarket(address cTokenAddress) external returns (uint) {\\n CToken cToken = CToken(cTokenAddress);\\n /* Get sender tokensHeld and amountOwed underlying from the cToken */\\n (uint oErr, uint tokensHeld, uint amountOwed, ) = cToken.getAccountSnapshot(msg.sender);\\n require(oErr == 0, \\\"exitMarket: getAccountSnapshot failed\\\"); // semi-opaque error code\\n\\n /* Fail if the sender has a borrow balance */\\n if (amountOwed != 0) {\\n return fail(Error.NONZERO_BORROW_BALANCE, FailureInfo.EXIT_MARKET_BALANCE_OWED);\\n }\\n\\n /* Fail if the sender is not permitted to redeem all of their tokens */\\n uint allowed = redeemAllowedInternal(cTokenAddress, msg.sender, tokensHeld);\\n if (allowed != 0) {\\n return failOpaque(Error.REJECTION, FailureInfo.EXIT_MARKET_REJECTION, allowed);\\n }\\n\\n Market storage marketToExit = markets[address(cToken)];\\n\\n /* Return true if the sender is not already \\u2018in\\u2019 the market */\\n if (!marketToExit.accountMembership[msg.sender]) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Set cToken account membership to false */\\n delete marketToExit.accountMembership[msg.sender];\\n\\n /* Delete cToken from the account\\u2019s list of assets */\\n // load into memory for faster iteration\\n CToken[] memory userAssetList = accountAssets[msg.sender];\\n uint len = userAssetList.length;\\n uint assetIndex = len;\\n for (uint i = 0; i < len; i++) {\\n if (userAssetList[i] == cToken) {\\n assetIndex = i;\\n break;\\n }\\n }\\n\\n // We *must* have found the asset in the list or our redundant data structure is broken\\n assert(assetIndex < len);\\n\\n // copy last item in list to location of item to be removed, reduce length by 1\\n CToken[] storage storedList = accountAssets[msg.sender];\\n storedList[assetIndex] = storedList[storedList.length - 1];\\n storedList.length--;\\n\\n emit MarketExited(cToken, 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 cToken The market to verify the mint against\\n * @param minter The account which would get the minted tokens\\n * @param mintAmount The amount of underlying being supplied to the market in exchange for tokens\\n * @return 0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function mintAllowed(address cToken, address minter, uint mintAmount) external returns (uint) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n require(!mintGuardianPaused[cToken], \\\"mint is paused\\\");\\n\\n // Shh - currently unused\\n minter;\\n mintAmount;\\n\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n // Keep the flywheel moving\\n updateCompSupplyIndex(cToken);\\n distributeSupplierComp(cToken, minter, false);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates mint and reverts on rejection. May emit logs.\\n * @param cToken Asset being minted\\n * @param minter The address minting the tokens\\n * @param actualMintAmount The amount of the underlying asset being minted\\n * @param mintTokens The number of tokens being minted\\n */\\n function mintVerify(address cToken, address minter, uint actualMintAmount, uint mintTokens) external {\\n // Shh - currently unused\\n cToken;\\n minter;\\n actualMintAmount;\\n mintTokens;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to redeem tokens in the given market\\n * @param cToken The market to verify the redeem against\\n * @param redeemer The account which would redeem the tokens\\n * @param redeemTokens The number of cTokens to exchange for the underlying asset in the market\\n * @return 0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function redeemAllowed(address cToken, address redeemer, uint redeemTokens) external returns (uint) {\\n uint allowed = redeemAllowedInternal(cToken, redeemer, redeemTokens);\\n if (allowed != uint(Error.NO_ERROR)) {\\n return allowed;\\n }\\n\\n // Keep the flywheel moving\\n updateCompSupplyIndex(cToken);\\n distributeSupplierComp(cToken, redeemer, false);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n function redeemAllowedInternal(address cToken, address redeemer, uint redeemTokens) internal view returns (uint) {\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!markets[cToken].accountMembership[redeemer]) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n (Error err, , uint shortfall) = getHypotheticalAccountLiquidityInternal(redeemer, CToken(cToken), redeemTokens, 0);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n if (shortfall > 0) {\\n return uint(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates redeem and reverts on rejection. May emit logs.\\n * @param cToken Asset being redeemed\\n * @param redeemer The address redeeming the tokens\\n * @param redeemAmount The amount of the underlying asset being redeemed\\n * @param redeemTokens The number of tokens being redeemed\\n */\\n function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) external {\\n // Shh - currently unused\\n cToken;\\n redeemer;\\n\\n // Require tokens is zero or amount is also zero\\n if (redeemTokens == 0 && redeemAmount > 0) {\\n revert(\\\"redeemTokens zero\\\");\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to borrow the underlying asset of the given market\\n * @param cToken The market to verify the borrow against\\n * @param borrower The account which would borrow the asset\\n * @param borrowAmount The amount of underlying the account would borrow\\n * @return 0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function borrowAllowed(address cToken, address borrower, uint borrowAmount) external returns (uint) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n require(!borrowGuardianPaused[cToken], \\\"borrow is paused\\\");\\n\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n if (!markets[cToken].accountMembership[borrower]) {\\n // only cTokens may call borrowAllowed if borrower not in market\\n require(msg.sender == cToken, \\\"sender must be cToken\\\");\\n\\n // attempt to add borrower to the market\\n Error err = addToMarketInternal(CToken(msg.sender), borrower);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n\\n // it should be impossible to break the important invariant\\n assert(markets[cToken].accountMembership[borrower]);\\n }\\n\\n if (oracle.getUnderlyingPrice(CToken(cToken)) == 0) {\\n return uint(Error.PRICE_ERROR);\\n }\\n\\n (Error err, , uint shortfall) = getHypotheticalAccountLiquidityInternal(borrower, CToken(cToken), 0, borrowAmount);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n if (shortfall > 0) {\\n return uint(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n\\n // Keep the flywheel moving\\n Exp memory borrowIndex = Exp({mantissa: CToken(cToken).borrowIndex()});\\n updateCompBorrowIndex(cToken, borrowIndex);\\n distributeBorrowerComp(cToken, borrower, borrowIndex, false);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates borrow and reverts on rejection. May emit logs.\\n * @param cToken Asset whose underlying is being borrowed\\n * @param borrower The address borrowing the underlying\\n * @param borrowAmount The amount of the underlying asset requested to borrow\\n */\\n function borrowVerify(address cToken, address borrower, uint borrowAmount) external {\\n // Shh - currently unused\\n cToken;\\n borrower;\\n borrowAmount;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to repay a borrow in the given market\\n * @param cToken The market to verify the repay against\\n * @param payer The account which would repay the asset\\n * @param borrower The account which would borrowed the asset\\n * @param repayAmount The amount of the underlying asset the account would repay\\n * @return 0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function repayBorrowAllowed(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount) external returns (uint) {\\n // Shh - currently unused\\n payer;\\n borrower;\\n repayAmount;\\n\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n // Keep the flywheel moving\\n Exp memory borrowIndex = Exp({mantissa: CToken(cToken).borrowIndex()});\\n updateCompBorrowIndex(cToken, borrowIndex);\\n distributeBorrowerComp(cToken, borrower, borrowIndex, false);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates repayBorrow and reverts on rejection. May emit logs.\\n * @param cToken Asset being repaid\\n * @param payer The address repaying the borrow\\n * @param borrower The address of the borrower\\n * @param actualRepayAmount The amount of underlying being repaid\\n */\\n function repayBorrowVerify(\\n address cToken,\\n address payer,\\n address borrower,\\n uint actualRepayAmount,\\n uint borrowerIndex) external {\\n // Shh - currently unused\\n cToken;\\n payer;\\n borrower;\\n actualRepayAmount;\\n borrowerIndex;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the liquidation should be allowed to occur\\n * @param cTokenBorrowed Asset which was borrowed by the borrower\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param repayAmount The amount of underlying being repaid\\n */\\n function liquidateBorrowAllowed(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount) external returns (uint) {\\n // Shh - currently unused\\n liquidator;\\n\\n if (!markets[cTokenBorrowed].isListed || !markets[cTokenCollateral].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n /* The borrower must have shortfall in order to be liquidatable */\\n (Error err, , uint shortfall) = getAccountLiquidityInternal(borrower);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n if (shortfall == 0) {\\n return uint(Error.INSUFFICIENT_SHORTFALL);\\n }\\n\\n /* The liquidator may not repay more than what is allowed by the closeFactor */\\n uint borrowBalance = CToken(cTokenBorrowed).borrowBalanceStored(borrower);\\n (MathError mathErr, uint maxClose) = mulScalarTruncate(Exp({mantissa: closeFactorMantissa}), borrowBalance);\\n if (mathErr != MathError.NO_ERROR) {\\n return uint(Error.MATH_ERROR);\\n }\\n if (repayAmount > 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 cTokenBorrowed Asset which was borrowed by the borrower\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param actualRepayAmount The amount of underlying being repaid\\n */\\n function liquidateBorrowVerify(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint actualRepayAmount,\\n uint seizeTokens) external {\\n // Shh - currently unused\\n cTokenBorrowed;\\n cTokenCollateral;\\n liquidator;\\n borrower;\\n actualRepayAmount;\\n seizeTokens;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the seizing of assets should be allowed to occur\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param cTokenBorrowed Asset which was borrowed by the borrower\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param seizeTokens The number of collateral tokens to seize\\n */\\n function seizeAllowed(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external returns (uint) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n require(!seizeGuardianPaused, \\\"seize is paused\\\");\\n\\n // Shh - currently unused\\n seizeTokens;\\n\\n if (!markets[cTokenCollateral].isListed || !markets[cTokenBorrowed].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n if (CToken(cTokenCollateral).comptroller() != CToken(cTokenBorrowed).comptroller()) {\\n return uint(Error.COMPTROLLER_MISMATCH);\\n }\\n\\n // Keep the flywheel moving\\n updateCompSupplyIndex(cTokenCollateral);\\n distributeSupplierComp(cTokenCollateral, borrower, false);\\n distributeSupplierComp(cTokenCollateral, liquidator, false);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates seize and reverts on rejection. May emit logs.\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param cTokenBorrowed Asset which was borrowed by the borrower\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param seizeTokens The number of collateral tokens to seize\\n */\\n function seizeVerify(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external {\\n // Shh - currently unused\\n cTokenCollateral;\\n cTokenBorrowed;\\n liquidator;\\n borrower;\\n seizeTokens;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to transfer tokens in the given market\\n * @param cToken The market to verify the transfer against\\n * @param src The account which sources the tokens\\n * @param dst The account which receives the tokens\\n * @param transferTokens The number of cTokens to transfer\\n * @return 0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function transferAllowed(address cToken, address src, address dst, uint transferTokens) external returns (uint) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n require(!transferGuardianPaused, \\\"transfer is paused\\\");\\n\\n // Currently the only consideration is whether or not\\n // the src is allowed to redeem this many tokens\\n uint allowed = redeemAllowedInternal(cToken, src, transferTokens);\\n if (allowed != uint(Error.NO_ERROR)) {\\n return allowed;\\n }\\n\\n // Keep the flywheel moving\\n updateCompSupplyIndex(cToken);\\n distributeSupplierComp(cToken, src, false);\\n distributeSupplierComp(cToken, dst, false);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates transfer and reverts on rejection. May emit logs.\\n * @param cToken Asset being transferred\\n * @param src The account which sources the tokens\\n * @param dst The account which receives the tokens\\n * @param transferTokens The number of cTokens to transfer\\n */\\n function transferVerify(address cToken, address src, address dst, uint transferTokens) external {\\n // Shh - currently unused\\n cToken;\\n src;\\n dst;\\n transferTokens;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n /**\\n * @dev Local vars for avoiding stack-depth limits in calculating account liquidity.\\n * Note that `cTokenBalance` is the number of cTokens the account owns in the market,\\n * whereas `borrowBalance` is the amount of underlying that the account has borrowed.\\n */\\n struct AccountLiquidityLocalVars {\\n uint sumCollateral;\\n uint sumBorrowPlusEffects;\\n uint cTokenBalance;\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n uint oraclePriceMantissa;\\n Exp collateralFactor;\\n Exp exchangeRate;\\n Exp oraclePrice;\\n Exp tokensToDenom;\\n }\\n\\n /**\\n * @notice Determine the current account liquidity wrt collateral requirements\\n * @return (possible error code (semi-opaque),\\n account liquidity in excess of collateral requirements,\\n * account shortfall below collateral requirements)\\n */\\n function getAccountLiquidity(address account) public view returns (uint, uint, uint) {\\n (Error err, uint liquidity, uint shortfall) = getHypotheticalAccountLiquidityInternal(account, CToken(0), 0, 0);\\n\\n return (uint(err), liquidity, shortfall);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity wrt collateral requirements\\n * @return (possible error code,\\n account liquidity in excess of collateral requirements,\\n * account shortfall below collateral requirements)\\n */\\n function getAccountLiquidityInternal(address account) internal view returns (Error, uint, uint) {\\n return getHypotheticalAccountLiquidityInternal(account, CToken(0), 0, 0);\\n }\\n\\n /**\\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\\n * @param cTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @return (possible error code (semi-opaque),\\n hypothetical account liquidity in excess of collateral requirements,\\n * hypothetical account shortfall below collateral requirements)\\n */\\n function getHypotheticalAccountLiquidity(\\n address account,\\n address cTokenModify,\\n uint redeemTokens,\\n uint borrowAmount) public view returns (uint, uint, uint) {\\n (Error err, uint liquidity, uint shortfall) = getHypotheticalAccountLiquidityInternal(account, CToken(cTokenModify), 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 cTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @dev Note that we calculate the exchangeRateStored for each collateral cToken using stored data,\\n * without calculating accumulated interest.\\n * @return (possible error code,\\n hypothetical account liquidity in excess of collateral requirements,\\n * hypothetical account shortfall below collateral requirements)\\n */\\n function getHypotheticalAccountLiquidityInternal(\\n address account,\\n CToken cTokenModify,\\n uint redeemTokens,\\n uint borrowAmount) internal view returns (Error, uint, uint) {\\n\\n AccountLiquidityLocalVars memory vars; // Holds all our calculation results\\n uint oErr;\\n MathError mErr;\\n\\n // For each asset the account is in\\n CToken[] memory assets = accountAssets[account];\\n for (uint i = 0; i < assets.length; i++) {\\n CToken asset = assets[i];\\n\\n // Read the balances and exchange rate from the cToken\\n (oErr, vars.cTokenBalance, vars.borrowBalance, vars.exchangeRateMantissa) = asset.getAccountSnapshot(account);\\n if (oErr != 0) { // semi-opaque error code, we assume NO_ERROR == 0 is invariant between upgrades\\n return (Error.SNAPSHOT_ERROR, 0, 0);\\n }\\n vars.collateralFactor = Exp({mantissa: markets[address(asset)].collateralFactorMantissa});\\n vars.exchangeRate = Exp({mantissa: vars.exchangeRateMantissa});\\n\\n // Get the normalized price of the asset\\n vars.oraclePriceMantissa = oracle.getUnderlyingPrice(asset);\\n if (vars.oraclePriceMantissa == 0) {\\n return (Error.PRICE_ERROR, 0, 0);\\n }\\n vars.oraclePrice = Exp({mantissa: vars.oraclePriceMantissa});\\n\\n // Pre-compute a conversion factor from tokens -> 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 * cTokenBalance\\n (mErr, vars.sumCollateral) = mulScalarTruncateAddUInt(vars.tokensToDenom, vars.cTokenBalance, 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 cTokenModify\\n if (asset == cTokenModify) {\\n // redeem effect\\n // sumBorrowPlusEffects += tokensToDenom * redeemTokens\\n (mErr, vars.sumBorrowPlusEffects) = mulScalarTruncateAddUInt(vars.tokensToDenom, redeemTokens, vars.sumBorrowPlusEffects);\\n if (mErr != MathError.NO_ERROR) {\\n return (Error.MATH_ERROR, 0, 0);\\n }\\n\\n // borrow effect\\n // sumBorrowPlusEffects += oraclePrice * borrowAmount\\n (mErr, vars.sumBorrowPlusEffects) = mulScalarTruncateAddUInt(vars.oraclePrice, borrowAmount, vars.sumBorrowPlusEffects);\\n if (mErr != MathError.NO_ERROR) {\\n return (Error.MATH_ERROR, 0, 0);\\n }\\n }\\n }\\n\\n // These are safe, as the underflow condition is checked first\\n if (vars.sumCollateral > vars.sumBorrowPlusEffects) {\\n return (Error.NO_ERROR, vars.sumCollateral - vars.sumBorrowPlusEffects, 0);\\n } else {\\n return (Error.NO_ERROR, 0, vars.sumBorrowPlusEffects - vars.sumCollateral);\\n }\\n }\\n\\n /**\\n * @notice Calculate number of tokens of collateral asset to seize given an underlying amount\\n * @dev Used in liquidation (called in cToken.liquidateBorrowFresh)\\n * @param cTokenBorrowed The address of the borrowed cToken\\n * @param cTokenCollateral The address of the collateral cToken\\n * @param actualRepayAmount The amount of cTokenBorrowed underlying to convert into cTokenCollateral tokens\\n * @return (errorCode, number of cTokenCollateral tokens to be seized in a liquidation)\\n */\\n function liquidateCalculateSeizeTokens(address cTokenBorrowed, address cTokenCollateral, uint actualRepayAmount) external view returns (uint, uint) {\\n /* Read oracle prices for borrowed and collateral markets */\\n uint priceBorrowedMantissa = oracle.getUnderlyingPrice(CToken(cTokenBorrowed));\\n uint priceCollateralMantissa = oracle.getUnderlyingPrice(CToken(cTokenCollateral));\\n if (priceBorrowedMantissa == 0 || priceCollateralMantissa == 0) {\\n return (uint(Error.PRICE_ERROR), 0);\\n }\\n\\n /*\\n * Get the exchange rate and calculate the number of collateral tokens to seize:\\n * seizeAmount = actualRepayAmount * liquidationIncentive * priceBorrowed / priceCollateral\\n * seizeTokens = seizeAmount / exchangeRate\\n * = actualRepayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate)\\n */\\n uint exchangeRateMantissa = CToken(cTokenCollateral).exchangeRateStored(); // Note: reverts on error\\n uint seizeTokens;\\n Exp memory numerator;\\n Exp memory denominator;\\n Exp memory ratio;\\n MathError mathErr;\\n\\n (mathErr, numerator) = mulExp(liquidationIncentiveMantissa, priceBorrowedMantissa);\\n if (mathErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0);\\n }\\n\\n (mathErr, denominator) = mulExp(priceCollateralMantissa, exchangeRateMantissa);\\n if (mathErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0);\\n }\\n\\n (mathErr, ratio) = divExp(numerator, denominator);\\n if (mathErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0);\\n }\\n\\n (mathErr, seizeTokens) = mulScalarTruncate(ratio, actualRepayAmount);\\n if (mathErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0);\\n }\\n\\n return (uint(Error.NO_ERROR), seizeTokens);\\n }\\n\\n /*** Admin Functions ***/\\n\\n /**\\n * @notice Sets a new price oracle for the comptroller\\n * @dev Admin function to set a new price oracle\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPriceOracle(PriceOracle newOracle) public returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PRICE_ORACLE_OWNER_CHECK);\\n }\\n\\n // Track the old oracle for the comptroller\\n PriceOracle oldOracle = oracle;\\n\\n // Set comptroller's oracle to newOracle\\n oracle = newOracle;\\n\\n // Emit NewPriceOracle(oldOracle, newOracle)\\n emit NewPriceOracle(oldOracle, newOracle);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets the closeFactor used when liquidating borrows\\n * @dev Admin function to set closeFactor\\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\\n * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function _setCloseFactor(uint newCloseFactorMantissa) external returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_CLOSE_FACTOR_OWNER_CHECK);\\n }\\n\\n Exp memory newCloseFactorExp = Exp({mantissa: newCloseFactorMantissa});\\n Exp memory lowLimit = Exp({mantissa: closeFactorMinMantissa});\\n if (lessThanOrEqualExp(newCloseFactorExp, lowLimit)) {\\n return fail(Error.INVALID_CLOSE_FACTOR, FailureInfo.SET_CLOSE_FACTOR_VALIDATION);\\n }\\n\\n Exp memory highLimit = Exp({mantissa: closeFactorMaxMantissa});\\n if (lessThanExp(highLimit, newCloseFactorExp)) {\\n return fail(Error.INVALID_CLOSE_FACTOR, FailureInfo.SET_CLOSE_FACTOR_VALIDATION);\\n }\\n\\n uint oldCloseFactorMantissa = closeFactorMantissa;\\n closeFactorMantissa = newCloseFactorMantissa;\\n emit NewCloseFactor(oldCloseFactorMantissa, closeFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets the collateralFactor for a market\\n * @dev Admin function to set per-market collateralFactor\\n * @param cToken The market to set the factor on\\n * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18\\n * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function _setCollateralFactor(CToken cToken, 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(cToken)];\\n if (!market.isListed) {\\n return fail(Error.MARKET_NOT_LISTED, FailureInfo.SET_COLLATERAL_FACTOR_NO_EXISTS);\\n }\\n\\n Exp memory newCollateralFactorExp = Exp({mantissa: newCollateralFactorMantissa});\\n\\n // Check collateral factor <= 0.9\\n Exp memory highLimit = Exp({mantissa: collateralFactorMaxMantissa});\\n if (lessThanExp(highLimit, newCollateralFactorExp)) {\\n return fail(Error.INVALID_COLLATERAL_FACTOR, FailureInfo.SET_COLLATERAL_FACTOR_VALIDATION);\\n }\\n\\n // If collateral factor != 0, fail if price == 0\\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(cToken) == 0) {\\n return fail(Error.PRICE_ERROR, FailureInfo.SET_COLLATERAL_FACTOR_WITHOUT_PRICE);\\n }\\n\\n // Set market's collateral factor to new collateral factor, remember old value\\n uint oldCollateralFactorMantissa = market.collateralFactorMantissa;\\n market.collateralFactorMantissa = newCollateralFactorMantissa;\\n\\n // Emit event with asset, old collateral factor, and new collateral factor\\n emit NewCollateralFactor(cToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets maxAssets which controls how many markets can be entered\\n * @dev Admin function to set maxAssets\\n * @param newMaxAssets New max assets\\n * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function _setMaxAssets(uint newMaxAssets) external returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_MAX_ASSETS_OWNER_CHECK);\\n }\\n\\n uint oldMaxAssets = maxAssets;\\n maxAssets = newMaxAssets;\\n emit NewMaxAssets(oldMaxAssets, newMaxAssets);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets liquidationIncentive\\n * @dev Admin function to set liquidationIncentive\\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\\n * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function _setLiquidationIncentive(uint newLiquidationIncentiveMantissa) external returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_LIQUIDATION_INCENTIVE_OWNER_CHECK);\\n }\\n\\n // Check de-scaled min <= newLiquidationIncentive <= max\\n Exp memory newLiquidationIncentive = Exp({mantissa: newLiquidationIncentiveMantissa});\\n Exp memory minLiquidationIncentive = Exp({mantissa: liquidationIncentiveMinMantissa});\\n if (lessThanExp(newLiquidationIncentive, minLiquidationIncentive)) {\\n return fail(Error.INVALID_LIQUIDATION_INCENTIVE, FailureInfo.SET_LIQUIDATION_INCENTIVE_VALIDATION);\\n }\\n\\n Exp memory maxLiquidationIncentive = Exp({mantissa: liquidationIncentiveMaxMantissa});\\n if (lessThanExp(maxLiquidationIncentive, newLiquidationIncentive)) {\\n return fail(Error.INVALID_LIQUIDATION_INCENTIVE, FailureInfo.SET_LIQUIDATION_INCENTIVE_VALIDATION);\\n }\\n\\n // Save current value for use in log\\n uint oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa;\\n\\n // Set liquidation incentive to new incentive\\n liquidationIncentiveMantissa = newLiquidationIncentiveMantissa;\\n\\n // Emit event with old incentive, new incentive\\n emit NewLiquidationIncentive(oldLiquidationIncentiveMantissa, newLiquidationIncentiveMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Add the market to the markets mapping and set it as listed\\n * @dev Admin function to set isListed and add support for the market\\n * @param cToken The address of the market (token) to list\\n * @return uint 0=success, otherwise a failure. (See enum Error for details)\\n */\\n function _supportMarket(CToken cToken) external returns (uint) {\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SUPPORT_MARKET_OWNER_CHECK);\\n }\\n\\n if (markets[address(cToken)].isListed) {\\n return fail(Error.MARKET_ALREADY_LISTED, FailureInfo.SUPPORT_MARKET_EXISTS);\\n }\\n\\n cToken.isCToken(); // Sanity check to make sure its really a CToken\\n\\n markets[address(cToken)] = Market({isListed: true, isComped: false, collateralFactorMantissa: 0});\\n\\n _addMarketInternal(address(cToken));\\n\\n emit MarketListed(cToken);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n function _addMarketInternal(address cToken) internal {\\n for (uint i = 0; i < allMarkets.length; i ++) {\\n require(allMarkets[i] != CToken(cToken), \\\"market already added\\\");\\n }\\n allMarkets.push(CToken(cToken));\\n }\\n\\n /**\\n * @notice Admin function to change the Pause Guardian\\n * @param newPauseGuardian The address of the new Pause Guardian\\n * @return uint 0=success, otherwise a failure. (See enum Error for details)\\n */\\n function _setPauseGuardian(address newPauseGuardian) public returns (uint) {\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PAUSE_GUARDIAN_OWNER_CHECK);\\n }\\n\\n // Save current value for inclusion in log\\n address oldPauseGuardian = pauseGuardian;\\n\\n // Store pauseGuardian with value newPauseGuardian\\n pauseGuardian = newPauseGuardian;\\n\\n // Emit NewPauseGuardian(OldPauseGuardian, NewPauseGuardian)\\n emit NewPauseGuardian(oldPauseGuardian, pauseGuardian);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n function _setMintPaused(CToken cToken, bool state) public returns (bool) {\\n require(markets[address(cToken)].isListed, \\\"cannot pause a market that is not listed\\\");\\n require(msg.sender == pauseGuardian || msg.sender == admin, \\\"only pause guardian and admin can pause\\\");\\n require(msg.sender == admin || state == true, \\\"only admin can unpause\\\");\\n\\n mintGuardianPaused[address(cToken)] = state;\\n emit ActionPaused(cToken, \\\"Mint\\\", state);\\n return state;\\n }\\n\\n function _setBorrowPaused(CToken cToken, bool state) public returns (bool) {\\n require(markets[address(cToken)].isListed, \\\"cannot pause a market that is not listed\\\");\\n require(msg.sender == pauseGuardian || msg.sender == admin, \\\"only pause guardian and admin can pause\\\");\\n require(msg.sender == admin || state == true, \\\"only admin can unpause\\\");\\n\\n borrowGuardianPaused[address(cToken)] = state;\\n emit ActionPaused(cToken, \\\"Borrow\\\", state);\\n return state;\\n }\\n\\n function _setTransferPaused(bool state) public returns (bool) {\\n require(msg.sender == pauseGuardian || msg.sender == admin, \\\"only pause guardian and admin can pause\\\");\\n require(msg.sender == admin || state == true, \\\"only admin can unpause\\\");\\n\\n transferGuardianPaused = state;\\n emit ActionPaused(\\\"Transfer\\\", state);\\n return state;\\n }\\n\\n function _setSeizePaused(bool state) public returns (bool) {\\n require(msg.sender == pauseGuardian || msg.sender == admin, \\\"only pause guardian and admin can pause\\\");\\n require(msg.sender == admin || state == true, \\\"only admin can unpause\\\");\\n\\n seizeGuardianPaused = state;\\n emit ActionPaused(\\\"Seize\\\", state);\\n return state;\\n }\\n\\n function _become(Unitroller unitroller, uint compRate_, address[] memory compMarketsToAdd, address[] memory otherMarketsToAdd) public {\\n require(msg.sender == unitroller.admin(), \\\"only unitroller admin can change brains\\\");\\n require(unitroller._acceptImplementation() == 0, \\\"change not authorized\\\");\\n\\n ComptrollerG3(address(unitroller))._becomeG3(compRate_, compMarketsToAdd, otherMarketsToAdd);\\n }\\n\\n function _becomeG3(uint compRate_, address[] memory compMarketsToAdd, address[] memory otherMarketsToAdd) public {\\n require(msg.sender == comptrollerImplementation, \\\"only brains can become itself\\\");\\n\\n for (uint i = 0; i < compMarketsToAdd.length; i++) {\\n _addMarketInternal(address(compMarketsToAdd[i]));\\n }\\n\\n for (uint i = 0; i < otherMarketsToAdd.length; i++) {\\n _addMarketInternal(address(otherMarketsToAdd[i]));\\n }\\n\\n _setCompRate(compRate_);\\n _addCompMarkets(compMarketsToAdd);\\n }\\n\\n /**\\n * @notice Checks caller is admin, or this contract is becoming the new implementation\\n */\\n function adminOrInitializing() internal view returns (bool) {\\n return msg.sender == admin || msg.sender == comptrollerImplementation;\\n }\\n\\n /*** Comp Distribution ***/\\n\\n /**\\n * @notice Recalculate and update COMP speeds for all COMP markets\\n */\\n function refreshCompSpeeds() public {\\n CToken[] memory allMarkets_ = allMarkets;\\n\\n for (uint i = 0; i < allMarkets_.length; i++) {\\n CToken cToken = allMarkets_[i];\\n Exp memory borrowIndex = Exp({mantissa: cToken.borrowIndex()});\\n updateCompSupplyIndex(address(cToken));\\n updateCompBorrowIndex(address(cToken), borrowIndex);\\n }\\n\\n Exp memory totalUtility = Exp({mantissa: 0});\\n Exp[] memory utilities = new Exp[](allMarkets_.length);\\n for (uint i = 0; i < allMarkets_.length; i++) {\\n CToken cToken = allMarkets_[i];\\n if (markets[address(cToken)].isComped) {\\n Exp memory assetPrice = Exp({mantissa: oracle.getUnderlyingPrice(cToken)});\\n Exp memory interestPerBlock = mul_(Exp({mantissa: cToken.borrowRatePerBlock()}), cToken.totalBorrows());\\n Exp memory utility = mul_(interestPerBlock, assetPrice);\\n utilities[i] = utility;\\n totalUtility = add_(totalUtility, utility);\\n }\\n }\\n\\n for (uint i = 0; i < allMarkets_.length; i++) {\\n CToken cToken = allMarkets[i];\\n uint newSpeed = totalUtility.mantissa > 0 ? mul_(compRate, div_(utilities[i], totalUtility)) : 0;\\n compSpeeds[address(cToken)] = newSpeed;\\n emit CompSpeedUpdated(cToken, newSpeed);\\n }\\n }\\n\\n /**\\n * @notice Accrue COMP to the market by updating the supply index\\n * @param cToken The market whose supply index to update\\n */\\n function updateCompSupplyIndex(address cToken) internal {\\n CompMarketState storage supplyState = compSupplyState[cToken];\\n uint supplySpeed = compSpeeds[cToken];\\n uint blockNumber = getBlockNumber();\\n uint deltaBlocks = sub_(blockNumber, uint(supplyState.block));\\n if (deltaBlocks > 0 && supplySpeed > 0) {\\n uint supplyTokens = CToken(cToken).totalSupply();\\n uint compAccrued = mul_(deltaBlocks, supplySpeed);\\n Double memory ratio = supplyTokens > 0 ? fraction(compAccrued, supplyTokens) : Double({mantissa: 0});\\n Double memory index = add_(Double({mantissa: supplyState.index}), ratio);\\n compSupplyState[cToken] = CompMarketState({\\n index: safe224(index.mantissa, \\\"new index exceeds 224 bits\\\"),\\n block: safe32(blockNumber, \\\"block number exceeds 32 bits\\\")\\n });\\n } else if (deltaBlocks > 0) {\\n supplyState.block = safe32(blockNumber, \\\"block number exceeds 32 bits\\\");\\n }\\n }\\n\\n /**\\n * @notice Accrue COMP to the market by updating the borrow index\\n * @param cToken The market whose borrow index to update\\n */\\n function updateCompBorrowIndex(address cToken, Exp memory marketBorrowIndex) internal {\\n CompMarketState storage borrowState = compBorrowState[cToken];\\n uint borrowSpeed = compSpeeds[cToken];\\n uint blockNumber = getBlockNumber();\\n uint deltaBlocks = sub_(blockNumber, uint(borrowState.block));\\n if (deltaBlocks > 0 && borrowSpeed > 0) {\\n uint borrowAmount = div_(CToken(cToken).totalBorrows(), marketBorrowIndex);\\n uint compAccrued = mul_(deltaBlocks, borrowSpeed);\\n Double memory ratio = borrowAmount > 0 ? fraction(compAccrued, borrowAmount) : Double({mantissa: 0});\\n Double memory index = add_(Double({mantissa: borrowState.index}), ratio);\\n compBorrowState[cToken] = CompMarketState({\\n index: safe224(index.mantissa, \\\"new index exceeds 224 bits\\\"),\\n block: safe32(blockNumber, \\\"block number exceeds 32 bits\\\")\\n });\\n } else if (deltaBlocks > 0) {\\n borrowState.block = safe32(blockNumber, \\\"block number exceeds 32 bits\\\");\\n }\\n }\\n\\n /**\\n * @notice Calculate COMP accrued by a supplier and possibly transfer it to them\\n * @param cToken The market in which the supplier is interacting\\n * @param supplier The address of the supplier to distribute COMP to\\n */\\n function distributeSupplierComp(address cToken, address supplier, bool distributeAll) internal {\\n CompMarketState storage supplyState = compSupplyState[cToken];\\n Double memory supplyIndex = Double({mantissa: supplyState.index});\\n Double memory supplierIndex = Double({mantissa: compSupplierIndex[cToken][supplier]});\\n compSupplierIndex[cToken][supplier] = supplyIndex.mantissa;\\n\\n if (supplierIndex.mantissa == 0 && supplyIndex.mantissa > 0) {\\n supplierIndex.mantissa = compInitialIndex;\\n }\\n\\n Double memory deltaIndex = sub_(supplyIndex, supplierIndex);\\n uint supplierTokens = CToken(cToken).balanceOf(supplier);\\n uint supplierDelta = mul_(supplierTokens, deltaIndex);\\n uint supplierAccrued = add_(compAccrued[supplier], supplierDelta);\\n compAccrued[supplier] = transferComp(supplier, supplierAccrued, distributeAll ? 0 : compClaimThreshold);\\n emit DistributedSupplierComp(CToken(cToken), supplier, supplierDelta, supplyIndex.mantissa);\\n }\\n\\n /**\\n * @notice Calculate COMP accrued by a borrower and possibly transfer it to them\\n * @dev Borrowers will not begin to accrue until after the first interaction with the protocol.\\n * @param cToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute COMP to\\n */\\n function distributeBorrowerComp(address cToken, address borrower, Exp memory marketBorrowIndex, bool distributeAll) internal {\\n CompMarketState storage borrowState = compBorrowState[cToken];\\n Double memory borrowIndex = Double({mantissa: borrowState.index});\\n Double memory borrowerIndex = Double({mantissa: compBorrowerIndex[cToken][borrower]});\\n compBorrowerIndex[cToken][borrower] = borrowIndex.mantissa;\\n\\n if (borrowerIndex.mantissa > 0) {\\n Double memory deltaIndex = sub_(borrowIndex, borrowerIndex);\\n uint borrowerAmount = div_(CToken(cToken).borrowBalanceStored(borrower), marketBorrowIndex);\\n uint borrowerDelta = mul_(borrowerAmount, deltaIndex);\\n uint borrowerAccrued = add_(compAccrued[borrower], borrowerDelta);\\n compAccrued[borrower] = transferComp(borrower, borrowerAccrued, distributeAll ? 0 : compClaimThreshold);\\n emit DistributedBorrowerComp(CToken(cToken), borrower, borrowerDelta, borrowIndex.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Transfer COMP to the user, if they are above the threshold\\n * @dev Note: If there is not enough COMP, we do not perform the transfer all.\\n * @param user The address of the user to transfer COMP to\\n * @param userAccrued The amount of COMP to (possibly) transfer\\n * @return The amount of COMP which was NOT transferred to the user\\n */\\n function transferComp(address user, uint userAccrued, uint threshold) internal returns (uint) {\\n if (userAccrued >= threshold && userAccrued > 0) {\\n Comp comp = Comp(getCompAddress());\\n uint compRemaining = comp.balanceOf(address(this));\\n if (userAccrued <= compRemaining) {\\n comp.transfer(user, userAccrued);\\n return 0;\\n }\\n }\\n return userAccrued;\\n }\\n\\n /**\\n * @notice Claim all the comp accrued by holder in all markets\\n * @param holder The address to claim COMP for\\n */\\n function claimComp(address holder) public {\\n return claimComp(holder, allMarkets);\\n }\\n\\n /**\\n * @notice Claim all the comp accrued by holder in the specified markets\\n * @param holder The address to claim COMP for\\n * @param cTokens The list of markets to claim COMP in\\n */\\n function claimComp(address holder, CToken[] memory cTokens) public {\\n address[] memory holders = new address[](1);\\n holders[0] = holder;\\n claimComp(holders, cTokens, true, true);\\n }\\n\\n /**\\n * @notice Claim all comp accrued by the holders\\n * @param holders The addresses to claim COMP for\\n * @param cTokens The list of markets to claim COMP in\\n * @param borrowers Whether or not to claim COMP earned by borrowing\\n * @param suppliers Whether or not to claim COMP earned by supplying\\n */\\n function claimComp(address[] memory holders, CToken[] memory cTokens, bool borrowers, bool suppliers) public {\\n for (uint i = 0; i < cTokens.length; i++) {\\n CToken cToken = cTokens[i];\\n require(markets[address(cToken)].isListed, \\\"market must be listed\\\");\\n if (borrowers == true) {\\n Exp memory borrowIndex = Exp({mantissa: cToken.borrowIndex()});\\n updateCompBorrowIndex(address(cToken), borrowIndex);\\n for (uint j = 0; j < holders.length; j++) {\\n distributeBorrowerComp(address(cToken), holders[j], borrowIndex, true);\\n }\\n }\\n if (suppliers == true) {\\n updateCompSupplyIndex(address(cToken));\\n for (uint j = 0; j < holders.length; j++) {\\n distributeSupplierComp(address(cToken), holders[j], true);\\n }\\n }\\n }\\n }\\n\\n /*** Comp Distribution Admin ***/\\n\\n /**\\n * @notice Set the amount of COMP distributed per block\\n * @param compRate_ The amount of COMP wei per block to distribute\\n */\\n function _setCompRate(uint compRate_) public {\\n require(adminOrInitializing(), \\\"only admin can change comp rate\\\");\\n\\n uint oldRate = compRate;\\n compRate = compRate_;\\n emit NewCompRate(oldRate, compRate_);\\n\\n refreshCompSpeeds();\\n }\\n\\n /**\\n * @notice Add markets to compMarkets, allowing them to earn COMP in the flywheel\\n * @param cTokens The addresses of the markets to add\\n */\\n function _addCompMarkets(address[] memory cTokens) public {\\n require(adminOrInitializing(), \\\"only admin can add comp market\\\");\\n\\n for (uint i = 0; i < cTokens.length; i++) {\\n _addCompMarketInternal(cTokens[i]);\\n }\\n\\n refreshCompSpeeds();\\n }\\n\\n function _addCompMarketInternal(address cToken) internal {\\n Market storage market = markets[cToken];\\n require(market.isListed == true, \\\"comp market is not listed\\\");\\n require(market.isComped == false, \\\"comp market already added\\\");\\n\\n market.isComped = true;\\n emit MarketComped(CToken(cToken), true);\\n\\n if (compSupplyState[cToken].index == 0 && compSupplyState[cToken].block == 0) {\\n compSupplyState[cToken] = CompMarketState({\\n index: compInitialIndex,\\n block: safe32(getBlockNumber(), \\\"block number exceeds 32 bits\\\")\\n });\\n }\\n\\n if (compBorrowState[cToken].index == 0 && compBorrowState[cToken].block == 0) {\\n compBorrowState[cToken] = CompMarketState({\\n index: compInitialIndex,\\n block: safe32(getBlockNumber(), \\\"block number exceeds 32 bits\\\")\\n });\\n }\\n }\\n\\n /**\\n * @notice Remove a market from compMarkets, preventing it from earning COMP in the flywheel\\n * @param cToken The address of the market to drop\\n */\\n function _dropCompMarket(address cToken) public {\\n require(msg.sender == admin, \\\"only admin can drop comp market\\\");\\n\\n Market storage market = markets[cToken];\\n require(market.isComped == true, \\\"market is not a comp market\\\");\\n\\n market.isComped = false;\\n emit MarketComped(CToken(cToken), false);\\n\\n refreshCompSpeeds();\\n }\\n\\n /**\\n * @notice Return all of the markets\\n * @dev The automatic getter may be used to access an individual market.\\n * @return The list of market addresses\\n */\\n function getAllMarkets() public view returns (CToken[] memory) {\\n return allMarkets;\\n }\\n\\n function getBlockNumber() public view returns (uint) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Return the address of the COMP token\\n * @return The address of COMP\\n */\\n function getCompAddress() public view returns (address) {\\n return 0xc00e94Cb662C3520282E6f5717214004A7f26888;\\n }\\n}\\n\",\"keccak256\":\"0x82424556429ca183d7a25069151e77c81007fe7c6cd75d8360c3a2bf7c03db9d\"},\"contracts/ComptrollerInterface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\ncontract ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n bool public constant isComptroller = true;\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata cTokens) external returns (uint[] memory);\\n function exitMarket(address cToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address cToken, address minter, uint mintAmount) external returns (uint);\\n function mintVerify(address cToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address cToken, address redeemer, uint redeemTokens) external returns (uint);\\n function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address cToken, address borrower, uint borrowAmount) external returns (uint);\\n function borrowVerify(address cToken, address borrower, uint borrowAmount) external;\\n\\n function repayBorrowAllowed(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount) external returns (uint);\\n function repayBorrowVerify(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex) external;\\n\\n function liquidateBorrowAllowed(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount) external returns (uint);\\n function liquidateBorrowVerify(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens) external;\\n\\n function seizeAllowed(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external returns (uint);\\n function seizeVerify(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external;\\n\\n function transferAllowed(address cToken, address src, address dst, uint transferTokens) external returns (uint);\\n function transferVerify(address cToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n uint repayAmount) external view returns (uint, uint);\\n}\\n\",\"keccak256\":\"0xede7670d2dd7b25d0187aecd2c28b7b5ca7d7c1bdac144fbedecf5d4bdd92a6b\"},\"contracts/ComptrollerStorage.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.sol\\\";\\nimport \\\"./PriceOracle.sol\\\";\\n\\ncontract UnitrollerAdminStorage {\\n /**\\n * @notice Administrator for this contract\\n */\\n address public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address public pendingAdmin;\\n\\n /**\\n * @notice Active brains of Unitroller\\n */\\n address public comptrollerImplementation;\\n\\n /**\\n * @notice Pending brains of Unitroller\\n */\\n address public pendingComptrollerImplementation;\\n}\\n\\ncontract ComptrollerV1Storage is UnitrollerAdminStorage {\\n\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n PriceOracle public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives\\n */\\n uint public liquidationIncentiveMantissa;\\n\\n /**\\n * @notice Max number of assets a single account can participate in (borrow or use as collateral)\\n */\\n uint public maxAssets;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\\n */\\n mapping(address => CToken[]) public accountAssets;\\n\\n}\\n\\ncontract ComptrollerV2Storage is ComptrollerV1Storage {\\n struct Market {\\n /// @notice Whether or not this market is listed\\n bool isListed;\\n\\n /**\\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\\n * For instance, 0.9 to allow borrowing 90% of collateral value.\\n * Must be between 0 and 1, and stored as a mantissa.\\n */\\n uint collateralFactorMantissa;\\n\\n /// @notice Per-market mapping of \\\"accounts in this asset\\\"\\n mapping(address => bool) accountMembership;\\n\\n /// @notice Whether or not this market receives COMP\\n bool isComped;\\n }\\n\\n /**\\n * @notice Official mapping of cTokens -> Market metadata\\n * @dev Used e.g. to determine if a market is supported\\n */\\n mapping(address => Market) public markets;\\n\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n * Actions which allow users to remove their own assets cannot be paused.\\n * Liquidation / seizing / transfer can only be paused globally, not by market.\\n */\\n address public pauseGuardian;\\n bool public _mintGuardianPaused;\\n bool public _borrowGuardianPaused;\\n bool public transferGuardianPaused;\\n bool public seizeGuardianPaused;\\n mapping(address => bool) public mintGuardianPaused;\\n mapping(address => bool) public borrowGuardianPaused;\\n}\\n\\ncontract ComptrollerV3Storage is ComptrollerV2Storage {\\n struct CompMarketState {\\n /// @notice The market's last updated compBorrowIndex or compSupplyIndex\\n uint224 index;\\n\\n /// @notice The block number the index was last updated at\\n uint32 block;\\n }\\n\\n /// @notice A list of all markets\\n CToken[] public allMarkets;\\n\\n /// @notice The rate at which the flywheel distributes COMP, per block\\n uint public compRate;\\n\\n /// @notice The portion of compRate that each market currently receives\\n mapping(address => uint) public compSpeeds;\\n\\n /// @notice The COMP market supply state for each market\\n mapping(address => CompMarketState) public compSupplyState;\\n\\n /// @notice The COMP market borrow state for each market\\n mapping(address => CompMarketState) public compBorrowState;\\n\\n /// @notice The COMP borrow index for each market for each supplier as of the last time they accrued COMP\\n mapping(address => mapping(address => uint)) public compSupplierIndex;\\n\\n /// @notice The COMP borrow index for each market for each borrower as of the last time they accrued COMP\\n mapping(address => mapping(address => uint)) public compBorrowerIndex;\\n\\n /// @notice The COMP accrued but not yet transferred to each user\\n mapping(address => uint) public compAccrued;\\n}\\n\\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\\n // @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\\n address public borrowCapGuardian;\\n\\n // @notice Borrow caps enforced by borrowAllowed for each cToken address. Defaults to zero which corresponds to unlimited borrowing.\\n mapping(address => uint) public borrowCaps;\\n}\\n\\ncontract ComptrollerV5Storage is ComptrollerV4Storage {\\n /// @notice The portion of COMP that each contributor receives per block\\n mapping(address => uint) public compContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's COMP rewards have been allocated\\n mapping(address => uint) public lastContributorBlock;\\n}\\n\",\"keccak256\":\"0x5db970485549f493618b5e36bfd4d799d4f8701a136bf71ed6e0117e1ed8c254\"},\"contracts/EIP20Interface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title ERC 20 Token Standard Interface\\n * https://eips.ethereum.org/EIPS/eip-20\\n */\\ninterface EIP20Interface {\\n function name() external view returns (string memory);\\n function symbol() external view returns (string memory);\\n function decimals() external view returns (uint8);\\n\\n /**\\n * @notice Get the total number of tokens in circulation\\n * @return The supply of tokens\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @notice Gets the balance of the specified address\\n * @param owner The address from which the balance will be retrieved\\n * @return The balance\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transfer(address dst, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferFrom(address src, address dst, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (-1 means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (-1 means infinite)\\n */\\n function allowance(address owner, address spender) external view returns (uint256 remaining);\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n}\\n\",\"keccak256\":\"0xfd8ed2eac6d0b4d9ee6b32628ba68bae17544b66f190a5f7ce0c6ad024579dc8\"},\"contracts/EIP20NonStandardInterface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title EIP20NonStandardInterface\\n * @dev Version of ERC20 with no return values for `transfer` and `transferFrom`\\n * See https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\\n */\\ninterface EIP20NonStandardInterface {\\n\\n /**\\n * @notice Get the total number of tokens in circulation\\n * @return The supply of tokens\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @notice Gets the balance of the specified address\\n * @param owner The address from which the balance will be retrieved\\n * @return The balance\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n ///\\n /// !!!!!!!!!!!!!!\\n /// !!! NOTICE !!! `transfer` does not return a value, in violation of the ERC-20 specification\\n /// !!!!!!!!!!!!!!\\n ///\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n */\\n function transfer(address dst, uint256 amount) external;\\n\\n ///\\n /// !!!!!!!!!!!!!!\\n /// !!! NOTICE !!! `transferFrom` does not return a value, in violation of the ERC-20 specification\\n /// !!!!!!!!!!!!!!\\n ///\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n */\\n function transferFrom(address src, address dst, uint256 amount) external;\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent\\n */\\n function allowance(address owner, address spender) external view returns (uint256 remaining);\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n}\\n\",\"keccak256\":\"0x9719f12e4b80b51147ac195553a198cf8b0c516e7e4d04fc324a23ed15cbafb2\"},\"contracts/ErrorReporter.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\ncontract ComptrollerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\",\"keccak256\":\"0x5179afb1071c0fd555e5c1f1d2565f72dbe1740cc3dd02f6e52037f150afc5c9\"},\"contracts/Exponential.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CarefulMath.sol\\\";\\nimport \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @dev Legacy contract for compatibility reasons with existing contracts that still use MathError\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: rational}));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({mantissa: result}));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({mantissa: result}));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: scaledMantissa}));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: descaledMantissa}));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) pure internal returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({mantissa: 0}));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({mantissa: product}));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) pure internal returns (MathError, Exp memory) {\\n return mulExp(Exp({mantissa: a}), Exp({mantissa: b}));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) pure internal returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6ff054d65a0289dbb43c9f437d6909f9cf1207c9b8f984b3cb8e97a9de76a434\"},\"contracts/ExponentialNoError.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\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 Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) pure internal returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) pure internal returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) pure internal returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) pure internal returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) pure internal returns (uint224) {\\n require(n < 2**224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) pure internal returns (uint32) {\\n require(n < 2**32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: add_(a.mantissa, b.mantissa)});\\n }\\n\\n function add_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: add_(a.mantissa, b.mantissa)});\\n }\\n\\n function add_(uint a, uint b) pure internal returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: sub_(a.mantissa, b.mantissa)});\\n }\\n\\n function sub_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: sub_(a.mantissa, b.mantissa)});\\n }\\n\\n function sub_(uint a, uint b) pure internal returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: mul_(a.mantissa, b.mantissa) / expScale});\\n }\\n\\n function mul_(Exp memory a, uint b) pure internal returns (Exp memory) {\\n return Exp({mantissa: mul_(a.mantissa, b)});\\n }\\n\\n function mul_(uint a, Exp memory b) pure internal returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: mul_(a.mantissa, b.mantissa) / doubleScale});\\n }\\n\\n function mul_(Double memory a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: mul_(a.mantissa, b)});\\n }\\n\\n function mul_(uint a, Double memory b) pure internal returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) pure internal returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) pure internal 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) pure internal returns (Exp memory) {\\n return Exp({mantissa: div_(mul_(a.mantissa, expScale), b.mantissa)});\\n }\\n\\n function div_(Exp memory a, uint b) pure internal returns (Exp memory) {\\n return Exp({mantissa: div_(a.mantissa, b)});\\n }\\n\\n function div_(uint a, Exp memory b) pure internal returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa)});\\n }\\n\\n function div_(Double memory a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(a.mantissa, b)});\\n }\\n\\n function div_(uint a, Double memory b) pure internal returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) pure internal returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(mul_(a, doubleScale), b)});\\n }\\n}\\n\",\"keccak256\":\"0x7cb184b7cee71a5e707053dfba7eebbd46f11974004028100510ccce19b6694d\"},\"contracts/Governance/Comp.sol\":{\"content\":\"pragma solidity ^0.5.16;\\npragma experimental ABIEncoderV2;\\n\\ncontract Comp {\\n /// @notice EIP-20 token name for this token\\n string public constant name = \\\"Compound\\\";\\n\\n /// @notice EIP-20 token symbol for this token\\n string public constant symbol = \\\"COMP\\\";\\n\\n /// @notice EIP-20 token decimals for this token\\n uint8 public constant decimals = 18;\\n\\n /// @notice Total number of tokens in circulation\\n uint public constant totalSupply = 10000000e18; // 10 million Comp\\n\\n /// @notice Allowance amounts on behalf of others\\n mapping (address => mapping (address => uint96)) internal allowances;\\n\\n /// @notice Official record of token balances for each account\\n mapping (address => uint96) internal balances;\\n\\n /// @notice A record of each accounts delegate\\n mapping (address => address) public delegates;\\n\\n /// @notice A checkpoint for marking number of votes from a given block\\n struct Checkpoint {\\n uint32 fromBlock;\\n uint96 votes;\\n }\\n\\n /// @notice A record of votes checkpoints for each account, by index\\n mapping (address => mapping (uint32 => Checkpoint)) public checkpoints;\\n\\n /// @notice The number of checkpoints for each account\\n mapping (address => uint32) public numCheckpoints;\\n\\n /// @notice The EIP-712 typehash for the contract's domain\\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\\\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\\\");\\n\\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\\\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\\\");\\n\\n /// @notice A record of states for signing / validating signatures\\n mapping (address => uint) public nonces;\\n\\n /// @notice An event thats emitted when an account changes its delegate\\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\\n\\n /// @notice An event thats emitted when a delegate account's vote balance changes\\n event DelegateVotesChanged(address indexed delegate, uint previousBalance, uint newBalance);\\n\\n /// @notice The standard EIP-20 transfer event\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n\\n /// @notice The standard EIP-20 approval event\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n\\n /**\\n * @notice Construct a new Comp token\\n * @param account The initial account to grant all the tokens\\n */\\n constructor(address account) public {\\n balances[account] = uint96(totalSupply);\\n emit Transfer(address(0), account, totalSupply);\\n }\\n\\n /**\\n * @notice Get the number of tokens `spender` is approved to spend on behalf of `account`\\n * @param account The address of the account holding the funds\\n * @param spender The address of the account spending the funds\\n * @return The number of tokens approved\\n */\\n function allowance(address account, address spender) external view returns (uint) {\\n return allowances[account][spender];\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param rawAmount The number of tokens that are approved (2^256-1 means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint rawAmount) external returns (bool) {\\n uint96 amount;\\n if (rawAmount == uint(-1)) {\\n amount = uint96(-1);\\n } else {\\n amount = safe96(rawAmount, \\\"Comp::approve: amount exceeds 96 bits\\\");\\n }\\n\\n allowances[msg.sender][spender] = amount;\\n\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the number of tokens held by the `account`\\n * @param account The address of the account to get the balance of\\n * @return The number of tokens held\\n */\\n function balanceOf(address account) external view returns (uint) {\\n return balances[account];\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param rawAmount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transfer(address dst, uint rawAmount) external returns (bool) {\\n uint96 amount = safe96(rawAmount, \\\"Comp::transfer: amount exceeds 96 bits\\\");\\n _transferTokens(msg.sender, dst, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param rawAmount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferFrom(address src, address dst, uint rawAmount) external returns (bool) {\\n address spender = msg.sender;\\n uint96 spenderAllowance = allowances[src][spender];\\n uint96 amount = safe96(rawAmount, \\\"Comp::approve: amount exceeds 96 bits\\\");\\n\\n if (spender != src && spenderAllowance != uint96(-1)) {\\n uint96 newAllowance = sub96(spenderAllowance, amount, \\\"Comp::transferFrom: transfer amount exceeds spender allowance\\\");\\n allowances[src][spender] = newAllowance;\\n\\n emit Approval(src, spender, newAllowance);\\n }\\n\\n _transferTokens(src, dst, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Delegate votes from `msg.sender` to `delegatee`\\n * @param delegatee The address to delegate votes to\\n */\\n function delegate(address delegatee) public {\\n return _delegate(msg.sender, delegatee);\\n }\\n\\n /**\\n * @notice Delegates votes from signatory to `delegatee`\\n * @param delegatee The address to delegate votes to\\n * @param nonce The contract state required to match the signature\\n * @param expiry The time at which to expire the signature\\n * @param v The recovery byte of the signature\\n * @param r Half of the ECDSA signature pair\\n * @param s Half of the ECDSA signature pair\\n */\\n function delegateBySig(address delegatee, uint nonce, uint expiry, uint8 v, bytes32 r, bytes32 s) public {\\n bytes32 domainSeparator = keccak256(abi.encode(DOMAIN_TYPEHASH, keccak256(bytes(name)), getChainId(), address(this)));\\n bytes32 structHash = keccak256(abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry));\\n bytes32 digest = keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash));\\n address signatory = ecrecover(digest, v, r, s);\\n require(signatory != address(0), \\\"Comp::delegateBySig: invalid signature\\\");\\n require(nonce == nonces[signatory]++, \\\"Comp::delegateBySig: invalid nonce\\\");\\n require(now <= expiry, \\\"Comp::delegateBySig: signature expired\\\");\\n return _delegate(signatory, delegatee);\\n }\\n\\n /**\\n * @notice Gets the current votes balance for `account`\\n * @param account The address to get votes balance\\n * @return The number of current votes for `account`\\n */\\n function getCurrentVotes(address account) external view returns (uint96) {\\n uint32 nCheckpoints = numCheckpoints[account];\\n return nCheckpoints > 0 ? checkpoints[account][nCheckpoints - 1].votes : 0;\\n }\\n\\n /**\\n * @notice Determine the prior number of votes for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param account The address of the account to check\\n * @param blockNumber The block number to get the vote balance at\\n * @return The number of votes the account had as of the given block\\n */\\n function getPriorVotes(address account, uint blockNumber) public view returns (uint96) {\\n require(blockNumber < block.number, \\\"Comp::getPriorVotes: not yet determined\\\");\\n\\n uint32 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (checkpoints[account][nCheckpoints - 1].fromBlock <= blockNumber) {\\n return checkpoints[account][nCheckpoints - 1].votes;\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[account][0].fromBlock > blockNumber) {\\n return 0;\\n }\\n\\n uint32 lower = 0;\\n uint32 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[account][center];\\n if (cp.fromBlock == blockNumber) {\\n return cp.votes;\\n } else if (cp.fromBlock < blockNumber) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return checkpoints[account][lower].votes;\\n }\\n\\n function _delegate(address delegator, address delegatee) internal {\\n address currentDelegate = delegates[delegator];\\n uint96 delegatorBalance = balances[delegator];\\n delegates[delegator] = delegatee;\\n\\n emit DelegateChanged(delegator, currentDelegate, delegatee);\\n\\n _moveDelegates(currentDelegate, delegatee, delegatorBalance);\\n }\\n\\n function _transferTokens(address src, address dst, uint96 amount) internal {\\n require(src != address(0), \\\"Comp::_transferTokens: cannot transfer from the zero address\\\");\\n require(dst != address(0), \\\"Comp::_transferTokens: cannot transfer to the zero address\\\");\\n\\n balances[src] = sub96(balances[src], amount, \\\"Comp::_transferTokens: transfer amount exceeds balance\\\");\\n balances[dst] = add96(balances[dst], amount, \\\"Comp::_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 && amount > 0) {\\n if (srcRep != address(0)) {\\n uint32 srcRepNum = numCheckpoints[srcRep];\\n uint96 srcRepOld = srcRepNum > 0 ? checkpoints[srcRep][srcRepNum - 1].votes : 0;\\n uint96 srcRepNew = sub96(srcRepOld, amount, \\\"Comp::_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 > 0 ? checkpoints[dstRep][dstRepNum - 1].votes : 0;\\n uint96 dstRepNew = add96(dstRepOld, amount, \\\"Comp::_moveVotes: vote amount overflows\\\");\\n _writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew);\\n }\\n }\\n }\\n\\n function _writeCheckpoint(address delegatee, uint32 nCheckpoints, uint96 oldVotes, uint96 newVotes) internal {\\n uint32 blockNumber = safe32(block.number, \\\"Comp::_writeCheckpoint: block number exceeds 32 bits\\\");\\n\\n if (nCheckpoints > 0 && checkpoints[delegatee][nCheckpoints - 1].fromBlock == blockNumber) {\\n checkpoints[delegatee][nCheckpoints - 1].votes = newVotes;\\n } else {\\n checkpoints[delegatee][nCheckpoints] = Checkpoint(blockNumber, newVotes);\\n numCheckpoints[delegatee] = nCheckpoints + 1;\\n }\\n\\n emit DelegateVotesChanged(delegatee, oldVotes, newVotes);\\n }\\n\\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\\n require(n < 2**32, errorMessage);\\n return uint32(n);\\n }\\n\\n function safe96(uint n, string memory errorMessage) internal pure returns (uint96) {\\n require(n < 2**96, errorMessage);\\n return uint96(n);\\n }\\n\\n function add96(uint96 a, uint96 b, string memory errorMessage) internal pure returns (uint96) {\\n uint96 c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub96(uint96 a, uint96 b, string memory errorMessage) internal pure returns (uint96) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function getChainId() internal pure returns (uint) {\\n uint256 chainId;\\n assembly { chainId := chainid() }\\n return chainId;\\n }\\n}\\n\",\"keccak256\":\"0x539f7158013dd91efd3ad42dc6a56e0f7aebdca06063d40ce7b6e9a981b726a3\"},\"contracts/InterestRateModel.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Compound's InterestRateModel Interface\\n * @author Compound\\n */\\ncontract InterestRateModel {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint cash, uint borrows, uint reserves) external view returns (uint);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) external view returns (uint);\\n\\n}\\n\",\"keccak256\":\"0x929282d73c79e6d700ebe79f9fafc1e414b3848acff5a56d6740afd1dc908678\"},\"contracts/PriceOracle.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.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 cToken asset\\n * @param cToken The cToken to get the underlying price of\\n * @return The underlying asset price mantissa (scaled by 1e18).\\n * Zero means the price is unavailable.\\n */\\n function getUnderlyingPrice(CToken cToken) external view returns (uint);\\n}\\n\",\"keccak256\":\"0xe79ebc23bba508eb2479e7b3340abf566da1ab62131f106aee1aac3dc53816ef\"},\"contracts/Unitroller.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ErrorReporter.sol\\\";\\nimport \\\"./ComptrollerStorage.sol\\\";\\n/**\\n * @title ComptrollerCore\\n * @dev Storage for the comptroller is at this address, while execution is delegated to the `comptrollerImplementation`.\\n * CTokens should reference this contract as their comptroller.\\n */\\ncontract Unitroller is UnitrollerAdminStorage, ComptrollerErrorReporter {\\n\\n /**\\n * @notice Emitted when pendingComptrollerImplementation is changed\\n */\\n event NewPendingImplementation(address oldPendingImplementation, address newPendingImplementation);\\n\\n /**\\n * @notice Emitted when pendingComptrollerImplementation is accepted, which means comptroller implementation is updated\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Emitted when pendingAdmin is accepted, which means admin is updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n constructor() public {\\n // Set admin to caller\\n admin = msg.sender;\\n }\\n\\n /*** Admin Functions ***/\\n function _setPendingImplementation(address newPendingImplementation) public returns (uint) {\\n\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_IMPLEMENTATION_OWNER_CHECK);\\n }\\n\\n address oldPendingImplementation = pendingComptrollerImplementation;\\n\\n pendingComptrollerImplementation = newPendingImplementation;\\n\\n emit NewPendingImplementation(oldPendingImplementation, pendingComptrollerImplementation);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts new implementation of comptroller. msg.sender must be pendingImplementation\\n * @dev Admin function for new implementation to accept it's role as implementation\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptImplementation() public returns (uint) {\\n // Check caller is pendingImplementation and pendingImplementation \\u2260 address(0)\\n if (msg.sender != pendingComptrollerImplementation || pendingComptrollerImplementation == address(0)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldImplementation = comptrollerImplementation;\\n address oldPendingImplementation = pendingComptrollerImplementation;\\n\\n comptrollerImplementation = pendingComptrollerImplementation;\\n\\n pendingComptrollerImplementation = address(0);\\n\\n emit NewImplementation(oldImplementation, comptrollerImplementation);\\n emit NewPendingImplementation(oldPendingImplementation, pendingComptrollerImplementation);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPendingAdmin(address newPendingAdmin) public returns (uint) {\\n // Check caller = admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\\n }\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptAdmin() public returns (uint) {\\n // Check caller is pendingAdmin and pendingAdmin \\u2260 address(0)\\n if (msg.sender != pendingAdmin || msg.sender == address(0)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = address(0);\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return 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 () payable external {\\n // delegate all other functions to current implementation\\n (bool success, ) = comptrollerImplementation.delegatecall(msg.data);\\n\\n assembly {\\n let free_mem_ptr := mload(0x40)\\n returndatacopy(free_mem_ptr, 0, returndatasize)\\n\\n switch success\\n case 0 { revert(free_mem_ptr, returndatasize) }\\n default { return(free_mem_ptr, returndatasize) }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x51f81451eab9d5c4849507e724f2b2c53e41f54e5359fdbeae89432a727c16df\"}},\"version\":1}" + }, + "contracts/ComptrollerG4.sol:ComptrollerG4": { + "abi": "[{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"action\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"pauseState\",\"type\":\"bool\"}],\"name\":\"ActionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"action\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"pauseState\",\"type\":\"bool\"}],\"name\":\"ActionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSpeed\",\"type\":\"uint256\"}],\"name\":\"CompSpeedUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compBorrowIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedBorrowerComp\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"supplier\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compSupplyIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedSupplierComp\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isComped\",\"type\":\"bool\"}],\"name\":\"MarketComped\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketEntered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketExited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"MarketListed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCloseFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCloseFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCollateralFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCollateralFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCompRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCompRate\",\"type\":\"uint256\"}],\"name\":\"NewCompRate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldLiquidationIncentiveMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"NewLiquidationIncentive\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMaxAssets\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMaxAssets\",\"type\":\"uint256\"}],\"name\":\"NewMaxAssets\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldPauseGuardian\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"NewPauseGuardian\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"oldPriceOracle\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"newPriceOracle\",\"type\":\"address\"}],\"name\":\"NewPriceOracle\",\"type\":\"event\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"_addCompMarkets\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract Unitroller\",\"name\":\"unitroller\",\"type\":\"address\"}],\"name\":\"_become\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"_dropCompMarket\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setBorrowPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCloseFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCollateralFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"compRate_\",\"type\":\"uint256\"}],\"name\":\"_setCompRate\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"_setLiquidationIncentive\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newMaxAssets\",\"type\":\"uint256\"}],\"name\":\"_setMaxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setMintPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"_setPauseGuardian\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"newOracle\",\"type\":\"address\"}],\"name\":\"_setPriceOracle\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setSeizePaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setTransferPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"_supportMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allMarkets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"checkMembership\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"},{\"internalType\":\"contract CToken[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"holders\",\"type\":\"address[]\"},{\"internalType\":\"contract CToken[]\",\"name\":\"cTokens\",\"type\":\"address[]\"},{\"internalType\":\"bool\",\"name\":\"borrowers\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"suppliers\",\"type\":\"bool\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compAccrued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compBorrowState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compBorrowerIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compClaimThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compInitialIndex\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSupplierIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSupplyState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"enterMarkets\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenAddress\",\"type\":\"address\"}],\"name\":\"exitMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getAllMarkets\",\"outputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAssetsIn\",\"outputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getCompAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenModify\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"getHypotheticalAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"isComptroller\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateCalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"liquidationIncentiveMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"markets\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isComped\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"mintAmount\",\"type\":\"uint256\"}],\"name\":\"mintAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualMintAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"mintTokens\",\"type\":\"uint256\"}],\"name\":\"mintVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"refreshCompSpeeds\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"repayBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowerIndex\",\"type\":\"uint256\"}],\"name\":\"repayBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"seizeGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"transferGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + "bin": "608060405234801561001057600080fd5b50600080546001600160a01b03191633179055615a4980620000336000396000f3fe608060405234801561001057600080fd5b506004361061041c5760003560e01c8063731f0c2b1161022b578063bdcdc25811610130578063dce15449116100b8578063e875544611610087578063e8755446146110ca578063e9af0292146110d2578063eabe7d91146110f8578063ede4edd01461112e578063f851a440146111545761041c565b8063dce1544914611062578063dcfbc0c71461108e578063e4028eee14611096578063e6653f3d146110c25761041c565b8063cc7ebdc4116100ff578063cc7ebdc414610f02578063ce485c5e14610f28578063d02f735114610fc9578063d9226ced1461100f578063da3d454c1461102c5761041c565b8063bdcdc25814610da8578063c299823814610de4578063c488847b14610e85578063ca0af04314610ed45761041c565b80639d1b5a0a116101b3578063abfceffc11610182578063abfceffc14610cec578063ac0b0bb714610d62578063b0772d0b14610d6a578063b21be7fd14610d72578063bb82aa5e14610da05761041c565b80639d1b5a0a14610c92578063a76b3fda14610c9a578063a7f0e23114610cc0578063aa90075414610ce45761041c565b80638c57804e116101fa5780638c57804e14610bcf5780638e8f294b14610bf55780638ebf636414610c3d578063929fe9a114610c5c57806394b2294b14610c8a5761041c565b8063731f0c2b14610b91578063747026c914610bb75780637dc0d1d014610bbf57806387f7630314610bc75761041c565b80634ada90af116103315780635ec88c79116102b95780636a491112116102885780636a49111214610a7e5780636a56947e14610a9b5780636b79c38d14610ad75780636d154ea514610b255780636d35bf9114610b4b5761041c565b80635ec88c79146108c05780635f5af1aa146108e65780635fc7e71e1461090c5780636810dfa6146109525761041c565b80634fd42e17116103005780634fd42e17146107ee57806351dff9891461080b57806352d84d1e1461084757806355ee1fe1146108645780635c7786051461088a5761041c565b80634ada90af1461074e5780634d8e5037146107565780634e79238f1461075e5780634ef4c3e1146107b85761041c565b806326782247116103b45780633bcf7ec1116103835780633bcf7ec1146106885780633c94786f146106b657806341c728b9146106be57806342cbb15c146106fa57806347ef3b3b146107025761041c565b8063267822471461061e5780632d70db7814610626578063317b0b77146106455780633aa729b4146106625761041c565b80631d7b33d7116103f05780631d7b33d7146105445780631ededc911461057c57806324008a62146105be57806324a3d622146105fa5761041c565b80627e3dd21461042157806318c882a51461043d5780631c3db2e01461046b5780631d504dc61461051e575b600080fd5b61042961115c565b604080519115158252519081900360200190f35b6104296004803603604081101561045357600080fd5b506001600160a01b0381351690602001351515611161565b61051c6004803603604081101561048157600080fd5b6001600160a01b038235169190810190604081016020820135600160201b8111156104ab57600080fd5b8201836020820111156104bd57600080fd5b803590602001918460208302840111600160201b831117156104de57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550611301945050505050565b005b61051c6004803603602081101561053457600080fd5b50356001600160a01b0316611363565b61056a6004803603602081101561055a57600080fd5b50356001600160a01b03166114c2565b60408051918252519081900360200190f35b61051c600480360360a081101561059257600080fd5b506001600160a01b038135811691602081013582169160408201351690606081013590608001356114d4565b61056a600480360360808110156105d457600080fd5b506001600160a01b038135811691602081013582169160408201351690606001356114db565b6106026115a4565b604080516001600160a01b039092168252519081900360200190f35b6106026115b3565b6104296004803603602081101561063c57600080fd5b503515156115c2565b61056a6004803603602081101561065b57600080fd5b50356116fc565b61051c6004803603602081101561067857600080fd5b50356001600160a01b031661180d565b6104296004803603604081101561069e57600080fd5b506001600160a01b038135169060200135151561193e565b610429611ad9565b61051c600480360360808110156106d457600080fd5b506001600160a01b03813581169160208101359091169060408101359060600135611ae9565b61056a611aef565b61051c600480360360c081101561071857600080fd5b506001600160a01b0381358116916020810135821691604082013581169160608101359091169060808101359060a00135611af4565b61056a611afc565b61051c611b02565b61079a6004803603608081101561077457600080fd5b506001600160a01b03813581169160208101359091169060408101359060600135611b4a565b60408051938452602084019290925282820152519081900360600190f35b61056a600480360360608110156107ce57600080fd5b506001600160a01b03813581169160208101359091169060400135611b84565b61056a6004803603602081101561080457600080fd5b5035611c2f565b61051c6004803603608081101561082157600080fd5b506001600160a01b03813581169160208101359091169060408101359060600135611d23565b6106026004803603602081101561085d57600080fd5b5035611d77565b61056a6004803603602081101561087a57600080fd5b50356001600160a01b0316611d9e565b61051c600480360360608110156108a057600080fd5b506001600160a01b03813581169160208101359091169060400135611e25565b61079a600480360360208110156108d657600080fd5b50356001600160a01b0316611e2a565b61056a600480360360208110156108fc57600080fd5b50356001600160a01b0316611e5f565b61056a600480360360a081101561092257600080fd5b506001600160a01b0381358116916020810135821691604082013581169160608101359091169060800135611ee3565b61051c6004803603608081101561096857600080fd5b810190602081018135600160201b81111561098257600080fd5b82018360208201111561099457600080fd5b803590602001918460208302840111600160201b831117156109b557600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b811115610a0457600080fd5b820183602082011115610a1657600080fd5b803590602001918460208302840111600160201b83111715610a3757600080fd5b91908080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525092955050505080351515915060200135151561206a565b61051c60048036036020811015610a9457600080fd5b5035612213565b61051c60048036036080811015610ab157600080fd5b506001600160a01b03813581169160208101358216916040820135169060600135611ae9565b610afd60048036036020811015610aed57600080fd5b50356001600160a01b03166122b7565b604080516001600160e01b03909316835263ffffffff90911660208301528051918290030190f35b61042960048036036020811015610b3b57600080fd5b50356001600160a01b03166122e1565b61051c600480360360a0811015610b6157600080fd5b506001600160a01b03813581169160208101358216916040820135811691606081013590911690608001356114d4565b61042960048036036020811015610ba757600080fd5b50356001600160a01b03166122f6565b61056a61230b565b610602612316565b610429612325565b610afd60048036036020811015610be557600080fd5b50356001600160a01b0316612335565b610c1b60048036036020811015610c0b57600080fd5b50356001600160a01b031661235f565b6040805193151584526020840192909252151582820152519081900360600190f35b61042960048036036020811015610c5357600080fd5b50351515612385565b61042960048036036040811015610c7257600080fd5b506001600160a01b03813581169160200135166124be565b61056a6124f1565b6106026124f7565b61056a60048036036020811015610cb057600080fd5b50356001600160a01b031661250f565b610cc861266c565b604080516001600160e01b039092168252519081900360200190f35b61056a61267f565b610d1260048036036020811015610d0257600080fd5b50356001600160a01b0316612685565b60408051602080825283518183015283519192839290830191858101910280838360005b83811015610d4e578181015183820152602001610d36565b505050509050019250505060405180910390f35b61042961270e565b610d1261271e565b61056a60048036036040811015610d8857600080fd5b506001600160a01b0381358116916020013516612780565b61060261279d565b61056a60048036036080811015610dbe57600080fd5b506001600160a01b038135811691602081013582169160408201351690606001356127ac565b610d1260048036036020811015610dfa57600080fd5b810190602081018135600160201b811115610e1457600080fd5b820183602082011115610e2657600080fd5b803590602001918460208302840111600160201b83111715610e4757600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550612840945050505050565b610ebb60048036036060811015610e9b57600080fd5b506001600160a01b038135811691602081013590911690604001356128d7565b6040805192835260208301919091528051918290030190f35b61056a60048036036040811015610eea57600080fd5b506001600160a01b0381358116916020013516612b4c565b61056a60048036036020811015610f1857600080fd5b50356001600160a01b0316612b69565b61051c60048036036020811015610f3e57600080fd5b810190602081018135600160201b811115610f5857600080fd5b820183602082011115610f6a57600080fd5b803590602001918460208302840111600160201b83111715610f8b57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550612b7b945050505050565b61056a600480360360a0811015610fdf57600080fd5b506001600160a01b0381358116916020810135821691604082013581169160608101359091169060800135612c0d565b61056a6004803603602081101561102557600080fd5b5035612dc5565b61056a6004803603606081101561104257600080fd5b506001600160a01b03813581169160208101359091169060400135612e2e565b6106026004803603604081101561107857600080fd5b506001600160a01b03813516906020013561311b565b610602613150565b61056a600480360360408110156110ac57600080fd5b506001600160a01b03813516906020013561315f565b61042961330f565b61056a61331f565b61051c600480360360208110156110e857600080fd5b50356001600160a01b0316613325565b61056a6004803603606081101561110e57600080fd5b506001600160a01b03813581169160208101359091169060400135613389565b61056a6004803603602081101561114457600080fd5b50356001600160a01b03166133c6565b6106026136d9565b600181565b6001600160a01b03821660009081526009602052604081205460ff166111b85760405162461bcd60e51b81526004018080602001828103825260288152602001806159296028913960400191505060405180910390fd5b600a546001600160a01b03163314806111db57506000546001600160a01b031633145b6112165760405162461bcd60e51b81526004018080602001828103825260278152602001806159826027913960400191505060405180910390fd5b6000546001600160a01b031633148061123157506001821515145b61127b576040805162461bcd60e51b81526020600482015260166024820152756f6e6c792061646d696e2063616e20756e706175736560501b604482015290519081900360640190fd5b6001600160a01b0383166000818152600c6020908152604091829020805486151560ff199091168117909155825193845283830152606090830181905260069083015265426f72726f7760d01b6080830152517f71aec636243f9709bb0007ae15e9afb8150ab01716d75fd7573be5cc096e03b09181900360a00190a150805b92915050565b60408051600180825281830190925260609160208083019080388339019050509050828160008151811061133157fe5b60200260200101906001600160a01b031690816001600160a01b03168152505061135e818360018061206a565b505050565b806001600160a01b031663f851a4406040518163ffffffff1660e01b815260040160206040518083038186803b15801561139c57600080fd5b505afa1580156113b0573d6000803e3d6000fd5b505050506040513d60208110156113c657600080fd5b50516001600160a01b0316331461140e5760405162461bcd60e51b81526004018080602001828103825260278152602001806159ee6027913960400191505060405180910390fd5b806001600160a01b031663c1e803346040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561144957600080fd5b505af115801561145d573d6000803e3d6000fd5b505050506040513d602081101561147357600080fd5b5051156114bf576040805162461bcd60e51b815260206004820152601560248201527418da185b99d9481b9bdd08185d5d1a1bdc9a5e9959605a1b604482015290519081900360640190fd5b50565b600f6020526000908152604090205481565b5050505050565b6001600160a01b03841660009081526009602052604081205460ff166115035750600961159c565b61150b615869565b6040518060200160405280876001600160a01b031663aa5af0fd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561154f57600080fd5b505afa158015611563573d6000803e3d6000fd5b505050506040513d602081101561157957600080fd5b50519052905061158986826136e8565b6115968685836000613970565b60009150505b949350505050565b600a546001600160a01b031681565b6001546001600160a01b031681565b600a546000906001600160a01b03163314806115e857506000546001600160a01b031633145b6116235760405162461bcd60e51b81526004018080602001828103825260278152602001806159826027913960400191505060405180910390fd5b6000546001600160a01b031633148061163e57506001821515145b611688576040805162461bcd60e51b81526020600482015260166024820152756f6e6c792061646d696e2063616e20756e706175736560501b604482015290519081900360640190fd5b600a8054831515600160b81b810260ff60b81b1990921691909117909155604080516020810192909252808252600582820152645365697a6560d81b6060830152517fef159d9a32b2472e32b098f954f3ce62d232939f1c207070b584df1814de2de09181900360800190a150805b919050565b600080546001600160a01b031633146117225761171b60016004613b5b565b90506116f7565b61172a615869565b506040805160208101909152828152611741615869565b50604080516020810190915266b1a2bc2ec5000081526117618282613bc1565b1561177a57611771600580613b5b565b925050506116f7565b611782615869565b506040805160208101909152670c7d713b49da000081526117a38184613bc9565b156117bd576117b3600580613b5b565b93505050506116f7565b6005805490869055604080518281526020810188905281517f3b9670cf975d26958e754b57098eaa2ac914d8d2a31b83257997b9f346110fd9929181900390910190a160005b9695505050505050565b6000546001600160a01b0316331461186c576040805162461bcd60e51b815260206004820152601f60248201527f6f6e6c792061646d696e2063616e2064726f7020636f6d70206d61726b657400604482015290519081900360640190fd5b6001600160a01b0381166000908152600960205260409020600381015460ff1615156001146118e2576040805162461bcd60e51b815260206004820152601b60248201527f6d61726b6574206973206e6f74206120636f6d70206d61726b65740000000000604482015290519081900360640190fd5b60038101805460ff19169055604080516001600160a01b03841681526000602082015281517f93c1f3e36ed71139f466a4ce8c9751790e2e33f5afb2df0dcfb3aeabe55d5aa2929181900390910190a161193a613bd0565b5050565b6001600160a01b03821660009081526009602052604081205460ff166119955760405162461bcd60e51b81526004018080602001828103825260288152602001806159296028913960400191505060405180910390fd5b600a546001600160a01b03163314806119b857506000546001600160a01b031633145b6119f35760405162461bcd60e51b81526004018080602001828103825260278152602001806159826027913960400191505060405180910390fd5b6000546001600160a01b0316331480611a0e57506001821515145b611a58576040805162461bcd60e51b81526020600482015260166024820152756f6e6c792061646d696e2063616e20756e706175736560501b604482015290519081900360640190fd5b6001600160a01b0383166000818152600b6020908152604091829020805486151560ff199091168117909155825193845283830152606090830181905260049083015263135a5b9d60e21b6080830152517f71aec636243f9709bb0007ae15e9afb8150ab01716d75fd7573be5cc096e03b09181900360a00190a150919050565b600a54600160a01b900460ff1681565b50505050565b435b90565b505050505050565b60065481565b333214611b405760405162461bcd60e51b81526004018080602001828103825260318152602001806159516031913960400191505060405180910390fd5b611b48613bd0565b565b600080600080600080611b5f8a8a8a8a613f95565b925092509250826011811115611b7157fe5b95509093509150505b9450945094915050565b6001600160a01b0383166000908152600b602052604081205460ff1615611be3576040805162461bcd60e51b815260206004820152600e60248201526d1b5a5b9d081a5cc81c185d5cd95960921b604482015290519081900360640190fd5b6001600160a01b03841660009081526009602052604090205460ff16611c0d5760095b9050611c28565b611c16846143b0565b611c228484600061462e565b60005b90505b9392505050565b600080546001600160a01b03163314611c4e5761171b6001600b613b5b565b611c56615869565b506040805160208101909152828152611c6d615869565b506040805160208101909152670de0b6b3a76400008152611c8e8282613bc9565b15611c9f576117716007600c613b5b565b611ca7615869565b5060408051602081019091526714d1120d7b1600008152611cc88184613bc9565b15611cd9576117b36007600c613b5b565b6006805490869055604080518281526020810188905281517faeba5a6c40a8ac138134bff1aaa65debf25971188a58804bad717f82f0ec1316929181900390910190a16000611803565b80158015611d315750600082115b15611ae9576040805162461bcd60e51b815260206004820152601160248201527072656465656d546f6b656e73207a65726f60781b604482015290519081900360640190fd5b600d8181548110611d8457fe5b6000918252602090912001546001600160a01b0316905081565b600080546001600160a01b03163314611dbd5761171b60016010613b5b565b600480546001600160a01b038481166001600160a01b0319831681179093556040805191909216808252602082019390935281517fd52b2b9b7e9ee655fcb95d2e5b9e0c9f69e7ef2b8e9d2d0ea78402d576d22e22929181900390910190a160009392505050565b61135e565b600080600080600080611e41876000806000613f95565b925092509250826011811115611e5357fe5b97919650945092505050565b600080546001600160a01b03163314611e7e5761171b60016013613b5b565b600a80546001600160a01b038481166001600160a01b0319831617928390556040805192821680845293909116602083015280517f0613b6ee6a04f0d09f390e4d9318894b9f6ac7fd83897cd8d18896ba579c401e9281900390910190a16000611c28565b6001600160a01b03851660009081526009602052604081205460ff161580611f2457506001600160a01b03851660009081526009602052604090205460ff16155b15611f335760095b9050612061565b600080611f3f85614826565b91935090915060009050826011811115611f5557fe5b14611f6f57816011811115611f6657fe5b92505050612061565b80611f7b576003611f66565b6000886001600160a01b03166395dd9193876040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015611fd357600080fd5b505afa158015611fe7573d6000803e3d6000fd5b505050506040513d6020811015611ffd57600080fd5b50516040805160208101909152600554815290915060009081906120219084614846565b9092509050600082600381111561203457fe5b1461204857600b5b95505050505050612061565b8087111561205757601161203c565b6000955050505050505b95945050505050565b60005b83518110156114d457600084828151811061208457fe5b6020908102919091018101516001600160a01b0381166000908152600990925260409091205490915060ff166120f9576040805162461bcd60e51b81526020600482015260156024820152741b585c9ad95d081b5d5cdd081899481b1a5cdd1959605a1b604482015290519081900360640190fd5b600184151514156121c15761210c615869565b6040518060200160405280836001600160a01b031663aa5af0fd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561215057600080fd5b505afa158015612164573d6000803e3d6000fd5b505050506040513d602081101561217a57600080fd5b50519052905061218a82826136e8565b60005b87518110156121be576121b6838983815181106121a657fe5b6020026020010151846001613970565b60010161218d565b50505b6001831515141561220a576121d5816143b0565b60005b865181101561220857612200828883815181106121f157fe5b6020026020010151600161462e565b6001016121d8565b505b5060010161206d565b61221b61489a565b61226c576040805162461bcd60e51b815260206004820152601f60248201527f6f6e6c792061646d696e2063616e206368616e676520636f6d70207261746500604482015290519081900360640190fd5b600e805490829055604080518281526020810184905281517fc227c9272633c3a307d9845bf2bc2509cefb20d655b5f3c1002d8e1e3f22c8b0929181900390910190a161193a613bd0565b6010602052600090815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b600c6020526000908152604090205460ff1681565b600b6020526000908152604090205460ff1681565b66038d7ea4c6800081565b6004546001600160a01b031681565b600a54600160b01b900460ff1681565b6011602052600090815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b60096020526000908152604090208054600182015460039092015460ff91821692911683565b600a546000906001600160a01b03163314806123ab57506000546001600160a01b031633145b6123e65760405162461bcd60e51b81526004018080602001828103825260278152602001806159826027913960400191505060405180910390fd5b6000546001600160a01b031633148061240157506001821515145b61244b576040805162461bcd60e51b81526020600482015260166024820152756f6e6c792061646d696e2063616e20756e706175736560501b604482015290519081900360640190fd5b600a8054831515600160b01b810260ff60b01b1990921691909117909155604080516020810192909252808252600882820152672a3930b739b332b960c11b6060830152517fef159d9a32b2472e32b098f954f3ce62d232939f1c207070b584df1814de2de09181900360800190a15090565b6001600160a01b038082166000908152600960209081526040808320938616835260029093019052205460ff1692915050565b60075481565b73c00e94cb662c3520282e6f5717214004a7f2688890565b600080546001600160a01b0316331461252e5761171b60016012613b5b565b6001600160a01b03821660009081526009602052604090205460ff161561255b5761171b600a6011613b5b565b816001600160a01b031663fe9c44ae6040518163ffffffff1660e01b815260040160206040518083038186803b15801561259457600080fd5b505afa1580156125a8573d6000803e3d6000fd5b505050506040513d60208110156125be57600080fd5b5050604080516060810182526001808252600060208381018281528486018381526001600160a01b03891684526009909252949091209251835490151560ff19918216178455935191830191909155516003909101805491151591909216179055612628826148c3565b604080516001600160a01b038416815290517fcf583bb0c569eb967f806b11601c4cb93c10310485c67add5f8362c2f212321f9181900360200190a1600092915050565b6ec097ce7bc90715b34b9f100000000081565b600e5481565b60608060086000846001600160a01b03166001600160a01b0316815260200190815260200160002080548060200260200160405190810160405280929190818152602001828054801561270157602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116126e3575b5093979650505050505050565b600a54600160b81b900460ff1681565b6060600d80548060200260200160405190810160405280929190818152602001828054801561277657602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612758575b5050505050905090565b601260209081526000928352604080842090915290825290205481565b6002546001600160a01b031681565b600a54600090600160b01b900460ff1615612803576040805162461bcd60e51b81526020600482015260126024820152711d1c985b9cd9995c881a5cc81c185d5cd95960721b604482015290519081900360640190fd5b60006128108686856149a1565b9050801561281f57905061159c565b612828866143b0565b6128348686600061462e565b6115968685600061462e565b6060600082519050606081604051908082528060200260200182016040528015612874578160200160208202803883390190505b50905060005b828110156128cf57600085828151811061289057fe5b602002602001015190506128a48133614a44565b60118111156128af57fe5b8383815181106128bb57fe5b60209081029190910101525060010161287a565b509392505050565b600480546040805163fc57d4df60e01b81526001600160a01b038781169482019490945290516000938493849391169163fc57d4df91602480820192602092909190829003018186803b15801561292d57600080fd5b505afa158015612941573d6000803e3d6000fd5b505050506040513d602081101561295757600080fd5b5051600480546040805163fc57d4df60e01b81526001600160a01b038a8116948201949094529051939450600093929091169163fc57d4df91602480820192602092909190829003018186803b1580156129b057600080fd5b505afa1580156129c4573d6000803e3d6000fd5b505050506040513d60208110156129da57600080fd5b505190508115806129e9575080155b156129fe57600d935060009250612b44915050565b6000866001600160a01b031663182df0f56040518163ffffffff1660e01b815260040160206040518083038186803b158015612a3957600080fd5b505afa158015612a4d573d6000803e3d6000fd5b505050506040513d6020811015612a6357600080fd5b505190506000612a71615869565b612a79615869565b612a81615869565b6000612a8f60065489614b65565b945090506000816003811115612aa157fe5b14612abd57600b5b995060009850612b44975050505050505050565b612ac78787614b65565b935090506000816003811115612ad957fe5b14612ae557600b612aa9565b612aef8484614ba0565b925090506000816003811115612b0157fe5b14612b0d57600b612aa9565b612b17828c614846565b955090506000816003811115612b2957fe5b14612b3557600b612aa9565b60009950939750505050505050505b935093915050565b601360209081526000928352604080842090915290825290205481565b60146020526000908152604090205481565b612b8361489a565b612bd4576040805162461bcd60e51b815260206004820152601e60248201527f6f6e6c792061646d696e2063616e2061646420636f6d70206d61726b65740000604482015290519081900360640190fd5b60005b8151811015612c0457612bfc828281518110612bef57fe5b6020026020010151614bb8565b600101612bd7565b506114bf613bd0565b600a54600090600160b81b900460ff1615612c61576040805162461bcd60e51b815260206004820152600f60248201526e1cd95a5e99481a5cc81c185d5cd959608a1b604482015290519081900360640190fd5b6001600160a01b03861660009081526009602052604090205460ff161580612ca257506001600160a01b03851660009081526009602052604090205460ff16155b15612cae576009611f2c565b846001600160a01b0316635fe3b5676040518163ffffffff1660e01b815260040160206040518083038186803b158015612ce757600080fd5b505afa158015612cfb573d6000803e3d6000fd5b505050506040513d6020811015612d1157600080fd5b505160408051635fe3b56760e01b815290516001600160a01b0392831692891691635fe3b567916004808301926020929190829003018186803b158015612d5757600080fd5b505afa158015612d6b573d6000803e3d6000fd5b505050506040513d6020811015612d8157600080fd5b50516001600160a01b031614612d98576002611f2c565b612da1866143b0565b612dad8684600061462e565b612db98685600061462e565b60009695505050505050565b600080546001600160a01b03163314612de45761171b6001600d613b5b565b6007805490839055604080518281526020810185905281517f7093cf1eb653f749c3ff531d6df7f92764536a7fa0d13530cd26e070780c32ea929181900390910190a16000611c28565b6001600160a01b0383166000908152600c602052604081205460ff1615612e8f576040805162461bcd60e51b815260206004820152601060248201526f189bdc9c9bddc81a5cc81c185d5cd95960821b604482015290519081900360640190fd5b6001600160a01b03841660009081526009602052604090205460ff16612eb6576009611c06565b6001600160a01b038085166000908152600960209081526040808320938716835260029093019052205460ff16612fa657336001600160a01b03851614612f3c576040805162461bcd60e51b815260206004820152601560248201527439b2b73232b91036bab9ba1031329031aa37b5b2b760591b604482015290519081900360640190fd5b6000612f483385614a44565b90506000816011811115612f5857fe5b14612f7157806011811115612f6957fe5b915050611c28565b6001600160a01b038086166000908152600960209081526040808320938816835260029093019052205460ff16612fa457fe5b505b600480546040805163fc57d4df60e01b81526001600160a01b03888116948201949094529051929091169163fc57d4df91602480820192602092909190829003018186803b158015612ff757600080fd5b505afa15801561300b573d6000803e3d6000fd5b505050506040513d602081101561302157600080fd5b505161302e57600d611c06565b60008061303e8587600087613f95565b9193509091506000905082601181111561305457fe5b1461306e5781601181111561306557fe5b92505050611c28565b801561307b576004613065565b613083615869565b6040518060200160405280886001600160a01b031663aa5af0fd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156130c757600080fd5b505afa1580156130db573d6000803e3d6000fd5b505050506040513d60208110156130f157600080fd5b50519052905061310187826136e8565b61310e8787836000613970565b6000979650505050505050565b6008602052816000526040600020818154811061313457fe5b6000918252602090912001546001600160a01b03169150829050565b6003546001600160a01b031681565b600080546001600160a01b031633146131855761317e60016006613b5b565b90506112fb565b6001600160a01b0383166000908152600960205260409020805460ff166131ba576131b260096007613b5b565b9150506112fb565b6131c2615869565b5060408051602081019091528381526131d9615869565b506040805160208101909152670c7d713b49da000081526131fa8183613bc9565b156132155761320b60066008613b5b565b93505050506112fb565b841580159061329e5750600480546040805163fc57d4df60e01b81526001600160a01b038a8116948201949094529051929091169163fc57d4df91602480820192602092909190829003018186803b15801561327057600080fd5b505afa158015613284573d6000803e3d6000fd5b505050506040513d602081101561329a57600080fd5b5051155b156132af5761320b600d6009613b5b565b60018301805490869055604080516001600160a01b03891681526020810183905280820188905290517f70483e6592cd5182d45ac970e05bc62cdcc90e9d8ef2c2dbe686cf383bcd7fc59181900360600190a16000979650505050505050565b600a54600160a81b900460ff1681565b60055481565b6114bf81600d80548060200260200160405190810160405280929190818152602001828054801561337f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311613361575b5050505050611301565b6000806133978585856149a1565b905080156133a6579050611c28565b6133af856143b0565b6133bb8585600061462e565b600095945050505050565b6000808290506000806000836001600160a01b031663c37f68e2336040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060806040518083038186803b15801561342757600080fd5b505afa15801561343b573d6000803e3d6000fd5b505050506040513d608081101561345157600080fd5b5080516020820151604090920151909450909250905082156134a45760405162461bcd60e51b81526004018080602001828103825260258152602001806159a96025913960400191505060405180910390fd5b80156134c1576134b6600c6002613b5b565b9450505050506116f7565b60006134ce8733856149a1565b905080156134ef576134e3600e600383614ed3565b955050505050506116f7565b6001600160a01b0385166000908152600960209081526040808320338452600281019092529091205460ff1661352e57600096505050505050506116f7565b3360009081526002820160209081526040808320805460ff1916905560088252918290208054835181840281018401909452808452606093928301828280156135a057602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311613582575b5050835193945083925060009150505b828110156135f557896001600160a01b03168482815181106135ce57fe5b60200260200101516001600160a01b031614156135ed578091506135f5565b6001016135b0565b508181106135ff57fe5b33600090815260086020526040902080548190600019810190811061362057fe5b9060005260206000200160009054906101000a90046001600160a01b031681838154811061364a57fe5b600091825260209091200180546001600160a01b0319166001600160a01b0392909216919091179055805461368382600019830161587c565b50604080516001600160a01b038c16815233602082015281517fe699a64c18b07ac5b7301aa273f36a2287239eb9501d81950672794afba29a0d929181900390910190a160009c9b505050505050505050505050565b6000546001600160a01b031681565b6001600160a01b0382166000908152601160209081526040808320600f9092528220549091613715611aef565b8354909150600090613735908390600160e01b900463ffffffff16614f39565b90506000811180156137475750600083115b156139165760006137bc876001600160a01b03166347bd37186040518163ffffffff1660e01b815260040160206040518083038186803b15801561378a57600080fd5b505afa15801561379e573d6000803e3d6000fd5b505050506040513d60208110156137b457600080fd5b505187614f73565b905060006137ca8386614f91565b90506137d4615869565b600083116137f157604051806020016040528060008152506137fb565b6137fb8284614fd3565b9050613805615869565b604080516020810190915288546001600160e01b031681526138279083615011565b9050604051806040016040528061387783600001516040518060400160405280601a81526020017f6e657720696e6465782065786365656473203232342062697473000000000000815250615036565b6001600160e01b031681526020016138b2886040518060400160405280601c81526020016000805160206159ce8339815191528152506150d0565b63ffffffff9081169091526001600160a01b038c166000908152601160209081526040909120835181549490920151909216600160e01b026001600160e01b039182166001600160e01b0319909416939093171691909117905550611af492505050565b8015611af457613949826040518060400160405280601c81526020016000805160206159ce8339815191528152506150d0565b845463ffffffff91909116600160e01b026001600160e01b03909116178455505050505050565b6001600160a01b0384166000908152601160205260409020613990615869565b50604080516020810190915281546001600160e01b031681526139b1615869565b5060408051602080820183526001600160a01b03808a16600090815260138352848120918a1680825282845294812080548552865195909152915291909155805115613b52576139ff615869565b613a098383615125565b90506000613a98896001600160a01b03166395dd91938a6040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015613a6657600080fd5b505afa158015613a7a573d6000803e3d6000fd5b505050506040513d6020811015613a9057600080fd5b505188614f73565b90506000613aa6828461514a565b6001600160a01b038a1660009081526014602052604081205491925090613acd9083615179565b9050613aee8a828a613ae65766038d7ea4c68000613ae9565b60005b6151af565b6001600160a01b03808c1660008181526014602090815260409182902094909455895181518781529485015280519193928f16927f1fc3ecc087d8d2d15e23d0032af5a47059c3892d003d8e139fdcb6bb327c99a6929081900390910190a3505050505b50505050505050565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0836011811115613b8a57fe5b836013811115613b9657fe5b604080519283526020830191909152600082820152519081900360600190a1826011811115611c2857fe5b519051111590565b5190511090565b6060600d805480602002602001604051908101604052809291908181526020018280548015613c2857602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311613c0a575b50939450600093505050505b8151811015613cee576000828281518110613c4b57fe5b60200260200101519050613c5d615869565b6040518060200160405280836001600160a01b031663aa5af0fd6040518163ffffffff1660e01b815260040160206040518083038186803b158015613ca157600080fd5b505afa158015613cb5573d6000803e3d6000fd5b505050506040513d6020811015613ccb57600080fd5b505190529050613cda826143b0565b613ce482826136e8565b5050600101613c34565b50613cf7615869565b60405180602001604052806000815250905060608251604051908082528060200260200182016040528015613d4657816020015b613d33615869565b815260200190600190039081613d2b5790505b50905060005b8351811015613ecc576000848281518110613d6357fe5b6020908102919091018101516001600160a01b0381166000908152600990925260409091206003015490915060ff1615613ec357613d9f615869565b60408051602080820180845260045463fc57d4df60e01b9091526001600160a01b03868116602485015293519293849391169163fc57d4df916044808601929190818703018186803b158015613df457600080fd5b505afa158015613e08573d6000803e3d6000fd5b505050506040513d6020811015613e1e57600080fd5b505190529050613e2c615869565b613e9a82846001600160a01b03166347bd37186040518163ffffffff1660e01b815260040160206040518083038186803b158015613e6957600080fd5b505afa158015613e7d573d6000803e3d6000fd5b505050506040513d6020811015613e9357600080fd5b50516152f4565b905080858581518110613ea957fe5b6020026020010181905250613ebe8682615011565b955050505b50600101613d4c565b5060005b8351811015611ae9576000600d8281548110613ee857fe5b600091825260208220015485516001600160a01b039091169250613f0d576000613f35565b613f35600e54613f30868681518110613f2257fe5b602002602001015188615315565b615348565b6001600160a01b0383166000818152600f60209081526040918290208490558151848152915193945091927f2ab93f65628379309f36cb125e90d7c902454a545c4f8b8cb0794af75c24b807929181900390910190a25050600101613ed0565b6000806000613fa26158a0565b6001600160a01b03881660009081526008602090815260408083208054825181850281018501909352808352849360609392919083018282801561400f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311613ff1575b50939450600093505050505b815181101561436b57600082828151811061403257fe5b60200260200101519050806001600160a01b031663c37f68e28e6040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060806040518083038186803b15801561409257600080fd5b505afa1580156140a6573d6000803e3d6000fd5b505050506040513d60808110156140bc57600080fd5b508051602082015160408084015160609485015160808c0152938a019390935291880191909152945084156141025750600f975060009650869550611b7a945050505050565b60408051602080820183526001600160a01b0380851660008181526009845285902060010154845260c08b01939093528351808301855260808b0151815260e08b015260048054855163fc57d4df60e01b815291820194909452935192169263fc57d4df9260248083019392829003018186803b15801561418257600080fd5b505afa158015614196573d6000803e3d6000fd5b505050506040513d60208110156141ac57600080fd5b505160a087018190526141d05750600d975060009650869550611b7a945050505050565b604080516020810190915260a08701518152610100870181905260c087015160e08801516141fd92615361565b6101208801529350600084600381111561421357fe5b1461422f5750600b975060009650869550611b7a945050505050565b614247866101200151876040015188600001516153b9565b87529350600084600381111561425957fe5b146142755750600b975060009650869550611b7a945050505050565b61428d866101000151876060015188602001516153b9565b6020880152935060008460038111156142a257fe5b146142be5750600b975060009650869550611b7a945050505050565b8b6001600160a01b0316816001600160a01b03161415614362576142ec8661012001518c88602001516153b9565b60208801529350600084600381111561430157fe5b1461431d5750600b975060009650869550611b7a945050505050565b6143318661010001518b88602001516153b9565b60208801529350600084600381111561434657fe5b146143625750600b975060009650869550611b7a945050505050565b5060010161401b565b50602084015184511115614392575050506020810151905160009450039150829050611b7a565b5050815160209092015160009550859450919091039150611b7a9050565b6001600160a01b0381166000908152601060209081526040808320600f90925282205490916143dd611aef565b83549091506000906143fd908390600160e01b900463ffffffff16614f39565b905060008111801561440f5750600083115b156145d5576000856001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561444f57600080fd5b505afa158015614463573d6000803e3d6000fd5b505050506040513d602081101561447957600080fd5b5051905060006144898386614f91565b9050614493615869565b600083116144b057604051806020016040528060008152506144ba565b6144ba8284614fd3565b90506144c4615869565b604080516020810190915288546001600160e01b031681526144e69083615011565b9050604051806040016040528061453683600001516040518060400160405280601a81526020017f6e657720696e6465782065786365656473203232342062697473000000000000815250615036565b6001600160e01b03168152602001614571886040518060400160405280601c81526020016000805160206159ce8339815191528152506150d0565b63ffffffff9081169091526001600160a01b038b166000908152601060209081526040909120835181549490920151909216600160e01b026001600160e01b039182166001600160e01b03199094169390931716919091179055506114d492505050565b80156114d457614608826040518060400160405280601c81526020016000805160206159ce8339815191528152506150d0565b845463ffffffff91909116600160e01b026001600160e01b039091161784555050505050565b6001600160a01b038316600090815260106020526040902061464e615869565b50604080516020810190915281546001600160e01b0316815261466f615869565b5060408051602080820183526001600160a01b038089166000908152601283528481209189168082528284529481208054855286519590915291529190915580511580156146bd5750815115155b156146d5576ec097ce7bc90715b34b9f100000000081525b6146dd615869565b6146e78383615125565b90506000876001600160a01b03166370a08231886040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561474157600080fd5b505afa158015614755573d6000803e3d6000fd5b505050506040513d602081101561476b57600080fd5b50519050600061477b828461514a565b6001600160a01b038916600090815260146020526040812054919250906147a29083615179565b90506147bb89828a613ae65766038d7ea4c68000613ae9565b6001600160a01b03808b1660008181526014602090815260409182902094909455895181518781529485015280519193928e16927f2caecd17d02f56fa897705dcc740da2d237c373f70686f4e0d9bd3bf0400ea7a929081900390910190a350505050505050505050565b6000806000614839846000806000613f95565b9250925092509193909250565b6000806000614853615869565b61485d8686615406565b9092509050600082600381111561487057fe5b146148815750915060009050614893565b600061488c8261546e565b9350935050505b9250929050565b600080546001600160a01b03163314806148be57506002546001600160a01b031633145b905090565b60005b600d5481101561494e57816001600160a01b0316600d82815481106148e757fe5b6000918252602090912001546001600160a01b03161415614946576040805162461bcd60e51b81526020600482015260146024820152731b585c9ad95d08185b1c9958591e48185919195960621b604482015290519081900360640190fd5b6001016148c6565b50600d80546001810182556000919091527fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb50180546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b03831660009081526009602052604081205460ff166149c8576009611c06565b6001600160a01b038085166000908152600960209081526040808320938716835260029093019052205460ff16614a00576000611c06565b600080614a108587866000613f95565b91935090915060009050826011811115614a2657fe5b14614a375781601181111561306557fe5b8015612db9576004613065565b6001600160a01b0382166000908152600960205260408120805460ff16614a6f5760099150506112fb565b6001600160a01b038316600090815260028201602052604090205460ff16151560011415614aa15760009150506112fb565b6007546001600160a01b03841660009081526008602052604090205410614acc5760109150506112fb565b6001600160a01b0380841660008181526002840160209081526040808320805460ff19166001908117909155600883528184208054918201815584529282902090920180549489166001600160a01b031990951685179055815193845283019190915280517f3ab23ab0d51cccc0c3085aec51f99228625aa1a922b3a8ca89a26b0f2027a1a59281900390910190a15060009392505050565b6000614b6f615869565b614b9560405180602001604052808681525060405180602001604052808681525061547d565b915091509250929050565b6000614baa615869565b83518351614b959190615566565b6001600160a01b0381166000908152600960205260409020805460ff161515600114614c2b576040805162461bcd60e51b815260206004820152601960248201527f636f6d70206d61726b6574206973206e6f74206c697374656400000000000000604482015290519081900360640190fd5b600381015460ff1615614c85576040805162461bcd60e51b815260206004820152601960248201527f636f6d70206d61726b657420616c726561647920616464656400000000000000604482015290519081900360640190fd5b60038101805460ff19166001908117909155604080516001600160a01b0385168152602081019290925280517f93c1f3e36ed71139f466a4ce8c9751790e2e33f5afb2df0dcfb3aeabe55d5aa29281900390910190a16001600160a01b0382166000908152601060205260409020546001600160e01b0316158015614d2d57506001600160a01b038216600090815260106020526040902054600160e01b900463ffffffff16155b15614dea5760405180604001604052806ec097ce7bc90715b34b9f10000000006001600160e01b03168152602001614d8f614d66611aef565b6040518060400160405280601c81526020016000805160206159ce8339815191528152506150d0565b63ffffffff9081169091526001600160a01b0384166000908152601060209081526040909120835181549490920151909216600160e01b026001600160e01b039182166001600160e01b031990941693909317169190911790555b6001600160a01b0382166000908152601160205260409020546001600160e01b0316158015614e3c57506001600160a01b038216600090815260116020526040902054600160e01b900463ffffffff16155b1561193a5760405180604001604052806ec097ce7bc90715b34b9f10000000006001600160e01b03168152602001614e75614d66611aef565b63ffffffff9081169091526001600160a01b0384166000908152601160209081526040909120835181549490920151909216600160e01b026001600160e01b039182166001600160e01b031990941693909317169190911790555050565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0846011811115614f0257fe5b846013811115614f0e57fe5b604080519283526020830191909152818101859052519081900360600190a1836011811115611c2557fe5b6000611c288383604051806040016040528060158152602001747375627472616374696f6e20756e646572666c6f7760581b815250615616565b6000611c28614f8a84670de0b6b3a7640000614f91565b8351615670565b6000611c2883836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f770000000000000000008152506156a3565b614fdb615869565b6040518060200160405280615008615002866ec097ce7bc90715b34b9f1000000000614f91565b85615670565b90529392505050565b615019615869565b604051806020016040528061500885600001518560000151615179565b600081600160e01b84106150c85760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561508d578181015183820152602001615075565b50505050905090810190601f1680156150ba5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b509192915050565b600081600160201b84106150c85760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561508d578181015183820152602001615075565b61512d615869565b604051806020016040528061500885600001518560000151614f39565b60006ec097ce7bc90715b34b9f100000000061516a848460000151614f91565b8161517157fe5b049392505050565b6000611c288383604051806040016040528060118152602001706164646974696f6e206f766572666c6f7760781b815250615722565b60008183101580156151c15750600083115b156152ec5760006151d06124f7565b604080516370a0823160e01b815230600482015290519192506000916001600160a01b038416916370a08231916024808301926020929190829003018186803b15801561521c57600080fd5b505afa158015615230573d6000803e3d6000fd5b505050506040513d602081101561524657600080fd5b505190508085116152e957816001600160a01b031663a9059cbb87876040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b1580156152b157600080fd5b505af11580156152c5573d6000803e3d6000fd5b505050506040513d60208110156152db57600080fd5b5060009350611c2892505050565b50505b509092915050565b6152fc615869565b6040518060200160405280615008856000015185614f91565b61531d615869565b60405180602001604052806150086153418660000151670de0b6b3a7640000614f91565b8551615670565b6000670de0b6b3a764000061516a848460000151614f91565b600061536b615869565b6000615375615869565b61537f878761547d565b9092509050600082600381111561539257fe5b146153a1579092509050612b44565b6153ab818661547d565b935093505050935093915050565b60008060006153c6615869565b6153d08787615406565b909250905060008260038111156153e357fe5b146153f45750915060009050612b44565b6153ab6154008261546e565b86615777565b6000615410615869565b60008061542186600001518661579d565b9092509050600082600381111561543457fe5b1461545357506040805160208101909152600081529092509050614893565b60408051602081019091529081526000969095509350505050565b51670de0b6b3a7640000900490565b6000615487615869565b60008061549c8660000151866000015161579d565b909250905060008260038111156154af57fe5b146154ce57506040805160208101909152600081529092509050614893565b6000806154e36706f05b59d3b2000084615777565b909250905060008260038111156154f657fe5b1461551857506040805160208101909152600081529094509250614893915050565b60008061552d83670de0b6b3a76400006157dc565b9092509050600082600381111561554057fe5b1461554757fe5b604080516020810190915290815260009a909950975050505050505050565b6000615570615869565b60008061558586670de0b6b3a764000061579d565b9092509050600082600381111561559857fe5b146155b757506040805160208101909152600081529092509050614893565b6000806155c483886157dc565b909250905060008260038111156155d757fe5b146155f957506040805160208101909152600081529094509250614893915050565b604080516020810190915290815260009890975095505050505050565b600081848411156156685760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561508d578181015183820152602001615075565b505050900390565b6000611c2883836040518060400160405280600e81526020016d646976696465206279207a65726f60901b815250615807565b60008315806156b0575082155b156156bd57506000611c28565b838302838582816156ca57fe5b041483906157195760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561508d578181015183820152602001615075565b50949350505050565b600083830182858210156157195760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561508d578181015183820152602001615075565b60008083830184811061578f57600092509050614893565b506002915060009050614893565b600080836157b057506000905080614893565b838302838582816157bd57fe5b04146157d157506002915060009050614893565b600092509050614893565b600080826157f05750600190506000614893565b60008385816157fb57fe5b04915091509250929050565b600081836158565760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561508d578181015183820152602001615075565b5082848161586057fe5b04949350505050565b6040518060200160405280600081525090565b81548183558181111561135e5760008381526020902061135e91810190830161590a565b6040518061014001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016158de615869565b81526020016158eb615869565b81526020016158f8615869565b8152602001615905615869565b905290565b611af191905b808211156159245760008155600101615910565b509056fe63616e6e6f742070617573652061206d61726b65742074686174206973206e6f74206c69737465646f6e6c792065787465726e616c6c79206f776e6564206163636f756e7473206d61792072656672657368207370656564736f6e6c7920706175736520677561726469616e20616e642061646d696e2063616e207061757365657869744d61726b65743a206765744163636f756e74536e617073686f74206661696c6564626c6f636b206e756d62657220657863656564732033322062697473000000006f6e6c7920756e6974726f6c6c65722061646d696e2063616e206368616e676520627261696e73a265627a7a723158206931aa37c380712b57afe908d2b1681005fe4211d481eaacdfed8f69085c676364736f6c63430005100032", + "metadata": "{\"compiler\":{\"version\":\"0.5.16+commit.9c3226ce\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"action\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"pauseState\",\"type\":\"bool\"}],\"name\":\"ActionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"action\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"pauseState\",\"type\":\"bool\"}],\"name\":\"ActionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSpeed\",\"type\":\"uint256\"}],\"name\":\"CompSpeedUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compBorrowIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedBorrowerComp\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"supplier\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compSupplyIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedSupplierComp\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isComped\",\"type\":\"bool\"}],\"name\":\"MarketComped\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketEntered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketExited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"MarketListed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCloseFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCloseFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCollateralFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCollateralFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCompRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCompRate\",\"type\":\"uint256\"}],\"name\":\"NewCompRate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldLiquidationIncentiveMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"NewLiquidationIncentive\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMaxAssets\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMaxAssets\",\"type\":\"uint256\"}],\"name\":\"NewMaxAssets\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldPauseGuardian\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"NewPauseGuardian\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"oldPriceOracle\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"newPriceOracle\",\"type\":\"address\"}],\"name\":\"NewPriceOracle\",\"type\":\"event\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"_addCompMarkets\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract Unitroller\",\"name\":\"unitroller\",\"type\":\"address\"}],\"name\":\"_become\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"_dropCompMarket\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setBorrowPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCloseFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCollateralFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"compRate_\",\"type\":\"uint256\"}],\"name\":\"_setCompRate\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"_setLiquidationIncentive\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newMaxAssets\",\"type\":\"uint256\"}],\"name\":\"_setMaxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setMintPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"_setPauseGuardian\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"newOracle\",\"type\":\"address\"}],\"name\":\"_setPriceOracle\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setSeizePaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setTransferPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"_supportMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allMarkets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"checkMembership\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"},{\"internalType\":\"contract CToken[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"holders\",\"type\":\"address[]\"},{\"internalType\":\"contract CToken[]\",\"name\":\"cTokens\",\"type\":\"address[]\"},{\"internalType\":\"bool\",\"name\":\"borrowers\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"suppliers\",\"type\":\"bool\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compAccrued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compBorrowState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compBorrowerIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compClaimThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compInitialIndex\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSupplierIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSupplyState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"enterMarkets\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenAddress\",\"type\":\"address\"}],\"name\":\"exitMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getAllMarkets\",\"outputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAssetsIn\",\"outputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getCompAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenModify\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"getHypotheticalAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"isComptroller\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateCalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"liquidationIncentiveMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"markets\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isComped\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"mintAmount\",\"type\":\"uint256\"}],\"name\":\"mintAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualMintAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"mintTokens\",\"type\":\"uint256\"}],\"name\":\"mintVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"refreshCompSpeeds\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"repayBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowerIndex\",\"type\":\"uint256\"}],\"name\":\"repayBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"seizeGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"transferGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Compound\",\"methods\":{\"_addCompMarkets(address[])\":{\"params\":{\"cTokens\":\"The addresses of the markets to add\"}},\"_dropCompMarket(address)\":{\"params\":{\"cToken\":\"The address of the market to drop\"}},\"_setCloseFactor(uint256)\":{\"details\":\"Admin function to set closeFactor\",\"params\":{\"newCloseFactorMantissa\":\"New close factor, scaled by 1e18\"},\"return\":\"uint 0=success, otherwise a failure. (See ErrorReporter for details)\"},\"_setCollateralFactor(address,uint256)\":{\"details\":\"Admin function to set per-market collateralFactor\",\"params\":{\"cToken\":\"The market to set the factor on\",\"newCollateralFactorMantissa\":\"The new collateral factor, scaled by 1e18\"},\"return\":\"uint 0=success, otherwise a failure. (See ErrorReporter for details)\"},\"_setCompRate(uint256)\":{\"params\":{\"compRate_\":\"The amount of COMP wei per block to distribute\"}},\"_setLiquidationIncentive(uint256)\":{\"details\":\"Admin function to set liquidationIncentive\",\"params\":{\"newLiquidationIncentiveMantissa\":\"New liquidationIncentive scaled by 1e18\"},\"return\":\"uint 0=success, otherwise a failure. (See ErrorReporter for details)\"},\"_setMaxAssets(uint256)\":{\"details\":\"Admin function to set maxAssets\",\"params\":{\"newMaxAssets\":\"New max assets\"},\"return\":\"uint 0=success, otherwise a failure. (See ErrorReporter for details)\"},\"_setPauseGuardian(address)\":{\"params\":{\"newPauseGuardian\":\"The address of the new Pause Guardian\"},\"return\":\"uint 0=success, otherwise a failure. (See enum Error for details)\"},\"_setPriceOracle(address)\":{\"details\":\"Admin function to set a new price oracle\",\"return\":\"uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\"},\"_supportMarket(address)\":{\"details\":\"Admin function to set isListed and add support for the market\",\"params\":{\"cToken\":\"The address of the market (token) to list\"},\"return\":\"uint 0=success, otherwise a failure. (See enum Error for details)\"},\"borrowAllowed(address,address,uint256)\":{\"params\":{\"borrowAmount\":\"The amount of underlying the account would borrow\",\"borrower\":\"The account which would borrow the asset\",\"cToken\":\"The market to verify the borrow against\"},\"return\":\"0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"borrowVerify(address,address,uint256)\":{\"params\":{\"borrowAmount\":\"The amount of the underlying asset requested to borrow\",\"borrower\":\"The address borrowing the underlying\",\"cToken\":\"Asset whose underlying is being borrowed\"}},\"checkMembership(address,address)\":{\"params\":{\"account\":\"The address of the account to check\",\"cToken\":\"The cToken to check\"},\"return\":\"True if the account is in the asset, otherwise false.\"},\"claimComp(address)\":{\"params\":{\"holder\":\"The address to claim COMP for\"}},\"claimComp(address,address[])\":{\"params\":{\"cTokens\":\"The list of markets to claim COMP in\",\"holder\":\"The address to claim COMP for\"}},\"claimComp(address[],address[],bool,bool)\":{\"params\":{\"borrowers\":\"Whether or not to claim COMP earned by borrowing\",\"cTokens\":\"The list of markets to claim COMP in\",\"holders\":\"The addresses to claim COMP for\",\"suppliers\":\"Whether or not to claim COMP earned by supplying\"}},\"enterMarkets(address[])\":{\"params\":{\"cTokens\":\"The list of addresses of the cToken markets to be enabled\"},\"return\":\"Success indicator for whether each corresponding market was entered\"},\"exitMarket(address)\":{\"details\":\"Sender must not have an outstanding borrow balance in the asset, or be providing necessary collateral for an outstanding borrow.\",\"params\":{\"cTokenAddress\":\"The address of the asset to be removed\"},\"return\":\"Whether or not the account successfully exited the market\"},\"getAccountLiquidity(address)\":{\"return\":\"(possible error code (semi-opaque), account liquidity in excess of collateral requirements, account shortfall below collateral requirements)\"},\"getAllMarkets()\":{\"details\":\"The automatic getter may be used to access an individual market.\",\"return\":\"The list of market addresses\"},\"getAssetsIn(address)\":{\"params\":{\"account\":\"The address of the account to pull assets for\"},\"return\":\"A dynamic list with the assets the account has entered\"},\"getCompAddress()\":{\"return\":\"The address of COMP\"},\"getHypotheticalAccountLiquidity(address,address,uint256,uint256)\":{\"params\":{\"account\":\"The account to determine liquidity for\",\"borrowAmount\":\"The amount of underlying to hypothetically borrow\",\"cTokenModify\":\"The market to hypothetically redeem/borrow in\",\"redeemTokens\":\"The number of tokens to hypothetically redeem\"},\"return\":\"(possible error code (semi-opaque), hypothetical account liquidity in excess of collateral requirements, hypothetical account shortfall below collateral requirements)\"},\"liquidateBorrowAllowed(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"repayAmount\":\"The amount of underlying being repaid\"}},\"liquidateBorrowVerify(address,address,address,address,uint256,uint256)\":{\"params\":{\"actualRepayAmount\":\"The amount of underlying being repaid\",\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\"}},\"liquidateCalculateSeizeTokens(address,address,uint256)\":{\"details\":\"Used in liquidation (called in cToken.liquidateBorrowFresh)\",\"params\":{\"actualRepayAmount\":\"The amount of cTokenBorrowed underlying to convert into cTokenCollateral tokens\",\"cTokenBorrowed\":\"The address of the borrowed cToken\",\"cTokenCollateral\":\"The address of the collateral cToken\"},\"return\":\"(errorCode, number of cTokenCollateral tokens to be seized in a liquidation)\"},\"mintAllowed(address,address,uint256)\":{\"params\":{\"cToken\":\"The market to verify the mint against\",\"mintAmount\":\"The amount of underlying being supplied to the market in exchange for tokens\",\"minter\":\"The account which would get the minted tokens\"},\"return\":\"0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"mintVerify(address,address,uint256,uint256)\":{\"params\":{\"actualMintAmount\":\"The amount of the underlying asset being minted\",\"cToken\":\"Asset being minted\",\"mintTokens\":\"The number of tokens being minted\",\"minter\":\"The address minting the tokens\"}},\"redeemAllowed(address,address,uint256)\":{\"params\":{\"cToken\":\"The market to verify the redeem against\",\"redeemTokens\":\"The number of cTokens to exchange for the underlying asset in the market\",\"redeemer\":\"The account which would redeem the tokens\"},\"return\":\"0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"redeemVerify(address,address,uint256,uint256)\":{\"params\":{\"cToken\":\"Asset being redeemed\",\"redeemAmount\":\"The amount of the underlying asset being redeemed\",\"redeemTokens\":\"The number of tokens being redeemed\",\"redeemer\":\"The address redeeming the tokens\"}},\"repayBorrowAllowed(address,address,address,uint256)\":{\"params\":{\"borrower\":\"The account which would borrowed the asset\",\"cToken\":\"The market to verify the repay against\",\"payer\":\"The account which would repay the asset\",\"repayAmount\":\"The amount of the underlying asset the account would repay\"},\"return\":\"0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"repayBorrowVerify(address,address,address,uint256,uint256)\":{\"params\":{\"actualRepayAmount\":\"The amount of underlying being repaid\",\"borrower\":\"The address of the borrower\",\"cToken\":\"Asset being repaid\",\"payer\":\"The address repaying the borrow\"}},\"seizeAllowed(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"seizeTokens\":\"The number of collateral tokens to seize\"}},\"seizeVerify(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"seizeTokens\":\"The number of collateral tokens to seize\"}},\"transferAllowed(address,address,address,uint256)\":{\"params\":{\"cToken\":\"The market to verify the transfer against\",\"dst\":\"The account which receives the tokens\",\"src\":\"The account which sources the tokens\",\"transferTokens\":\"The number of cTokens to transfer\"},\"return\":\"0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"transferVerify(address,address,address,uint256)\":{\"params\":{\"cToken\":\"Asset being transferred\",\"dst\":\"The account which receives the tokens\",\"src\":\"The account which sources the tokens\",\"transferTokens\":\"The number of cTokens to transfer\"}}},\"title\":\"Compound's Comptroller Contract\"},\"userdoc\":{\"methods\":{\"_addCompMarkets(address[])\":{\"notice\":\"Add markets to compMarkets, allowing them to earn COMP in the flywheel\"},\"_dropCompMarket(address)\":{\"notice\":\"Remove a market from compMarkets, preventing it from earning COMP in the flywheel\"},\"_setCloseFactor(uint256)\":{\"notice\":\"Sets the closeFactor used when liquidating borrows\"},\"_setCollateralFactor(address,uint256)\":{\"notice\":\"Sets the collateralFactor for a market\"},\"_setCompRate(uint256)\":{\"notice\":\"Set the amount of COMP distributed per block\"},\"_setLiquidationIncentive(uint256)\":{\"notice\":\"Sets liquidationIncentive\"},\"_setMaxAssets(uint256)\":{\"notice\":\"Sets maxAssets which controls how many markets can be entered\"},\"_setPauseGuardian(address)\":{\"notice\":\"Admin function to change the Pause Guardian\"},\"_setPriceOracle(address)\":{\"notice\":\"Sets a new price oracle for the comptroller\"},\"_supportMarket(address)\":{\"notice\":\"Add the market to the markets mapping and set it as listed\"},\"borrowAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to borrow the underlying asset of the given market\"},\"borrowVerify(address,address,uint256)\":{\"notice\":\"Validates borrow and reverts on rejection. May emit logs.\"},\"checkMembership(address,address)\":{\"notice\":\"Returns whether the given account is entered in the given asset\"},\"claimComp(address)\":{\"notice\":\"Claim all the comp accrued by holder in all markets\"},\"claimComp(address,address[])\":{\"notice\":\"Claim all the comp accrued by holder in the specified markets\"},\"claimComp(address[],address[],bool,bool)\":{\"notice\":\"Claim all comp accrued by the holders\"},\"enterMarkets(address[])\":{\"notice\":\"Add assets to be included in account liquidity calculation\"},\"exitMarket(address)\":{\"notice\":\"Removes asset from sender's account liquidity calculation\"},\"getAccountLiquidity(address)\":{\"notice\":\"Determine the current account liquidity wrt collateral requirements\"},\"getAllMarkets()\":{\"notice\":\"Return all of the markets\"},\"getAssetsIn(address)\":{\"notice\":\"Returns the assets an account has entered\"},\"getCompAddress()\":{\"notice\":\"Return the address of the COMP token\"},\"getHypotheticalAccountLiquidity(address,address,uint256,uint256)\":{\"notice\":\"Determine what the account liquidity would be if the given amounts were redeemed/borrowed\"},\"liquidateBorrowAllowed(address,address,address,address,uint256)\":{\"notice\":\"Checks if the liquidation should be allowed to occur\"},\"liquidateBorrowVerify(address,address,address,address,uint256,uint256)\":{\"notice\":\"Validates liquidateBorrow and reverts on rejection. May emit logs.\"},\"liquidateCalculateSeizeTokens(address,address,uint256)\":{\"notice\":\"Calculate number of tokens of collateral asset to seize given an underlying amount\"},\"mintAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to mint tokens in the given market\"},\"mintVerify(address,address,uint256,uint256)\":{\"notice\":\"Validates mint and reverts on rejection. May emit logs.\"},\"redeemAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to redeem tokens in the given market\"},\"redeemVerify(address,address,uint256,uint256)\":{\"notice\":\"Validates redeem and reverts on rejection. May emit logs.\"},\"refreshCompSpeeds()\":{\"notice\":\"Recalculate and update COMP speeds for all COMP markets\"},\"repayBorrowAllowed(address,address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to repay a borrow in the given market\"},\"repayBorrowVerify(address,address,address,uint256,uint256)\":{\"notice\":\"Validates repayBorrow and reverts on rejection. May emit logs.\"},\"seizeAllowed(address,address,address,address,uint256)\":{\"notice\":\"Checks if the seizing of assets should be allowed to occur\"},\"seizeVerify(address,address,address,address,uint256)\":{\"notice\":\"Validates seize and reverts on rejection. May emit logs.\"},\"transferAllowed(address,address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to transfer tokens in the given market\"},\"transferVerify(address,address,address,uint256)\":{\"notice\":\"Validates transfer and reverts on rejection. May emit logs.\"}}}},\"settings\":{\"compilationTarget\":{\"contracts/ComptrollerG4.sol\":\"ComptrollerG4\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/CToken.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./CTokenInterfaces.sol\\\";\\nimport \\\"./ErrorReporter.sol\\\";\\nimport \\\"./Exponential.sol\\\";\\nimport \\\"./EIP20Interface.sol\\\";\\nimport \\\"./InterestRateModel.sol\\\";\\n\\n/**\\n * @title Compound's CToken Contract\\n * @notice Abstract base for CTokens\\n * @author Compound\\n */\\ncontract CToken is CTokenInterface, Exponential, TokenErrorReporter {\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_) public {\\n require(msg.sender == admin, \\\"only admin may initialize the market\\\");\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = getBlockNumber();\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Transfer `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = uint(-1);\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srcTokensNew;\\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, srcTokensNew) = 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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srcTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != uint(-1)) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n // unused function\\n // comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transfer(address dst, uint256 amount) external nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferFrom(address src, address dst, uint256 amount) external nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (-1 means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool) {\\n address src = msg.sender;\\n transferAllowances[src][spender] = amount;\\n emit Approval(src, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (-1 means infinite)\\n */\\n function allowance(address owner, address spender) external view returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external returns (uint) {\\n Exp memory exchangeRate = Exp({mantissa: exchangeRateCurrent()});\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n require(mErr == MathError.NO_ERROR, \\\"balance could not be calculated\\\");\\n return balance;\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view returns (uint, uint, uint, uint) {\\n uint cTokenBalance = accountTokens[account];\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), cTokenBalance, borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @dev Function to simply retrieve block number\\n * This exists mainly for inheriting test contracts to stub this result.\\n */\\n function getBlockNumber() internal view returns (uint) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this cToken\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view returns (uint) {\\n return interestRateModel.getBorrowRate(getCashPrior(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this cToken\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view returns (uint) {\\n return interestRateModel.getSupplyRate(getCashPrior(), totalBorrows, totalReserves, reserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n require(err == MathError.NO_ERROR, \\\"borrowBalanceStored: borrowBalanceStoredInternal failed\\\");\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return (error code, the calculated balance or 0 if error code is non-zero)\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the CToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n require(err == MathError.NO_ERROR, \\\"exchangeRateStored: exchangeRateStoredInternal failed\\\");\\n return result;\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the CToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return (error code, calculated exchange rate scaled by 1e18)\\n */\\n function exchangeRateStoredInternal() internal view returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows - totalReserves) / totalSupply\\n */\\n uint totalCash = getCashPrior();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Get cash balance of this cToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage.\\n */\\n function accrueInterest() public returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = getBlockNumber();\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = getCashPrior();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n require(mathErr == MathError.NO_ERROR, \\\"could not calculate block delta\\\");\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({mantissa: borrowRateMantissa}), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(Exp({mantissa: reserveFactorMantissa}), interestAccumulated, reservesPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives cTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n struct MintLocalVars {\\n Error err;\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives cTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, 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's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the cToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of cTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.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 cTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED\\\");\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\\");\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender redeems cTokens in exchange for the underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemTokens The number of cTokens to redeem into underlying\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemInternal(uint redeemTokens) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(msg.sender, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems cTokens in exchange for a specified amount of underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemAmount The amount of underlying to receive from redeeming cTokens\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemUnderlyingInternal(uint redeemAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(msg.sender, 0, redeemAmount);\\n }\\n\\n struct RedeemLocalVars {\\n Error err;\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n /**\\n * @notice User redeems cTokens in exchange for the underlying asset\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param redeemTokensIn The number of cTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming cTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemFresh(address payable redeemer, uint redeemTokensIn, uint redeemAmountIn) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr));\\n }\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(Exp({mantissa: vars.exchangeRateMantissa}), redeemTokensIn);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(redeemAmountIn, Exp({mantissa: vars.exchangeRateMantissa}));\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REDEEM_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDEEM_FRESHNESS_CHECK);\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDEEM_TRANSFER_OUT_NOT_POSSIBLE);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We invoke doTransferOut for the redeemer and the redeemAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(redeemer, vars.redeemAmount);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n /* We call the defense hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender borrows assets from the protocol to their own address\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function borrowInternal(uint borrowAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(msg.sender, borrowAmount);\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n /**\\n * @notice Users borrow assets from the protocol to their own address\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function borrowFresh(address payable borrower, uint borrowAmount) internal returns (uint) {\\n /* Fail if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.BORROW_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.BORROW_FRESHNESS_CHECK);\\n }\\n\\n /* Fail gracefully if protocol has insufficient underlying cash */\\n if (getCashPrior() < borrowAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.BORROW_CASH_NOT_AVAILABLE);\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We invoke doTransferOut for the borrower and the borrowAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(borrower, borrowAmount);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to borrower\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer the account paying off the borrow\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount the amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED\\\");\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED\\\");\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this cToken to be liquidated\\n * @param cTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) 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 = cTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, cTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this cToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param cTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowFresh(address liquidator, address borrower, uint repayAmount, CTokenInterface cTokenCollateral) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(address(this), address(cTokenCollateral), liquidator, borrower, repayAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify cTokenCollateral market's block number equals current block number */\\n if (cTokenCollateral.accrualBlockNumber() != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = -1 */\\n if (repayAmount == uint(-1)) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & 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(cTokenCollateral), actualRepayAmount);\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(cTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(cTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = cTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(cTokenCollateral), seizeTokens);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.liquidateBorrowVerify(address(this), address(cTokenCollateral), liquidator, borrower, actualRepayAmount, seizeTokens);\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another cToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed cToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of cTokens to seize\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function seize(address liquidator, address borrower, uint seizeTokens) external nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n struct SeizeInternalLocalVars {\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n uint liquidatorSeizeTokens;\\n uint protocolSeizeTokens;\\n uint protocolSeizeAmount;\\n uint exchangeRateMantissa;\\n uint totalReservesNew;\\n uint totalSupplyNew;\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another CToken.\\n * Its absolutely critical to use msg.sender as the seizer cToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed cToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of cTokens to seize\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function seizeInternal(address seizerToken, address liquidator, address borrower, uint seizeTokens) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n SeizeInternalLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (vars.mathErr, vars.borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(vars.mathErr));\\n }\\n\\n vars.protocolSeizeTokens = mul_(seizeTokens, Exp({mantissa: protocolSeizeShareMantissa}));\\n vars.liquidatorSeizeTokens = sub_(seizeTokens, vars.protocolSeizeTokens);\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n require(vars.mathErr == MathError.NO_ERROR, \\\"exchange rate math error\\\");\\n\\n vars.protocolSeizeAmount = mul_ScalarTruncate(Exp({mantissa: vars.exchangeRateMantissa}), vars.protocolSeizeTokens);\\n\\n vars.totalReservesNew = add_(totalReserves, vars.protocolSeizeAmount);\\n vars.totalSupplyNew = sub_(totalSupply, vars.protocolSeizeTokens);\\n\\n (vars.mathErr, vars.liquidatorTokensNew) = addUInt(accountTokens[liquidator], vars.liquidatorSeizeTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(vars.mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n totalReserves = vars.totalReservesNew;\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[borrower] = vars.borrowerTokensNew;\\n accountTokens[liquidator] = vars.liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, vars.liquidatorSeizeTokens);\\n emit Transfer(borrower, address(this), vars.protocolSeizeTokens);\\n emit ReservesAdded(address(this), vars.protocolSeizeAmount, vars.totalReservesNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n\\n /*** Admin Functions ***/\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPendingAdmin(address payable newPendingAdmin) external returns (uint) {\\n // Check caller = admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\\n }\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptAdmin() external returns (uint) {\\n // Check caller is pendingAdmin and pendingAdmin \\u2260 address(0)\\n if (msg.sender != pendingAdmin || msg.sender == address(0)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = address(0);\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setComptroller(ComptrollerInterface newComptroller) public returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_COMPTROLLER_OWNER_CHECK);\\n }\\n\\n ComptrollerInterface oldComptroller = comptroller;\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(oldComptroller, newComptroller);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh\\n * @dev Admin function to accrue interest and set a new reserve factor\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setReserveFactor(uint newReserveFactorMantissa) external nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\\n * @dev Admin function to set a new reserve factor\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_RESERVE_FACTOR_ADMIN_CHECK);\\n }\\n\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring from msg.sender\\n * @param addAmount Amount of addition to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to admin\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _reduceReserves(uint reduceAmount) external nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to admin\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _reduceReservesFresh(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's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n totalReservesNew = totalReserves - reduceAmount;\\n // We checked reduceAmount <= totalReserves above, so this should never revert.\\n require(totalReservesNew <= 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't be sure if side effects occurred.\\n doTransferOut(admin, reduceAmount);\\n\\n emit ReservesReduced(admin, reduceAmount, totalReservesNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Admin function to accrue interest and update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel);\\n }\\n\\n /**\\n * @notice updates the interest rate model (*requires fresh interest accrual)\\n * @dev Admin function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal returns (uint) {\\n\\n // Used to store old model for use in the event that is emitted on success\\n InterestRateModel oldInterestRateModel;\\n\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_INTEREST_RATE_MODEL_OWNER_CHECK);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Track the market's current interest rate model\\n oldInterestRateModel = interestRateModel;\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view returns (uint);\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure tather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal;\\n\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n}\\n\",\"keccak256\":\"0x436ec2e309682995f8a82dfdd9e8f75928599c10a9a680dddbee6c275014008d\"},\"contracts/CTokenInterfaces.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./InterestRateModel.sol\\\";\\nimport \\\"./EIP20NonStandardInterface.sol\\\";\\n\\ncontract CTokenStorage {\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-cToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModel public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first CTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping (address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping (address => mapping (address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Share of seized collateral that is added to reserves\\n */\\n uint public constant protocolSeizeShareMantissa = 2.8e16; //2.8%\\n\\n}\\n\\ncontract CTokenInterface is CTokenStorage {\\n /**\\n * @notice Indicator that this is a CToken contract (for inspection)\\n */\\n bool public constant isCToken = true;\\n\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(address liquidator, address borrower, uint repayAmount, address cTokenCollateral, uint seizeTokens);\\n\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin is updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(InterestRateModel oldInterestRateModel, InterestRateModel newInterestRateModel);\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address admin, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Failure event\\n */\\n event Failure(uint error, uint info, uint detail);\\n\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external returns (bool);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function approve(address spender, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function balanceOfUnderlying(address owner) external returns (uint);\\n function getAccountSnapshot(address account) external view returns (uint, uint, uint, uint);\\n function borrowRatePerBlock() external view returns (uint);\\n function supplyRatePerBlock() external view returns (uint);\\n function totalBorrowsCurrent() external returns (uint);\\n function borrowBalanceCurrent(address account) external returns (uint);\\n function borrowBalanceStored(address account) public view returns (uint);\\n function exchangeRateCurrent() public returns (uint);\\n function exchangeRateStored() public view returns (uint);\\n function getCash() external view returns (uint);\\n function accrueInterest() public returns (uint);\\n function seize(address liquidator, address borrower, uint seizeTokens) external returns (uint);\\n\\n\\n /*** Admin Functions ***/\\n\\n function _setPendingAdmin(address payable newPendingAdmin) external returns (uint);\\n function _acceptAdmin() external returns (uint);\\n function _setComptroller(ComptrollerInterface newComptroller) public returns (uint);\\n function _setReserveFactor(uint newReserveFactorMantissa) external returns (uint);\\n function _reduceReserves(uint reduceAmount) external returns (uint);\\n function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint);\\n}\\n\\ncontract CErc20Storage {\\n /**\\n * @notice Underlying asset for this CToken\\n */\\n address public underlying;\\n}\\n\\ncontract CErc20Interface is CErc20Storage {\\n\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n function redeem(uint redeemTokens) external returns (uint);\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n function borrow(uint borrowAmount) external returns (uint);\\n function repayBorrow(uint repayAmount) external returns (uint);\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n function liquidateBorrow(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) external returns (uint);\\n function sweepToken(EIP20NonStandardInterface token) external;\\n\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ncontract CDelegationStorage {\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n}\\n\\ncontract CDelegatorInterface is CDelegationStorage {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(address implementation_, bool allowResign, bytes memory becomeImplementationData) public;\\n}\\n\\ncontract CDelegateInterface is CDelegationStorage {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) public;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() public;\\n}\\n\",\"keccak256\":\"0x963bbf60b4c0b76900b3fcb2db8c8be634934b37b4113f1055e57a308197d21a\"},\"contracts/CarefulMath.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Careful Math\\n * @author Compound\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c = a * b;\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n return (MathError.NO_ERROR, a - b);\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c = a + b;\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\",\"keccak256\":\"0x0647348f27e41d22555d99eebd217dee02a4d737df6accd7cce5347a7487c7de\"},\"contracts/ComptrollerG4.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.sol\\\";\\nimport \\\"./ErrorReporter.sol\\\";\\nimport \\\"./Exponential.sol\\\";\\nimport \\\"./PriceOracle.sol\\\";\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./ComptrollerStorage.sol\\\";\\nimport \\\"./Unitroller.sol\\\";\\nimport \\\"./Governance/Comp.sol\\\";\\n\\n/**\\n * @title Compound's Comptroller Contract\\n * @author Compound\\n */\\ncontract ComptrollerG4 is ComptrollerV3Storage, ComptrollerInterface, ComptrollerErrorReporter, Exponential {\\n /// @notice Emitted when an admin supports a market\\n event MarketListed(CToken cToken);\\n\\n /// @notice Emitted when an account enters a market\\n event MarketEntered(CToken cToken, address account);\\n\\n /// @notice Emitted when an account exits a market\\n event MarketExited(CToken cToken, 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(CToken cToken, 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 maxAssets is changed by admin\\n event NewMaxAssets(uint oldMaxAssets, uint newMaxAssets);\\n\\n /// @notice Emitted when price oracle is changed\\n event NewPriceOracle(PriceOracle oldPriceOracle, PriceOracle newPriceOracle);\\n\\n /// @notice Emitted when pause guardian is changed\\n event NewPauseGuardian(address oldPauseGuardian, address newPauseGuardian);\\n\\n /// @notice Emitted when an action is paused globally\\n event ActionPaused(string action, bool pauseState);\\n\\n /// @notice Emitted when an action is paused on a market\\n event ActionPaused(CToken cToken, string action, bool pauseState);\\n\\n /// @notice Emitted when market comped status is changed\\n event MarketComped(CToken cToken, bool isComped);\\n\\n /// @notice Emitted when COMP rate is changed\\n event NewCompRate(uint oldCompRate, uint newCompRate);\\n\\n /// @notice Emitted when a new COMP speed is calculated for a market\\n event CompSpeedUpdated(CToken indexed cToken, uint newSpeed);\\n\\n /// @notice Emitted when COMP is distributed to a supplier\\n event DistributedSupplierComp(CToken indexed cToken, address indexed supplier, uint compDelta, uint compSupplyIndex);\\n\\n /// @notice Emitted when COMP is distributed to a borrower\\n event DistributedBorrowerComp(CToken indexed cToken, address indexed borrower, uint compDelta, uint compBorrowIndex);\\n\\n /// @notice The threshold above which the flywheel transfers COMP, in wei\\n uint public constant compClaimThreshold = 0.001e18;\\n\\n /// @notice The initial COMP index for a market\\n uint224 public constant compInitialIndex = 1e36;\\n\\n // closeFactorMantissa must be strictly greater than this value\\n uint internal constant closeFactorMinMantissa = 0.05e18; // 0.05\\n\\n // closeFactorMantissa must not exceed this value\\n uint internal constant closeFactorMaxMantissa = 0.9e18; // 0.9\\n\\n // No collateralFactorMantissa may exceed this value\\n uint internal constant collateralFactorMaxMantissa = 0.9e18; // 0.9\\n\\n // liquidationIncentiveMantissa must be no less than this value\\n uint internal constant liquidationIncentiveMinMantissa = 1.0e18; // 1.0\\n\\n // liquidationIncentiveMantissa must be no greater than this value\\n uint internal constant liquidationIncentiveMaxMantissa = 1.5e18; // 1.5\\n\\n constructor() public {\\n admin = msg.sender;\\n }\\n\\n /*** Assets You Are In ***/\\n\\n /**\\n * @notice Returns the assets an account has entered\\n * @param account The address of the account to pull assets for\\n * @return A dynamic list with the assets the account has entered\\n */\\n function getAssetsIn(address account) external view returns (CToken[] memory) {\\n CToken[] memory assetsIn = accountAssets[account];\\n\\n return assetsIn;\\n }\\n\\n /**\\n * @notice Returns whether the given account is entered in the given asset\\n * @param account The address of the account to check\\n * @param cToken The cToken to check\\n * @return True if the account is in the asset, otherwise false.\\n */\\n function checkMembership(address account, CToken cToken) external view returns (bool) {\\n return markets[address(cToken)].accountMembership[account];\\n }\\n\\n /**\\n * @notice Add assets to be included in account liquidity calculation\\n * @param cTokens The list of addresses of the cToken markets to be enabled\\n * @return Success indicator for whether each corresponding market was entered\\n */\\n function enterMarkets(address[] memory cTokens) public returns (uint[] memory) {\\n uint len = cTokens.length;\\n\\n uint[] memory results = new uint[](len);\\n for (uint i = 0; i < len; i++) {\\n CToken cToken = CToken(cTokens[i]);\\n\\n results[i] = uint(addToMarketInternal(cToken, msg.sender));\\n }\\n\\n return results;\\n }\\n\\n /**\\n * @notice Add the market to the borrower's \\\"assets in\\\" for liquidity calculations\\n * @param cToken The market to enter\\n * @param borrower The address of the account to modify\\n * @return Success indicator for whether the market was entered\\n */\\n function addToMarketInternal(CToken cToken, address borrower) internal returns (Error) {\\n Market storage marketToJoin = markets[address(cToken)];\\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 if (accountAssets[borrower].length >= maxAssets) {\\n // no space, cannot join\\n return Error.TOO_MANY_ASSETS;\\n }\\n\\n // survived the gauntlet, add to list\\n // NOTE: we store these somewhat redundantly as a significant optimization\\n // this avoids having to iterate through the list for the most common use cases\\n // that is, only when we need to perform liquidity checks\\n // and not whenever we want to check if an account is in a particular market\\n marketToJoin.accountMembership[borrower] = true;\\n accountAssets[borrower].push(cToken);\\n\\n emit MarketEntered(cToken, borrower);\\n\\n return Error.NO_ERROR;\\n }\\n\\n /**\\n * @notice Removes asset from sender's 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 cTokenAddress The address of the asset to be removed\\n * @return Whether or not the account successfully exited the market\\n */\\n function exitMarket(address cTokenAddress) external returns (uint) {\\n CToken cToken = CToken(cTokenAddress);\\n /* Get sender tokensHeld and amountOwed underlying from the cToken */\\n (uint oErr, uint tokensHeld, uint amountOwed, ) = cToken.getAccountSnapshot(msg.sender);\\n require(oErr == 0, \\\"exitMarket: getAccountSnapshot failed\\\"); // semi-opaque error code\\n\\n /* Fail if the sender has a borrow balance */\\n if (amountOwed != 0) {\\n return fail(Error.NONZERO_BORROW_BALANCE, FailureInfo.EXIT_MARKET_BALANCE_OWED);\\n }\\n\\n /* Fail if the sender is not permitted to redeem all of their tokens */\\n uint allowed = redeemAllowedInternal(cTokenAddress, msg.sender, tokensHeld);\\n if (allowed != 0) {\\n return failOpaque(Error.REJECTION, FailureInfo.EXIT_MARKET_REJECTION, allowed);\\n }\\n\\n Market storage marketToExit = markets[address(cToken)];\\n\\n /* Return true if the sender is not already \\u2018in\\u2019 the market */\\n if (!marketToExit.accountMembership[msg.sender]) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Set cToken account membership to false */\\n delete marketToExit.accountMembership[msg.sender];\\n\\n /* Delete cToken from the account\\u2019s list of assets */\\n // load into memory for faster iteration\\n CToken[] memory userAssetList = accountAssets[msg.sender];\\n uint len = userAssetList.length;\\n uint assetIndex = len;\\n for (uint i = 0; i < len; i++) {\\n if (userAssetList[i] == cToken) {\\n assetIndex = i;\\n break;\\n }\\n }\\n\\n // We *must* have found the asset in the list or our redundant data structure is broken\\n assert(assetIndex < len);\\n\\n // copy last item in list to location of item to be removed, reduce length by 1\\n CToken[] storage storedList = accountAssets[msg.sender];\\n storedList[assetIndex] = storedList[storedList.length - 1];\\n storedList.length--;\\n\\n emit MarketExited(cToken, 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 cToken The market to verify the mint against\\n * @param minter The account which would get the minted tokens\\n * @param mintAmount The amount of underlying being supplied to the market in exchange for tokens\\n * @return 0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function mintAllowed(address cToken, address minter, uint mintAmount) external returns (uint) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n require(!mintGuardianPaused[cToken], \\\"mint is paused\\\");\\n\\n // Shh - currently unused\\n minter;\\n mintAmount;\\n\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n // Keep the flywheel moving\\n updateCompSupplyIndex(cToken);\\n distributeSupplierComp(cToken, minter, false);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates mint and reverts on rejection. May emit logs.\\n * @param cToken Asset being minted\\n * @param minter The address minting the tokens\\n * @param actualMintAmount The amount of the underlying asset being minted\\n * @param mintTokens The number of tokens being minted\\n */\\n function mintVerify(address cToken, address minter, uint actualMintAmount, uint mintTokens) external {\\n // Shh - currently unused\\n cToken;\\n minter;\\n actualMintAmount;\\n mintTokens;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to redeem tokens in the given market\\n * @param cToken The market to verify the redeem against\\n * @param redeemer The account which would redeem the tokens\\n * @param redeemTokens The number of cTokens to exchange for the underlying asset in the market\\n * @return 0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function redeemAllowed(address cToken, address redeemer, uint redeemTokens) external returns (uint) {\\n uint allowed = redeemAllowedInternal(cToken, redeemer, redeemTokens);\\n if (allowed != uint(Error.NO_ERROR)) {\\n return allowed;\\n }\\n\\n // Keep the flywheel moving\\n updateCompSupplyIndex(cToken);\\n distributeSupplierComp(cToken, redeemer, false);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n function redeemAllowedInternal(address cToken, address redeemer, uint redeemTokens) internal view returns (uint) {\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!markets[cToken].accountMembership[redeemer]) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n (Error err, , uint shortfall) = getHypotheticalAccountLiquidityInternal(redeemer, CToken(cToken), redeemTokens, 0);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n if (shortfall > 0) {\\n return uint(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates redeem and reverts on rejection. May emit logs.\\n * @param cToken Asset being redeemed\\n * @param redeemer The address redeeming the tokens\\n * @param redeemAmount The amount of the underlying asset being redeemed\\n * @param redeemTokens The number of tokens being redeemed\\n */\\n function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) external {\\n // Shh - currently unused\\n cToken;\\n redeemer;\\n\\n // Require tokens is zero or amount is also zero\\n if (redeemTokens == 0 && redeemAmount > 0) {\\n revert(\\\"redeemTokens zero\\\");\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to borrow the underlying asset of the given market\\n * @param cToken The market to verify the borrow against\\n * @param borrower The account which would borrow the asset\\n * @param borrowAmount The amount of underlying the account would borrow\\n * @return 0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function borrowAllowed(address cToken, address borrower, uint borrowAmount) external returns (uint) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n require(!borrowGuardianPaused[cToken], \\\"borrow is paused\\\");\\n\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n if (!markets[cToken].accountMembership[borrower]) {\\n // only cTokens may call borrowAllowed if borrower not in market\\n require(msg.sender == cToken, \\\"sender must be cToken\\\");\\n\\n // attempt to add borrower to the market\\n Error err = addToMarketInternal(CToken(msg.sender), borrower);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n\\n // it should be impossible to break the important invariant\\n assert(markets[cToken].accountMembership[borrower]);\\n }\\n\\n if (oracle.getUnderlyingPrice(CToken(cToken)) == 0) {\\n return uint(Error.PRICE_ERROR);\\n }\\n\\n (Error err, , uint shortfall) = getHypotheticalAccountLiquidityInternal(borrower, CToken(cToken), 0, borrowAmount);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n if (shortfall > 0) {\\n return uint(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n\\n // Keep the flywheel moving\\n Exp memory borrowIndex = Exp({mantissa: CToken(cToken).borrowIndex()});\\n updateCompBorrowIndex(cToken, borrowIndex);\\n distributeBorrowerComp(cToken, borrower, borrowIndex, false);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates borrow and reverts on rejection. May emit logs.\\n * @param cToken Asset whose underlying is being borrowed\\n * @param borrower The address borrowing the underlying\\n * @param borrowAmount The amount of the underlying asset requested to borrow\\n */\\n function borrowVerify(address cToken, address borrower, uint borrowAmount) external {\\n // Shh - currently unused\\n cToken;\\n borrower;\\n borrowAmount;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to repay a borrow in the given market\\n * @param cToken The market to verify the repay against\\n * @param payer The account which would repay the asset\\n * @param borrower The account which would borrowed the asset\\n * @param repayAmount The amount of the underlying asset the account would repay\\n * @return 0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function repayBorrowAllowed(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount) external returns (uint) {\\n // Shh - currently unused\\n payer;\\n borrower;\\n repayAmount;\\n\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n // Keep the flywheel moving\\n Exp memory borrowIndex = Exp({mantissa: CToken(cToken).borrowIndex()});\\n updateCompBorrowIndex(cToken, borrowIndex);\\n distributeBorrowerComp(cToken, borrower, borrowIndex, false);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates repayBorrow and reverts on rejection. May emit logs.\\n * @param cToken Asset being repaid\\n * @param payer The address repaying the borrow\\n * @param borrower The address of the borrower\\n * @param actualRepayAmount The amount of underlying being repaid\\n */\\n function repayBorrowVerify(\\n address cToken,\\n address payer,\\n address borrower,\\n uint actualRepayAmount,\\n uint borrowerIndex) external {\\n // Shh - currently unused\\n cToken;\\n payer;\\n borrower;\\n actualRepayAmount;\\n borrowerIndex;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the liquidation should be allowed to occur\\n * @param cTokenBorrowed Asset which was borrowed by the borrower\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param repayAmount The amount of underlying being repaid\\n */\\n function liquidateBorrowAllowed(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount) external returns (uint) {\\n // Shh - currently unused\\n liquidator;\\n\\n if (!markets[cTokenBorrowed].isListed || !markets[cTokenCollateral].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n /* The borrower must have shortfall in order to be liquidatable */\\n (Error err, , uint shortfall) = getAccountLiquidityInternal(borrower);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n if (shortfall == 0) {\\n return uint(Error.INSUFFICIENT_SHORTFALL);\\n }\\n\\n /* The liquidator may not repay more than what is allowed by the closeFactor */\\n uint borrowBalance = CToken(cTokenBorrowed).borrowBalanceStored(borrower);\\n (MathError mathErr, uint maxClose) = mulScalarTruncate(Exp({mantissa: closeFactorMantissa}), borrowBalance);\\n if (mathErr != MathError.NO_ERROR) {\\n return uint(Error.MATH_ERROR);\\n }\\n if (repayAmount > 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 cTokenBorrowed Asset which was borrowed by the borrower\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param actualRepayAmount The amount of underlying being repaid\\n */\\n function liquidateBorrowVerify(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint actualRepayAmount,\\n uint seizeTokens) external {\\n // Shh - currently unused\\n cTokenBorrowed;\\n cTokenCollateral;\\n liquidator;\\n borrower;\\n actualRepayAmount;\\n seizeTokens;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the seizing of assets should be allowed to occur\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param cTokenBorrowed Asset which was borrowed by the borrower\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param seizeTokens The number of collateral tokens to seize\\n */\\n function seizeAllowed(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external returns (uint) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n require(!seizeGuardianPaused, \\\"seize is paused\\\");\\n\\n // Shh - currently unused\\n seizeTokens;\\n\\n if (!markets[cTokenCollateral].isListed || !markets[cTokenBorrowed].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n if (CToken(cTokenCollateral).comptroller() != CToken(cTokenBorrowed).comptroller()) {\\n return uint(Error.COMPTROLLER_MISMATCH);\\n }\\n\\n // Keep the flywheel moving\\n updateCompSupplyIndex(cTokenCollateral);\\n distributeSupplierComp(cTokenCollateral, borrower, false);\\n distributeSupplierComp(cTokenCollateral, liquidator, false);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates seize and reverts on rejection. May emit logs.\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param cTokenBorrowed Asset which was borrowed by the borrower\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param seizeTokens The number of collateral tokens to seize\\n */\\n function seizeVerify(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external {\\n // Shh - currently unused\\n cTokenCollateral;\\n cTokenBorrowed;\\n liquidator;\\n borrower;\\n seizeTokens;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to transfer tokens in the given market\\n * @param cToken The market to verify the transfer against\\n * @param src The account which sources the tokens\\n * @param dst The account which receives the tokens\\n * @param transferTokens The number of cTokens to transfer\\n * @return 0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function transferAllowed(address cToken, address src, address dst, uint transferTokens) external returns (uint) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n require(!transferGuardianPaused, \\\"transfer is paused\\\");\\n\\n // Currently the only consideration is whether or not\\n // the src is allowed to redeem this many tokens\\n uint allowed = redeemAllowedInternal(cToken, src, transferTokens);\\n if (allowed != uint(Error.NO_ERROR)) {\\n return allowed;\\n }\\n\\n // Keep the flywheel moving\\n updateCompSupplyIndex(cToken);\\n distributeSupplierComp(cToken, src, false);\\n distributeSupplierComp(cToken, dst, false);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates transfer and reverts on rejection. May emit logs.\\n * @param cToken Asset being transferred\\n * @param src The account which sources the tokens\\n * @param dst The account which receives the tokens\\n * @param transferTokens The number of cTokens to transfer\\n */\\n function transferVerify(address cToken, address src, address dst, uint transferTokens) external {\\n // Shh - currently unused\\n cToken;\\n src;\\n dst;\\n transferTokens;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n /**\\n * @dev Local vars for avoiding stack-depth limits in calculating account liquidity.\\n * Note that `cTokenBalance` is the number of cTokens the account owns in the market,\\n * whereas `borrowBalance` is the amount of underlying that the account has borrowed.\\n */\\n struct AccountLiquidityLocalVars {\\n uint sumCollateral;\\n uint sumBorrowPlusEffects;\\n uint cTokenBalance;\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n uint oraclePriceMantissa;\\n Exp collateralFactor;\\n Exp exchangeRate;\\n Exp oraclePrice;\\n Exp tokensToDenom;\\n }\\n\\n /**\\n * @notice Determine the current account liquidity wrt collateral requirements\\n * @return (possible error code (semi-opaque),\\n account liquidity in excess of collateral requirements,\\n * account shortfall below collateral requirements)\\n */\\n function getAccountLiquidity(address account) public view returns (uint, uint, uint) {\\n (Error err, uint liquidity, uint shortfall) = getHypotheticalAccountLiquidityInternal(account, CToken(0), 0, 0);\\n\\n return (uint(err), liquidity, shortfall);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity wrt collateral requirements\\n * @return (possible error code,\\n account liquidity in excess of collateral requirements,\\n * account shortfall below collateral requirements)\\n */\\n function getAccountLiquidityInternal(address account) internal view returns (Error, uint, uint) {\\n return getHypotheticalAccountLiquidityInternal(account, CToken(0), 0, 0);\\n }\\n\\n /**\\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\\n * @param cTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @return (possible error code (semi-opaque),\\n hypothetical account liquidity in excess of collateral requirements,\\n * hypothetical account shortfall below collateral requirements)\\n */\\n function getHypotheticalAccountLiquidity(\\n address account,\\n address cTokenModify,\\n uint redeemTokens,\\n uint borrowAmount) public view returns (uint, uint, uint) {\\n (Error err, uint liquidity, uint shortfall) = getHypotheticalAccountLiquidityInternal(account, CToken(cTokenModify), 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 cTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @dev Note that we calculate the exchangeRateStored for each collateral cToken using stored data,\\n * without calculating accumulated interest.\\n * @return (possible error code,\\n hypothetical account liquidity in excess of collateral requirements,\\n * hypothetical account shortfall below collateral requirements)\\n */\\n function getHypotheticalAccountLiquidityInternal(\\n address account,\\n CToken cTokenModify,\\n uint redeemTokens,\\n uint borrowAmount) internal view returns (Error, uint, uint) {\\n\\n AccountLiquidityLocalVars memory vars; // Holds all our calculation results\\n uint oErr;\\n MathError mErr;\\n\\n // For each asset the account is in\\n CToken[] memory assets = accountAssets[account];\\n for (uint i = 0; i < assets.length; i++) {\\n CToken asset = assets[i];\\n\\n // Read the balances and exchange rate from the cToken\\n (oErr, vars.cTokenBalance, vars.borrowBalance, vars.exchangeRateMantissa) = asset.getAccountSnapshot(account);\\n if (oErr != 0) { // semi-opaque error code, we assume NO_ERROR == 0 is invariant between upgrades\\n return (Error.SNAPSHOT_ERROR, 0, 0);\\n }\\n vars.collateralFactor = Exp({mantissa: markets[address(asset)].collateralFactorMantissa});\\n vars.exchangeRate = Exp({mantissa: vars.exchangeRateMantissa});\\n\\n // Get the normalized price of the asset\\n vars.oraclePriceMantissa = oracle.getUnderlyingPrice(asset);\\n if (vars.oraclePriceMantissa == 0) {\\n return (Error.PRICE_ERROR, 0, 0);\\n }\\n vars.oraclePrice = Exp({mantissa: vars.oraclePriceMantissa});\\n\\n // Pre-compute a conversion factor from tokens -> 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 * cTokenBalance\\n (mErr, vars.sumCollateral) = mulScalarTruncateAddUInt(vars.tokensToDenom, vars.cTokenBalance, 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 cTokenModify\\n if (asset == cTokenModify) {\\n // redeem effect\\n // sumBorrowPlusEffects += tokensToDenom * redeemTokens\\n (mErr, vars.sumBorrowPlusEffects) = mulScalarTruncateAddUInt(vars.tokensToDenom, redeemTokens, vars.sumBorrowPlusEffects);\\n if (mErr != MathError.NO_ERROR) {\\n return (Error.MATH_ERROR, 0, 0);\\n }\\n\\n // borrow effect\\n // sumBorrowPlusEffects += oraclePrice * borrowAmount\\n (mErr, vars.sumBorrowPlusEffects) = mulScalarTruncateAddUInt(vars.oraclePrice, borrowAmount, vars.sumBorrowPlusEffects);\\n if (mErr != MathError.NO_ERROR) {\\n return (Error.MATH_ERROR, 0, 0);\\n }\\n }\\n }\\n\\n // These are safe, as the underflow condition is checked first\\n if (vars.sumCollateral > vars.sumBorrowPlusEffects) {\\n return (Error.NO_ERROR, vars.sumCollateral - vars.sumBorrowPlusEffects, 0);\\n } else {\\n return (Error.NO_ERROR, 0, vars.sumBorrowPlusEffects - vars.sumCollateral);\\n }\\n }\\n\\n /**\\n * @notice Calculate number of tokens of collateral asset to seize given an underlying amount\\n * @dev Used in liquidation (called in cToken.liquidateBorrowFresh)\\n * @param cTokenBorrowed The address of the borrowed cToken\\n * @param cTokenCollateral The address of the collateral cToken\\n * @param actualRepayAmount The amount of cTokenBorrowed underlying to convert into cTokenCollateral tokens\\n * @return (errorCode, number of cTokenCollateral tokens to be seized in a liquidation)\\n */\\n function liquidateCalculateSeizeTokens(address cTokenBorrowed, address cTokenCollateral, uint actualRepayAmount) external view returns (uint, uint) {\\n /* Read oracle prices for borrowed and collateral markets */\\n uint priceBorrowedMantissa = oracle.getUnderlyingPrice(CToken(cTokenBorrowed));\\n uint priceCollateralMantissa = oracle.getUnderlyingPrice(CToken(cTokenCollateral));\\n if (priceBorrowedMantissa == 0 || priceCollateralMantissa == 0) {\\n return (uint(Error.PRICE_ERROR), 0);\\n }\\n\\n /*\\n * Get the exchange rate and calculate the number of collateral tokens to seize:\\n * seizeAmount = actualRepayAmount * liquidationIncentive * priceBorrowed / priceCollateral\\n * seizeTokens = seizeAmount / exchangeRate\\n * = actualRepayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate)\\n */\\n uint exchangeRateMantissa = CToken(cTokenCollateral).exchangeRateStored(); // Note: reverts on error\\n uint seizeTokens;\\n Exp memory numerator;\\n Exp memory denominator;\\n Exp memory ratio;\\n MathError mathErr;\\n\\n (mathErr, numerator) = mulExp(liquidationIncentiveMantissa, priceBorrowedMantissa);\\n if (mathErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0);\\n }\\n\\n (mathErr, denominator) = mulExp(priceCollateralMantissa, exchangeRateMantissa);\\n if (mathErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0);\\n }\\n\\n (mathErr, ratio) = divExp(numerator, denominator);\\n if (mathErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0);\\n }\\n\\n (mathErr, seizeTokens) = mulScalarTruncate(ratio, actualRepayAmount);\\n if (mathErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0);\\n }\\n\\n return (uint(Error.NO_ERROR), seizeTokens);\\n }\\n\\n /*** Admin Functions ***/\\n\\n /**\\n * @notice Sets a new price oracle for the comptroller\\n * @dev Admin function to set a new price oracle\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPriceOracle(PriceOracle newOracle) public returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PRICE_ORACLE_OWNER_CHECK);\\n }\\n\\n // Track the old oracle for the comptroller\\n PriceOracle oldOracle = oracle;\\n\\n // Set comptroller's oracle to newOracle\\n oracle = newOracle;\\n\\n // Emit NewPriceOracle(oldOracle, newOracle)\\n emit NewPriceOracle(oldOracle, newOracle);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets the closeFactor used when liquidating borrows\\n * @dev Admin function to set closeFactor\\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\\n * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function _setCloseFactor(uint newCloseFactorMantissa) external returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_CLOSE_FACTOR_OWNER_CHECK);\\n }\\n\\n Exp memory newCloseFactorExp = Exp({mantissa: newCloseFactorMantissa});\\n Exp memory lowLimit = Exp({mantissa: closeFactorMinMantissa});\\n if (lessThanOrEqualExp(newCloseFactorExp, lowLimit)) {\\n return fail(Error.INVALID_CLOSE_FACTOR, FailureInfo.SET_CLOSE_FACTOR_VALIDATION);\\n }\\n\\n Exp memory highLimit = Exp({mantissa: closeFactorMaxMantissa});\\n if (lessThanExp(highLimit, newCloseFactorExp)) {\\n return fail(Error.INVALID_CLOSE_FACTOR, FailureInfo.SET_CLOSE_FACTOR_VALIDATION);\\n }\\n\\n uint oldCloseFactorMantissa = closeFactorMantissa;\\n closeFactorMantissa = newCloseFactorMantissa;\\n emit NewCloseFactor(oldCloseFactorMantissa, closeFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets the collateralFactor for a market\\n * @dev Admin function to set per-market collateralFactor\\n * @param cToken The market to set the factor on\\n * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18\\n * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function _setCollateralFactor(CToken cToken, 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(cToken)];\\n if (!market.isListed) {\\n return fail(Error.MARKET_NOT_LISTED, FailureInfo.SET_COLLATERAL_FACTOR_NO_EXISTS);\\n }\\n\\n Exp memory newCollateralFactorExp = Exp({mantissa: newCollateralFactorMantissa});\\n\\n // Check collateral factor <= 0.9\\n Exp memory highLimit = Exp({mantissa: collateralFactorMaxMantissa});\\n if (lessThanExp(highLimit, newCollateralFactorExp)) {\\n return fail(Error.INVALID_COLLATERAL_FACTOR, FailureInfo.SET_COLLATERAL_FACTOR_VALIDATION);\\n }\\n\\n // If collateral factor != 0, fail if price == 0\\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(cToken) == 0) {\\n return fail(Error.PRICE_ERROR, FailureInfo.SET_COLLATERAL_FACTOR_WITHOUT_PRICE);\\n }\\n\\n // Set market's collateral factor to new collateral factor, remember old value\\n uint oldCollateralFactorMantissa = market.collateralFactorMantissa;\\n market.collateralFactorMantissa = newCollateralFactorMantissa;\\n\\n // Emit event with asset, old collateral factor, and new collateral factor\\n emit NewCollateralFactor(cToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets maxAssets which controls how many markets can be entered\\n * @dev Admin function to set maxAssets\\n * @param newMaxAssets New max assets\\n * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function _setMaxAssets(uint newMaxAssets) external returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_MAX_ASSETS_OWNER_CHECK);\\n }\\n\\n uint oldMaxAssets = maxAssets;\\n maxAssets = newMaxAssets;\\n emit NewMaxAssets(oldMaxAssets, newMaxAssets);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets liquidationIncentive\\n * @dev Admin function to set liquidationIncentive\\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\\n * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function _setLiquidationIncentive(uint newLiquidationIncentiveMantissa) external returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_LIQUIDATION_INCENTIVE_OWNER_CHECK);\\n }\\n\\n // Check de-scaled min <= newLiquidationIncentive <= max\\n Exp memory newLiquidationIncentive = Exp({mantissa: newLiquidationIncentiveMantissa});\\n Exp memory minLiquidationIncentive = Exp({mantissa: liquidationIncentiveMinMantissa});\\n if (lessThanExp(newLiquidationIncentive, minLiquidationIncentive)) {\\n return fail(Error.INVALID_LIQUIDATION_INCENTIVE, FailureInfo.SET_LIQUIDATION_INCENTIVE_VALIDATION);\\n }\\n\\n Exp memory maxLiquidationIncentive = Exp({mantissa: liquidationIncentiveMaxMantissa});\\n if (lessThanExp(maxLiquidationIncentive, newLiquidationIncentive)) {\\n return fail(Error.INVALID_LIQUIDATION_INCENTIVE, FailureInfo.SET_LIQUIDATION_INCENTIVE_VALIDATION);\\n }\\n\\n // Save current value for use in log\\n uint oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa;\\n\\n // Set liquidation incentive to new incentive\\n liquidationIncentiveMantissa = newLiquidationIncentiveMantissa;\\n\\n // Emit event with old incentive, new incentive\\n emit NewLiquidationIncentive(oldLiquidationIncentiveMantissa, newLiquidationIncentiveMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Add the market to the markets mapping and set it as listed\\n * @dev Admin function to set isListed and add support for the market\\n * @param cToken The address of the market (token) to list\\n * @return uint 0=success, otherwise a failure. (See enum Error for details)\\n */\\n function _supportMarket(CToken cToken) external returns (uint) {\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SUPPORT_MARKET_OWNER_CHECK);\\n }\\n\\n if (markets[address(cToken)].isListed) {\\n return fail(Error.MARKET_ALREADY_LISTED, FailureInfo.SUPPORT_MARKET_EXISTS);\\n }\\n\\n cToken.isCToken(); // Sanity check to make sure its really a CToken\\n\\n markets[address(cToken)] = Market({isListed: true, isComped: false, collateralFactorMantissa: 0});\\n\\n _addMarketInternal(address(cToken));\\n\\n emit MarketListed(cToken);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n function _addMarketInternal(address cToken) internal {\\n for (uint i = 0; i < allMarkets.length; i ++) {\\n require(allMarkets[i] != CToken(cToken), \\\"market already added\\\");\\n }\\n allMarkets.push(CToken(cToken));\\n }\\n\\n /**\\n * @notice Admin function to change the Pause Guardian\\n * @param newPauseGuardian The address of the new Pause Guardian\\n * @return uint 0=success, otherwise a failure. (See enum Error for details)\\n */\\n function _setPauseGuardian(address newPauseGuardian) public returns (uint) {\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PAUSE_GUARDIAN_OWNER_CHECK);\\n }\\n\\n // Save current value for inclusion in log\\n address oldPauseGuardian = pauseGuardian;\\n\\n // Store pauseGuardian with value newPauseGuardian\\n pauseGuardian = newPauseGuardian;\\n\\n // Emit NewPauseGuardian(OldPauseGuardian, NewPauseGuardian)\\n emit NewPauseGuardian(oldPauseGuardian, pauseGuardian);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n function _setMintPaused(CToken cToken, bool state) public returns (bool) {\\n require(markets[address(cToken)].isListed, \\\"cannot pause a market that is not listed\\\");\\n require(msg.sender == pauseGuardian || msg.sender == admin, \\\"only pause guardian and admin can pause\\\");\\n require(msg.sender == admin || state == true, \\\"only admin can unpause\\\");\\n\\n mintGuardianPaused[address(cToken)] = state;\\n emit ActionPaused(cToken, \\\"Mint\\\", state);\\n return state;\\n }\\n\\n function _setBorrowPaused(CToken cToken, bool state) public returns (bool) {\\n require(markets[address(cToken)].isListed, \\\"cannot pause a market that is not listed\\\");\\n require(msg.sender == pauseGuardian || msg.sender == admin, \\\"only pause guardian and admin can pause\\\");\\n require(msg.sender == admin || state == true, \\\"only admin can unpause\\\");\\n\\n borrowGuardianPaused[address(cToken)] = state;\\n emit ActionPaused(cToken, \\\"Borrow\\\", state);\\n return state;\\n }\\n\\n function _setTransferPaused(bool state) public returns (bool) {\\n require(msg.sender == pauseGuardian || msg.sender == admin, \\\"only pause guardian and admin can pause\\\");\\n require(msg.sender == admin || state == true, \\\"only admin can unpause\\\");\\n\\n transferGuardianPaused = state;\\n emit ActionPaused(\\\"Transfer\\\", state);\\n return state;\\n }\\n\\n function _setSeizePaused(bool state) public returns (bool) {\\n require(msg.sender == pauseGuardian || msg.sender == admin, \\\"only pause guardian and admin can pause\\\");\\n require(msg.sender == admin || state == true, \\\"only admin can unpause\\\");\\n\\n seizeGuardianPaused = state;\\n emit ActionPaused(\\\"Seize\\\", state);\\n return state;\\n }\\n\\n function _become(Unitroller unitroller) public {\\n require(msg.sender == unitroller.admin(), \\\"only unitroller admin can change brains\\\");\\n require(unitroller._acceptImplementation() == 0, \\\"change not authorized\\\");\\n }\\n\\n /**\\n * @notice Checks caller is admin, or this contract is becoming the new implementation\\n */\\n function adminOrInitializing() internal view returns (bool) {\\n return msg.sender == admin || msg.sender == comptrollerImplementation;\\n }\\n\\n /*** Comp Distribution ***/\\n\\n /**\\n * @notice Recalculate and update COMP speeds for all COMP markets\\n */\\n function refreshCompSpeeds() public {\\n require(msg.sender == tx.origin, \\\"only externally owned accounts may refresh speeds\\\");\\n refreshCompSpeedsInternal();\\n }\\n\\n function refreshCompSpeedsInternal() internal {\\n CToken[] memory allMarkets_ = allMarkets;\\n\\n for (uint i = 0; i < allMarkets_.length; i++) {\\n CToken cToken = allMarkets_[i];\\n Exp memory borrowIndex = Exp({mantissa: cToken.borrowIndex()});\\n updateCompSupplyIndex(address(cToken));\\n updateCompBorrowIndex(address(cToken), borrowIndex);\\n }\\n\\n Exp memory totalUtility = Exp({mantissa: 0});\\n Exp[] memory utilities = new Exp[](allMarkets_.length);\\n for (uint i = 0; i < allMarkets_.length; i++) {\\n CToken cToken = allMarkets_[i];\\n if (markets[address(cToken)].isComped) {\\n Exp memory assetPrice = Exp({mantissa: oracle.getUnderlyingPrice(cToken)});\\n Exp memory utility = mul_(assetPrice, cToken.totalBorrows());\\n utilities[i] = utility;\\n totalUtility = add_(totalUtility, utility);\\n }\\n }\\n\\n for (uint i = 0; i < allMarkets_.length; i++) {\\n CToken cToken = allMarkets[i];\\n uint newSpeed = totalUtility.mantissa > 0 ? mul_(compRate, div_(utilities[i], totalUtility)) : 0;\\n compSpeeds[address(cToken)] = newSpeed;\\n emit CompSpeedUpdated(cToken, newSpeed);\\n }\\n }\\n\\n /**\\n * @notice Accrue COMP to the market by updating the supply index\\n * @param cToken The market whose supply index to update\\n */\\n function updateCompSupplyIndex(address cToken) internal {\\n CompMarketState storage supplyState = compSupplyState[cToken];\\n uint supplySpeed = compSpeeds[cToken];\\n uint blockNumber = getBlockNumber();\\n uint deltaBlocks = sub_(blockNumber, uint(supplyState.block));\\n if (deltaBlocks > 0 && supplySpeed > 0) {\\n uint supplyTokens = CToken(cToken).totalSupply();\\n uint compAccrued = mul_(deltaBlocks, supplySpeed);\\n Double memory ratio = supplyTokens > 0 ? fraction(compAccrued, supplyTokens) : Double({mantissa: 0});\\n Double memory index = add_(Double({mantissa: supplyState.index}), ratio);\\n compSupplyState[cToken] = CompMarketState({\\n index: safe224(index.mantissa, \\\"new index exceeds 224 bits\\\"),\\n block: safe32(blockNumber, \\\"block number exceeds 32 bits\\\")\\n });\\n } else if (deltaBlocks > 0) {\\n supplyState.block = safe32(blockNumber, \\\"block number exceeds 32 bits\\\");\\n }\\n }\\n\\n /**\\n * @notice Accrue COMP to the market by updating the borrow index\\n * @param cToken The market whose borrow index to update\\n */\\n function updateCompBorrowIndex(address cToken, Exp memory marketBorrowIndex) internal {\\n CompMarketState storage borrowState = compBorrowState[cToken];\\n uint borrowSpeed = compSpeeds[cToken];\\n uint blockNumber = getBlockNumber();\\n uint deltaBlocks = sub_(blockNumber, uint(borrowState.block));\\n if (deltaBlocks > 0 && borrowSpeed > 0) {\\n uint borrowAmount = div_(CToken(cToken).totalBorrows(), marketBorrowIndex);\\n uint compAccrued = mul_(deltaBlocks, borrowSpeed);\\n Double memory ratio = borrowAmount > 0 ? fraction(compAccrued, borrowAmount) : Double({mantissa: 0});\\n Double memory index = add_(Double({mantissa: borrowState.index}), ratio);\\n compBorrowState[cToken] = CompMarketState({\\n index: safe224(index.mantissa, \\\"new index exceeds 224 bits\\\"),\\n block: safe32(blockNumber, \\\"block number exceeds 32 bits\\\")\\n });\\n } else if (deltaBlocks > 0) {\\n borrowState.block = safe32(blockNumber, \\\"block number exceeds 32 bits\\\");\\n }\\n }\\n\\n /**\\n * @notice Calculate COMP accrued by a supplier and possibly transfer it to them\\n * @param cToken The market in which the supplier is interacting\\n * @param supplier The address of the supplier to distribute COMP to\\n */\\n function distributeSupplierComp(address cToken, address supplier, bool distributeAll) internal {\\n CompMarketState storage supplyState = compSupplyState[cToken];\\n Double memory supplyIndex = Double({mantissa: supplyState.index});\\n Double memory supplierIndex = Double({mantissa: compSupplierIndex[cToken][supplier]});\\n compSupplierIndex[cToken][supplier] = supplyIndex.mantissa;\\n\\n if (supplierIndex.mantissa == 0 && supplyIndex.mantissa > 0) {\\n supplierIndex.mantissa = compInitialIndex;\\n }\\n\\n Double memory deltaIndex = sub_(supplyIndex, supplierIndex);\\n uint supplierTokens = CToken(cToken).balanceOf(supplier);\\n uint supplierDelta = mul_(supplierTokens, deltaIndex);\\n uint supplierAccrued = add_(compAccrued[supplier], supplierDelta);\\n compAccrued[supplier] = transferComp(supplier, supplierAccrued, distributeAll ? 0 : compClaimThreshold);\\n emit DistributedSupplierComp(CToken(cToken), supplier, supplierDelta, supplyIndex.mantissa);\\n }\\n\\n /**\\n * @notice Calculate COMP accrued by a borrower and possibly transfer it to them\\n * @dev Borrowers will not begin to accrue until after the first interaction with the protocol.\\n * @param cToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute COMP to\\n */\\n function distributeBorrowerComp(address cToken, address borrower, Exp memory marketBorrowIndex, bool distributeAll) internal {\\n CompMarketState storage borrowState = compBorrowState[cToken];\\n Double memory borrowIndex = Double({mantissa: borrowState.index});\\n Double memory borrowerIndex = Double({mantissa: compBorrowerIndex[cToken][borrower]});\\n compBorrowerIndex[cToken][borrower] = borrowIndex.mantissa;\\n\\n if (borrowerIndex.mantissa > 0) {\\n Double memory deltaIndex = sub_(borrowIndex, borrowerIndex);\\n uint borrowerAmount = div_(CToken(cToken).borrowBalanceStored(borrower), marketBorrowIndex);\\n uint borrowerDelta = mul_(borrowerAmount, deltaIndex);\\n uint borrowerAccrued = add_(compAccrued[borrower], borrowerDelta);\\n compAccrued[borrower] = transferComp(borrower, borrowerAccrued, distributeAll ? 0 : compClaimThreshold);\\n emit DistributedBorrowerComp(CToken(cToken), borrower, borrowerDelta, borrowIndex.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Transfer COMP to the user, if they are above the threshold\\n * @dev Note: If there is not enough COMP, we do not perform the transfer all.\\n * @param user The address of the user to transfer COMP to\\n * @param userAccrued The amount of COMP to (possibly) transfer\\n * @return The amount of COMP which was NOT transferred to the user\\n */\\n function transferComp(address user, uint userAccrued, uint threshold) internal returns (uint) {\\n if (userAccrued >= threshold && userAccrued > 0) {\\n Comp comp = Comp(getCompAddress());\\n uint compRemaining = comp.balanceOf(address(this));\\n if (userAccrued <= compRemaining) {\\n comp.transfer(user, userAccrued);\\n return 0;\\n }\\n }\\n return userAccrued;\\n }\\n\\n /**\\n * @notice Claim all the comp accrued by holder in all markets\\n * @param holder The address to claim COMP for\\n */\\n function claimComp(address holder) public {\\n return claimComp(holder, allMarkets);\\n }\\n\\n /**\\n * @notice Claim all the comp accrued by holder in the specified markets\\n * @param holder The address to claim COMP for\\n * @param cTokens The list of markets to claim COMP in\\n */\\n function claimComp(address holder, CToken[] memory cTokens) public {\\n address[] memory holders = new address[](1);\\n holders[0] = holder;\\n claimComp(holders, cTokens, true, true);\\n }\\n\\n /**\\n * @notice Claim all comp accrued by the holders\\n * @param holders The addresses to claim COMP for\\n * @param cTokens The list of markets to claim COMP in\\n * @param borrowers Whether or not to claim COMP earned by borrowing\\n * @param suppliers Whether or not to claim COMP earned by supplying\\n */\\n function claimComp(address[] memory holders, CToken[] memory cTokens, bool borrowers, bool suppliers) public {\\n for (uint i = 0; i < cTokens.length; i++) {\\n CToken cToken = cTokens[i];\\n require(markets[address(cToken)].isListed, \\\"market must be listed\\\");\\n if (borrowers == true) {\\n Exp memory borrowIndex = Exp({mantissa: cToken.borrowIndex()});\\n updateCompBorrowIndex(address(cToken), borrowIndex);\\n for (uint j = 0; j < holders.length; j++) {\\n distributeBorrowerComp(address(cToken), holders[j], borrowIndex, true);\\n }\\n }\\n if (suppliers == true) {\\n updateCompSupplyIndex(address(cToken));\\n for (uint j = 0; j < holders.length; j++) {\\n distributeSupplierComp(address(cToken), holders[j], true);\\n }\\n }\\n }\\n }\\n\\n /*** Comp Distribution Admin ***/\\n\\n /**\\n * @notice Set the amount of COMP distributed per block\\n * @param compRate_ The amount of COMP wei per block to distribute\\n */\\n function _setCompRate(uint compRate_) public {\\n require(adminOrInitializing(), \\\"only admin can change comp rate\\\");\\n\\n uint oldRate = compRate;\\n compRate = compRate_;\\n emit NewCompRate(oldRate, compRate_);\\n\\n refreshCompSpeedsInternal();\\n }\\n\\n /**\\n * @notice Add markets to compMarkets, allowing them to earn COMP in the flywheel\\n * @param cTokens The addresses of the markets to add\\n */\\n function _addCompMarkets(address[] memory cTokens) public {\\n require(adminOrInitializing(), \\\"only admin can add comp market\\\");\\n\\n for (uint i = 0; i < cTokens.length; i++) {\\n _addCompMarketInternal(cTokens[i]);\\n }\\n\\n refreshCompSpeedsInternal();\\n }\\n\\n function _addCompMarketInternal(address cToken) internal {\\n Market storage market = markets[cToken];\\n require(market.isListed == true, \\\"comp market is not listed\\\");\\n require(market.isComped == false, \\\"comp market already added\\\");\\n\\n market.isComped = true;\\n emit MarketComped(CToken(cToken), true);\\n\\n if (compSupplyState[cToken].index == 0 && compSupplyState[cToken].block == 0) {\\n compSupplyState[cToken] = CompMarketState({\\n index: compInitialIndex,\\n block: safe32(getBlockNumber(), \\\"block number exceeds 32 bits\\\")\\n });\\n }\\n\\n if (compBorrowState[cToken].index == 0 && compBorrowState[cToken].block == 0) {\\n compBorrowState[cToken] = CompMarketState({\\n index: compInitialIndex,\\n block: safe32(getBlockNumber(), \\\"block number exceeds 32 bits\\\")\\n });\\n }\\n }\\n\\n /**\\n * @notice Remove a market from compMarkets, preventing it from earning COMP in the flywheel\\n * @param cToken The address of the market to drop\\n */\\n function _dropCompMarket(address cToken) public {\\n require(msg.sender == admin, \\\"only admin can drop comp market\\\");\\n\\n Market storage market = markets[cToken];\\n require(market.isComped == true, \\\"market is not a comp market\\\");\\n\\n market.isComped = false;\\n emit MarketComped(CToken(cToken), false);\\n\\n refreshCompSpeedsInternal();\\n }\\n\\n /**\\n * @notice Return all of the markets\\n * @dev The automatic getter may be used to access an individual market.\\n * @return The list of market addresses\\n */\\n function getAllMarkets() public view returns (CToken[] memory) {\\n return allMarkets;\\n }\\n\\n function getBlockNumber() public view returns (uint) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Return the address of the COMP token\\n * @return The address of COMP\\n */\\n function getCompAddress() public view returns (address) {\\n return 0xc00e94Cb662C3520282E6f5717214004A7f26888;\\n }\\n}\\n\",\"keccak256\":\"0xb78d0330a0c8697901972280103a7749d673d6b6d8084002ab4f53cc853ade4c\"},\"contracts/ComptrollerInterface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\ncontract ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n bool public constant isComptroller = true;\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata cTokens) external returns (uint[] memory);\\n function exitMarket(address cToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address cToken, address minter, uint mintAmount) external returns (uint);\\n function mintVerify(address cToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address cToken, address redeemer, uint redeemTokens) external returns (uint);\\n function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address cToken, address borrower, uint borrowAmount) external returns (uint);\\n function borrowVerify(address cToken, address borrower, uint borrowAmount) external;\\n\\n function repayBorrowAllowed(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount) external returns (uint);\\n function repayBorrowVerify(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex) external;\\n\\n function liquidateBorrowAllowed(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount) external returns (uint);\\n function liquidateBorrowVerify(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens) external;\\n\\n function seizeAllowed(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external returns (uint);\\n function seizeVerify(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external;\\n\\n function transferAllowed(address cToken, address src, address dst, uint transferTokens) external returns (uint);\\n function transferVerify(address cToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n uint repayAmount) external view returns (uint, uint);\\n}\\n\",\"keccak256\":\"0xede7670d2dd7b25d0187aecd2c28b7b5ca7d7c1bdac144fbedecf5d4bdd92a6b\"},\"contracts/ComptrollerStorage.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.sol\\\";\\nimport \\\"./PriceOracle.sol\\\";\\n\\ncontract UnitrollerAdminStorage {\\n /**\\n * @notice Administrator for this contract\\n */\\n address public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address public pendingAdmin;\\n\\n /**\\n * @notice Active brains of Unitroller\\n */\\n address public comptrollerImplementation;\\n\\n /**\\n * @notice Pending brains of Unitroller\\n */\\n address public pendingComptrollerImplementation;\\n}\\n\\ncontract ComptrollerV1Storage is UnitrollerAdminStorage {\\n\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n PriceOracle public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives\\n */\\n uint public liquidationIncentiveMantissa;\\n\\n /**\\n * @notice Max number of assets a single account can participate in (borrow or use as collateral)\\n */\\n uint public maxAssets;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\\n */\\n mapping(address => CToken[]) public accountAssets;\\n\\n}\\n\\ncontract ComptrollerV2Storage is ComptrollerV1Storage {\\n struct Market {\\n /// @notice Whether or not this market is listed\\n bool isListed;\\n\\n /**\\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\\n * For instance, 0.9 to allow borrowing 90% of collateral value.\\n * Must be between 0 and 1, and stored as a mantissa.\\n */\\n uint collateralFactorMantissa;\\n\\n /// @notice Per-market mapping of \\\"accounts in this asset\\\"\\n mapping(address => bool) accountMembership;\\n\\n /// @notice Whether or not this market receives COMP\\n bool isComped;\\n }\\n\\n /**\\n * @notice Official mapping of cTokens -> Market metadata\\n * @dev Used e.g. to determine if a market is supported\\n */\\n mapping(address => Market) public markets;\\n\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n * Actions which allow users to remove their own assets cannot be paused.\\n * Liquidation / seizing / transfer can only be paused globally, not by market.\\n */\\n address public pauseGuardian;\\n bool public _mintGuardianPaused;\\n bool public _borrowGuardianPaused;\\n bool public transferGuardianPaused;\\n bool public seizeGuardianPaused;\\n mapping(address => bool) public mintGuardianPaused;\\n mapping(address => bool) public borrowGuardianPaused;\\n}\\n\\ncontract ComptrollerV3Storage is ComptrollerV2Storage {\\n struct CompMarketState {\\n /// @notice The market's last updated compBorrowIndex or compSupplyIndex\\n uint224 index;\\n\\n /// @notice The block number the index was last updated at\\n uint32 block;\\n }\\n\\n /// @notice A list of all markets\\n CToken[] public allMarkets;\\n\\n /// @notice The rate at which the flywheel distributes COMP, per block\\n uint public compRate;\\n\\n /// @notice The portion of compRate that each market currently receives\\n mapping(address => uint) public compSpeeds;\\n\\n /// @notice The COMP market supply state for each market\\n mapping(address => CompMarketState) public compSupplyState;\\n\\n /// @notice The COMP market borrow state for each market\\n mapping(address => CompMarketState) public compBorrowState;\\n\\n /// @notice The COMP borrow index for each market for each supplier as of the last time they accrued COMP\\n mapping(address => mapping(address => uint)) public compSupplierIndex;\\n\\n /// @notice The COMP borrow index for each market for each borrower as of the last time they accrued COMP\\n mapping(address => mapping(address => uint)) public compBorrowerIndex;\\n\\n /// @notice The COMP accrued but not yet transferred to each user\\n mapping(address => uint) public compAccrued;\\n}\\n\\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\\n // @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\\n address public borrowCapGuardian;\\n\\n // @notice Borrow caps enforced by borrowAllowed for each cToken address. Defaults to zero which corresponds to unlimited borrowing.\\n mapping(address => uint) public borrowCaps;\\n}\\n\\ncontract ComptrollerV5Storage is ComptrollerV4Storage {\\n /// @notice The portion of COMP that each contributor receives per block\\n mapping(address => uint) public compContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's COMP rewards have been allocated\\n mapping(address => uint) public lastContributorBlock;\\n}\\n\",\"keccak256\":\"0x5db970485549f493618b5e36bfd4d799d4f8701a136bf71ed6e0117e1ed8c254\"},\"contracts/EIP20Interface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title ERC 20 Token Standard Interface\\n * https://eips.ethereum.org/EIPS/eip-20\\n */\\ninterface EIP20Interface {\\n function name() external view returns (string memory);\\n function symbol() external view returns (string memory);\\n function decimals() external view returns (uint8);\\n\\n /**\\n * @notice Get the total number of tokens in circulation\\n * @return The supply of tokens\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @notice Gets the balance of the specified address\\n * @param owner The address from which the balance will be retrieved\\n * @return The balance\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transfer(address dst, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferFrom(address src, address dst, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (-1 means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (-1 means infinite)\\n */\\n function allowance(address owner, address spender) external view returns (uint256 remaining);\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n}\\n\",\"keccak256\":\"0xfd8ed2eac6d0b4d9ee6b32628ba68bae17544b66f190a5f7ce0c6ad024579dc8\"},\"contracts/EIP20NonStandardInterface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title EIP20NonStandardInterface\\n * @dev Version of ERC20 with no return values for `transfer` and `transferFrom`\\n * See https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\\n */\\ninterface EIP20NonStandardInterface {\\n\\n /**\\n * @notice Get the total number of tokens in circulation\\n * @return The supply of tokens\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @notice Gets the balance of the specified address\\n * @param owner The address from which the balance will be retrieved\\n * @return The balance\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n ///\\n /// !!!!!!!!!!!!!!\\n /// !!! NOTICE !!! `transfer` does not return a value, in violation of the ERC-20 specification\\n /// !!!!!!!!!!!!!!\\n ///\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n */\\n function transfer(address dst, uint256 amount) external;\\n\\n ///\\n /// !!!!!!!!!!!!!!\\n /// !!! NOTICE !!! `transferFrom` does not return a value, in violation of the ERC-20 specification\\n /// !!!!!!!!!!!!!!\\n ///\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n */\\n function transferFrom(address src, address dst, uint256 amount) external;\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent\\n */\\n function allowance(address owner, address spender) external view returns (uint256 remaining);\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n}\\n\",\"keccak256\":\"0x9719f12e4b80b51147ac195553a198cf8b0c516e7e4d04fc324a23ed15cbafb2\"},\"contracts/ErrorReporter.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\ncontract ComptrollerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\",\"keccak256\":\"0x5179afb1071c0fd555e5c1f1d2565f72dbe1740cc3dd02f6e52037f150afc5c9\"},\"contracts/Exponential.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CarefulMath.sol\\\";\\nimport \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @dev Legacy contract for compatibility reasons with existing contracts that still use MathError\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: rational}));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({mantissa: result}));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({mantissa: result}));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: scaledMantissa}));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: descaledMantissa}));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) pure internal returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({mantissa: 0}));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({mantissa: product}));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) pure internal returns (MathError, Exp memory) {\\n return mulExp(Exp({mantissa: a}), Exp({mantissa: b}));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) pure internal returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6ff054d65a0289dbb43c9f437d6909f9cf1207c9b8f984b3cb8e97a9de76a434\"},\"contracts/ExponentialNoError.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\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 Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) pure internal returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) pure internal returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) pure internal returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) pure internal returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) pure internal returns (uint224) {\\n require(n < 2**224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) pure internal returns (uint32) {\\n require(n < 2**32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: add_(a.mantissa, b.mantissa)});\\n }\\n\\n function add_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: add_(a.mantissa, b.mantissa)});\\n }\\n\\n function add_(uint a, uint b) pure internal returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: sub_(a.mantissa, b.mantissa)});\\n }\\n\\n function sub_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: sub_(a.mantissa, b.mantissa)});\\n }\\n\\n function sub_(uint a, uint b) pure internal returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: mul_(a.mantissa, b.mantissa) / expScale});\\n }\\n\\n function mul_(Exp memory a, uint b) pure internal returns (Exp memory) {\\n return Exp({mantissa: mul_(a.mantissa, b)});\\n }\\n\\n function mul_(uint a, Exp memory b) pure internal returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: mul_(a.mantissa, b.mantissa) / doubleScale});\\n }\\n\\n function mul_(Double memory a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: mul_(a.mantissa, b)});\\n }\\n\\n function mul_(uint a, Double memory b) pure internal returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) pure internal returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) pure internal 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) pure internal returns (Exp memory) {\\n return Exp({mantissa: div_(mul_(a.mantissa, expScale), b.mantissa)});\\n }\\n\\n function div_(Exp memory a, uint b) pure internal returns (Exp memory) {\\n return Exp({mantissa: div_(a.mantissa, b)});\\n }\\n\\n function div_(uint a, Exp memory b) pure internal returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa)});\\n }\\n\\n function div_(Double memory a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(a.mantissa, b)});\\n }\\n\\n function div_(uint a, Double memory b) pure internal returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) pure internal returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(mul_(a, doubleScale), b)});\\n }\\n}\\n\",\"keccak256\":\"0x7cb184b7cee71a5e707053dfba7eebbd46f11974004028100510ccce19b6694d\"},\"contracts/Governance/Comp.sol\":{\"content\":\"pragma solidity ^0.5.16;\\npragma experimental ABIEncoderV2;\\n\\ncontract Comp {\\n /// @notice EIP-20 token name for this token\\n string public constant name = \\\"Compound\\\";\\n\\n /// @notice EIP-20 token symbol for this token\\n string public constant symbol = \\\"COMP\\\";\\n\\n /// @notice EIP-20 token decimals for this token\\n uint8 public constant decimals = 18;\\n\\n /// @notice Total number of tokens in circulation\\n uint public constant totalSupply = 10000000e18; // 10 million Comp\\n\\n /// @notice Allowance amounts on behalf of others\\n mapping (address => mapping (address => uint96)) internal allowances;\\n\\n /// @notice Official record of token balances for each account\\n mapping (address => uint96) internal balances;\\n\\n /// @notice A record of each accounts delegate\\n mapping (address => address) public delegates;\\n\\n /// @notice A checkpoint for marking number of votes from a given block\\n struct Checkpoint {\\n uint32 fromBlock;\\n uint96 votes;\\n }\\n\\n /// @notice A record of votes checkpoints for each account, by index\\n mapping (address => mapping (uint32 => Checkpoint)) public checkpoints;\\n\\n /// @notice The number of checkpoints for each account\\n mapping (address => uint32) public numCheckpoints;\\n\\n /// @notice The EIP-712 typehash for the contract's domain\\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\\\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\\\");\\n\\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\\\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\\\");\\n\\n /// @notice A record of states for signing / validating signatures\\n mapping (address => uint) public nonces;\\n\\n /// @notice An event thats emitted when an account changes its delegate\\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\\n\\n /// @notice An event thats emitted when a delegate account's vote balance changes\\n event DelegateVotesChanged(address indexed delegate, uint previousBalance, uint newBalance);\\n\\n /// @notice The standard EIP-20 transfer event\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n\\n /// @notice The standard EIP-20 approval event\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n\\n /**\\n * @notice Construct a new Comp token\\n * @param account The initial account to grant all the tokens\\n */\\n constructor(address account) public {\\n balances[account] = uint96(totalSupply);\\n emit Transfer(address(0), account, totalSupply);\\n }\\n\\n /**\\n * @notice Get the number of tokens `spender` is approved to spend on behalf of `account`\\n * @param account The address of the account holding the funds\\n * @param spender The address of the account spending the funds\\n * @return The number of tokens approved\\n */\\n function allowance(address account, address spender) external view returns (uint) {\\n return allowances[account][spender];\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param rawAmount The number of tokens that are approved (2^256-1 means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint rawAmount) external returns (bool) {\\n uint96 amount;\\n if (rawAmount == uint(-1)) {\\n amount = uint96(-1);\\n } else {\\n amount = safe96(rawAmount, \\\"Comp::approve: amount exceeds 96 bits\\\");\\n }\\n\\n allowances[msg.sender][spender] = amount;\\n\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the number of tokens held by the `account`\\n * @param account The address of the account to get the balance of\\n * @return The number of tokens held\\n */\\n function balanceOf(address account) external view returns (uint) {\\n return balances[account];\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param rawAmount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transfer(address dst, uint rawAmount) external returns (bool) {\\n uint96 amount = safe96(rawAmount, \\\"Comp::transfer: amount exceeds 96 bits\\\");\\n _transferTokens(msg.sender, dst, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param rawAmount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferFrom(address src, address dst, uint rawAmount) external returns (bool) {\\n address spender = msg.sender;\\n uint96 spenderAllowance = allowances[src][spender];\\n uint96 amount = safe96(rawAmount, \\\"Comp::approve: amount exceeds 96 bits\\\");\\n\\n if (spender != src && spenderAllowance != uint96(-1)) {\\n uint96 newAllowance = sub96(spenderAllowance, amount, \\\"Comp::transferFrom: transfer amount exceeds spender allowance\\\");\\n allowances[src][spender] = newAllowance;\\n\\n emit Approval(src, spender, newAllowance);\\n }\\n\\n _transferTokens(src, dst, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Delegate votes from `msg.sender` to `delegatee`\\n * @param delegatee The address to delegate votes to\\n */\\n function delegate(address delegatee) public {\\n return _delegate(msg.sender, delegatee);\\n }\\n\\n /**\\n * @notice Delegates votes from signatory to `delegatee`\\n * @param delegatee The address to delegate votes to\\n * @param nonce The contract state required to match the signature\\n * @param expiry The time at which to expire the signature\\n * @param v The recovery byte of the signature\\n * @param r Half of the ECDSA signature pair\\n * @param s Half of the ECDSA signature pair\\n */\\n function delegateBySig(address delegatee, uint nonce, uint expiry, uint8 v, bytes32 r, bytes32 s) public {\\n bytes32 domainSeparator = keccak256(abi.encode(DOMAIN_TYPEHASH, keccak256(bytes(name)), getChainId(), address(this)));\\n bytes32 structHash = keccak256(abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry));\\n bytes32 digest = keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash));\\n address signatory = ecrecover(digest, v, r, s);\\n require(signatory != address(0), \\\"Comp::delegateBySig: invalid signature\\\");\\n require(nonce == nonces[signatory]++, \\\"Comp::delegateBySig: invalid nonce\\\");\\n require(now <= expiry, \\\"Comp::delegateBySig: signature expired\\\");\\n return _delegate(signatory, delegatee);\\n }\\n\\n /**\\n * @notice Gets the current votes balance for `account`\\n * @param account The address to get votes balance\\n * @return The number of current votes for `account`\\n */\\n function getCurrentVotes(address account) external view returns (uint96) {\\n uint32 nCheckpoints = numCheckpoints[account];\\n return nCheckpoints > 0 ? checkpoints[account][nCheckpoints - 1].votes : 0;\\n }\\n\\n /**\\n * @notice Determine the prior number of votes for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param account The address of the account to check\\n * @param blockNumber The block number to get the vote balance at\\n * @return The number of votes the account had as of the given block\\n */\\n function getPriorVotes(address account, uint blockNumber) public view returns (uint96) {\\n require(blockNumber < block.number, \\\"Comp::getPriorVotes: not yet determined\\\");\\n\\n uint32 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (checkpoints[account][nCheckpoints - 1].fromBlock <= blockNumber) {\\n return checkpoints[account][nCheckpoints - 1].votes;\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[account][0].fromBlock > blockNumber) {\\n return 0;\\n }\\n\\n uint32 lower = 0;\\n uint32 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[account][center];\\n if (cp.fromBlock == blockNumber) {\\n return cp.votes;\\n } else if (cp.fromBlock < blockNumber) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return checkpoints[account][lower].votes;\\n }\\n\\n function _delegate(address delegator, address delegatee) internal {\\n address currentDelegate = delegates[delegator];\\n uint96 delegatorBalance = balances[delegator];\\n delegates[delegator] = delegatee;\\n\\n emit DelegateChanged(delegator, currentDelegate, delegatee);\\n\\n _moveDelegates(currentDelegate, delegatee, delegatorBalance);\\n }\\n\\n function _transferTokens(address src, address dst, uint96 amount) internal {\\n require(src != address(0), \\\"Comp::_transferTokens: cannot transfer from the zero address\\\");\\n require(dst != address(0), \\\"Comp::_transferTokens: cannot transfer to the zero address\\\");\\n\\n balances[src] = sub96(balances[src], amount, \\\"Comp::_transferTokens: transfer amount exceeds balance\\\");\\n balances[dst] = add96(balances[dst], amount, \\\"Comp::_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 && amount > 0) {\\n if (srcRep != address(0)) {\\n uint32 srcRepNum = numCheckpoints[srcRep];\\n uint96 srcRepOld = srcRepNum > 0 ? checkpoints[srcRep][srcRepNum - 1].votes : 0;\\n uint96 srcRepNew = sub96(srcRepOld, amount, \\\"Comp::_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 > 0 ? checkpoints[dstRep][dstRepNum - 1].votes : 0;\\n uint96 dstRepNew = add96(dstRepOld, amount, \\\"Comp::_moveVotes: vote amount overflows\\\");\\n _writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew);\\n }\\n }\\n }\\n\\n function _writeCheckpoint(address delegatee, uint32 nCheckpoints, uint96 oldVotes, uint96 newVotes) internal {\\n uint32 blockNumber = safe32(block.number, \\\"Comp::_writeCheckpoint: block number exceeds 32 bits\\\");\\n\\n if (nCheckpoints > 0 && checkpoints[delegatee][nCheckpoints - 1].fromBlock == blockNumber) {\\n checkpoints[delegatee][nCheckpoints - 1].votes = newVotes;\\n } else {\\n checkpoints[delegatee][nCheckpoints] = Checkpoint(blockNumber, newVotes);\\n numCheckpoints[delegatee] = nCheckpoints + 1;\\n }\\n\\n emit DelegateVotesChanged(delegatee, oldVotes, newVotes);\\n }\\n\\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\\n require(n < 2**32, errorMessage);\\n return uint32(n);\\n }\\n\\n function safe96(uint n, string memory errorMessage) internal pure returns (uint96) {\\n require(n < 2**96, errorMessage);\\n return uint96(n);\\n }\\n\\n function add96(uint96 a, uint96 b, string memory errorMessage) internal pure returns (uint96) {\\n uint96 c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub96(uint96 a, uint96 b, string memory errorMessage) internal pure returns (uint96) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function getChainId() internal pure returns (uint) {\\n uint256 chainId;\\n assembly { chainId := chainid() }\\n return chainId;\\n }\\n}\\n\",\"keccak256\":\"0x539f7158013dd91efd3ad42dc6a56e0f7aebdca06063d40ce7b6e9a981b726a3\"},\"contracts/InterestRateModel.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Compound's InterestRateModel Interface\\n * @author Compound\\n */\\ncontract InterestRateModel {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint cash, uint borrows, uint reserves) external view returns (uint);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) external view returns (uint);\\n\\n}\\n\",\"keccak256\":\"0x929282d73c79e6d700ebe79f9fafc1e414b3848acff5a56d6740afd1dc908678\"},\"contracts/PriceOracle.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.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 cToken asset\\n * @param cToken The cToken to get the underlying price of\\n * @return The underlying asset price mantissa (scaled by 1e18).\\n * Zero means the price is unavailable.\\n */\\n function getUnderlyingPrice(CToken cToken) external view returns (uint);\\n}\\n\",\"keccak256\":\"0xe79ebc23bba508eb2479e7b3340abf566da1ab62131f106aee1aac3dc53816ef\"},\"contracts/Unitroller.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ErrorReporter.sol\\\";\\nimport \\\"./ComptrollerStorage.sol\\\";\\n/**\\n * @title ComptrollerCore\\n * @dev Storage for the comptroller is at this address, while execution is delegated to the `comptrollerImplementation`.\\n * CTokens should reference this contract as their comptroller.\\n */\\ncontract Unitroller is UnitrollerAdminStorage, ComptrollerErrorReporter {\\n\\n /**\\n * @notice Emitted when pendingComptrollerImplementation is changed\\n */\\n event NewPendingImplementation(address oldPendingImplementation, address newPendingImplementation);\\n\\n /**\\n * @notice Emitted when pendingComptrollerImplementation is accepted, which means comptroller implementation is updated\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Emitted when pendingAdmin is accepted, which means admin is updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n constructor() public {\\n // Set admin to caller\\n admin = msg.sender;\\n }\\n\\n /*** Admin Functions ***/\\n function _setPendingImplementation(address newPendingImplementation) public returns (uint) {\\n\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_IMPLEMENTATION_OWNER_CHECK);\\n }\\n\\n address oldPendingImplementation = pendingComptrollerImplementation;\\n\\n pendingComptrollerImplementation = newPendingImplementation;\\n\\n emit NewPendingImplementation(oldPendingImplementation, pendingComptrollerImplementation);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts new implementation of comptroller. msg.sender must be pendingImplementation\\n * @dev Admin function for new implementation to accept it's role as implementation\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptImplementation() public returns (uint) {\\n // Check caller is pendingImplementation and pendingImplementation \\u2260 address(0)\\n if (msg.sender != pendingComptrollerImplementation || pendingComptrollerImplementation == address(0)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldImplementation = comptrollerImplementation;\\n address oldPendingImplementation = pendingComptrollerImplementation;\\n\\n comptrollerImplementation = pendingComptrollerImplementation;\\n\\n pendingComptrollerImplementation = address(0);\\n\\n emit NewImplementation(oldImplementation, comptrollerImplementation);\\n emit NewPendingImplementation(oldPendingImplementation, pendingComptrollerImplementation);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPendingAdmin(address newPendingAdmin) public returns (uint) {\\n // Check caller = admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\\n }\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptAdmin() public returns (uint) {\\n // Check caller is pendingAdmin and pendingAdmin \\u2260 address(0)\\n if (msg.sender != pendingAdmin || msg.sender == address(0)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = address(0);\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return 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 () payable external {\\n // delegate all other functions to current implementation\\n (bool success, ) = comptrollerImplementation.delegatecall(msg.data);\\n\\n assembly {\\n let free_mem_ptr := mload(0x40)\\n returndatacopy(free_mem_ptr, 0, returndatasize)\\n\\n switch success\\n case 0 { revert(free_mem_ptr, returndatasize) }\\n default { return(free_mem_ptr, returndatasize) }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x51f81451eab9d5c4849507e724f2b2c53e41f54e5359fdbeae89432a727c16df\"}},\"version\":1}" + }, + "contracts/ComptrollerG5.sol:ComptrollerG5": { + "abi": "[{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"action\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"pauseState\",\"type\":\"bool\"}],\"name\":\"ActionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"action\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"pauseState\",\"type\":\"bool\"}],\"name\":\"ActionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSpeed\",\"type\":\"uint256\"}],\"name\":\"CompSpeedUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compBorrowIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedBorrowerComp\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"supplier\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compSupplyIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedSupplierComp\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isComped\",\"type\":\"bool\"}],\"name\":\"MarketComped\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketEntered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketExited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"MarketListed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newBorrowCap\",\"type\":\"uint256\"}],\"name\":\"NewBorrowCap\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldBorrowCapGuardian\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newBorrowCapGuardian\",\"type\":\"address\"}],\"name\":\"NewBorrowCapGuardian\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCloseFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCloseFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCollateralFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCollateralFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCompRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCompRate\",\"type\":\"uint256\"}],\"name\":\"NewCompRate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldLiquidationIncentiveMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"NewLiquidationIncentive\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMaxAssets\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMaxAssets\",\"type\":\"uint256\"}],\"name\":\"NewMaxAssets\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldPauseGuardian\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"NewPauseGuardian\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"oldPriceOracle\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"newPriceOracle\",\"type\":\"address\"}],\"name\":\"NewPriceOracle\",\"type\":\"event\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"_addCompMarkets\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract Unitroller\",\"name\":\"unitroller\",\"type\":\"address\"}],\"name\":\"_become\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"_dropCompMarket\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"newBorrowCapGuardian\",\"type\":\"address\"}],\"name\":\"_setBorrowCapGuardian\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setBorrowPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCloseFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCollateralFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"compRate_\",\"type\":\"uint256\"}],\"name\":\"_setCompRate\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"_setLiquidationIncentive\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"cTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"newBorrowCaps\",\"type\":\"uint256[]\"}],\"name\":\"_setMarketBorrowCaps\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newMaxAssets\",\"type\":\"uint256\"}],\"name\":\"_setMaxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setMintPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"_setPauseGuardian\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"newOracle\",\"type\":\"address\"}],\"name\":\"_setPriceOracle\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setSeizePaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setTransferPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"_supportMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allMarkets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"borrowCapGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"checkMembership\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"},{\"internalType\":\"contract CToken[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"holders\",\"type\":\"address[]\"},{\"internalType\":\"contract CToken[]\",\"name\":\"cTokens\",\"type\":\"address[]\"},{\"internalType\":\"bool\",\"name\":\"borrowers\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"suppliers\",\"type\":\"bool\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compAccrued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compBorrowState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compBorrowerIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compClaimThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compInitialIndex\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSupplierIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSupplyState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"enterMarkets\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenAddress\",\"type\":\"address\"}],\"name\":\"exitMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getAllMarkets\",\"outputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAssetsIn\",\"outputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getCompAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenModify\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"getHypotheticalAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"isComptroller\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateCalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"liquidationIncentiveMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"markets\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isComped\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"mintAmount\",\"type\":\"uint256\"}],\"name\":\"mintAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualMintAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"mintTokens\",\"type\":\"uint256\"}],\"name\":\"mintVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"refreshCompSpeeds\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"repayBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowerIndex\",\"type\":\"uint256\"}],\"name\":\"repayBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"seizeGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"transferGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + "bin": "608060405234801561001057600080fd5b50600080546001600160a01b03191633179055615f9480620000336000396000f3fe608060405234801561001057600080fd5b50600436106104485760003560e01c80636d154ea511610241578063bb82aa5e1161013b578063da3d454c116100c3578063e875544611610087578063e875544614611208578063e9af029214611210578063eabe7d9114611236578063ede4edd01461126c578063f851a4401461129257610448565b8063da3d454c1461116a578063dce15449146111a0578063dcfbc0c7146111cc578063e4028eee146111d4578063e6653f3d1461120057610448565b8063ca0af0431161010a578063ca0af04314611012578063cc7ebdc414611040578063ce485c5e14611066578063d02f735114611107578063d9226ced1461114d57610448565b8063bb82aa5e14610ede578063bdcdc25814610ee6578063c299823814610f22578063c488847b14610fc357610448565b8063929fe9a1116101c9578063aa9007541161018d578063aa90075414610e22578063abfceffc14610e2a578063ac0b0bb714610ea0578063b0772d0b14610ea8578063b21be7fd14610eb057610448565b8063929fe9a114610d9a57806394b2294b14610dc85780639d1b5a0a14610dd0578063a76b3fda14610dd8578063a7f0e23114610dfe57610448565b80637dc0d1d0116102105780637dc0d1d014610cfd57806387f7630314610d055780638c57804e14610d0d5780638e8f294b14610d335780638ebf636414610d7b57610448565b80636d154ea514610c635780636d35bf9114610c89578063731f0c2b14610ccf578063747026c914610cf557610448565b806347ef3b3b1161035257806355ee1fe1116102da578063607ef6c11161029e578063607ef6c1146109d25780636810dfa614610a905780636a49111214610bbc5780636a56947e14610bd95780636b79c38d14610c1557610448565b806355ee1fe1146108e45780635c7786051461090a5780635ec88c79146109405780635f5af1aa146109665780635fc7e71e1461098c57610448565b80634e79238f116103215780634e79238f146107de5780634ef4c3e1146108385780634fd42e171461086e57806351dff9891461088b57806352d84d1e146108c757610448565b806347ef3b3b1461075c5780634a584432146107a85780634ada90af146107ce5780634d8e5037146107d657610448565b806326782247116103d55780633aa729b4116103a45780633aa729b4146106bc5780633bcf7ec1146106e25780633c94786f1461071057806341c728b91461071857806342cbb15c1461075457610448565b806326782247146106525780632d70db781461065a578063317b0b7714610679578063391957d71461069657610448565b80631d7b33d71161041c5780631d7b33d7146105705780631ededc91146105a857806321af4569146105ea57806324008a621461060e57806324a3d6221461064a57610448565b80627e3dd21461044d57806318c882a5146104695780631c3db2e0146104975780631d504dc61461054a575b600080fd5b61045561129a565b604080519115158252519081900360200190f35b6104556004803603604081101561047f57600080fd5b506001600160a01b038135169060200135151561129f565b610548600480360360408110156104ad57600080fd5b6001600160a01b038235169190810190604081016020820135600160201b8111156104d757600080fd5b8201836020820111156104e957600080fd5b803590602001918460208302840111600160201b8311171561050a57600080fd5b91908080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525092955061143f945050505050565b005b6105486004803603602081101561056057600080fd5b50356001600160a01b03166114a1565b6105966004803603602081101561058657600080fd5b50356001600160a01b0316611600565b60408051918252519081900360200190f35b610548600480360360a08110156105be57600080fd5b506001600160a01b03813581169160208101358216916040820135169060608101359060800135611612565b6105f2611619565b604080516001600160a01b039092168252519081900360200190f35b6105966004803603608081101561062457600080fd5b506001600160a01b03813581169160208101358216916040820135169060600135611628565b6105f26116f1565b6105f2611700565b6104556004803603602081101561067057600080fd5b5035151561170f565b6105966004803603602081101561068f57600080fd5b5035611849565b610548600480360360208110156106ac57600080fd5b50356001600160a01b031661195a565b610548600480360360208110156106d257600080fd5b50356001600160a01b0316611a06565b610455600480360360408110156106f857600080fd5b506001600160a01b0381351690602001351515611b37565b610455611cd2565b6105486004803603608081101561072e57600080fd5b506001600160a01b03813581169160208101359091169060408101359060600135611ce2565b610596611ce8565b610548600480360360c081101561077257600080fd5b506001600160a01b0381358116916020810135821691604082013581169160608101359091169060808101359060a00135611ced565b610596600480360360208110156107be57600080fd5b50356001600160a01b0316611cf5565b610596611d07565b610548611d0d565b61081a600480360360808110156107f457600080fd5b506001600160a01b03813581169160208101359091169060408101359060600135611d55565b60408051938452602084019290925282820152519081900360600190f35b6105966004803603606081101561084e57600080fd5b506001600160a01b03813581169160208101359091169060400135611d8f565b6105966004803603602081101561088457600080fd5b5035611e3a565b610548600480360360808110156108a157600080fd5b506001600160a01b03813581169160208101359091169060408101359060600135611f2e565b6105f2600480360360208110156108dd57600080fd5b5035611f82565b610596600480360360208110156108fa57600080fd5b50356001600160a01b0316611fa9565b6105486004803603606081101561092057600080fd5b506001600160a01b03813581169160208101359091169060400135612030565b61081a6004803603602081101561095657600080fd5b50356001600160a01b0316612035565b6105966004803603602081101561097c57600080fd5b50356001600160a01b031661206a565b610596600480360360a08110156109a257600080fd5b506001600160a01b03813581169160208101358216916040820135811691606081013590911690608001356120ee565b610548600480360360408110156109e857600080fd5b810190602081018135600160201b811115610a0257600080fd5b820183602082011115610a1457600080fd5b803590602001918460208302840111600160201b83111715610a3557600080fd5b919390929091602081019035600160201b811115610a5257600080fd5b820183602082011115610a6457600080fd5b803590602001918460208302840111600160201b83111715610a8557600080fd5b509092509050612275565b61054860048036036080811015610aa657600080fd5b810190602081018135600160201b811115610ac057600080fd5b820183602082011115610ad257600080fd5b803590602001918460208302840111600160201b83111715610af357600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b811115610b4257600080fd5b820183602082011115610b5457600080fd5b803590602001918460208302840111600160201b83111715610b7557600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550505050803515159150602001351515612405565b61054860048036036020811015610bd257600080fd5b50356125ae565b61054860048036036080811015610bef57600080fd5b506001600160a01b03813581169160208101358216916040820135169060600135611ce2565b610c3b60048036036020811015610c2b57600080fd5b50356001600160a01b0316612652565b604080516001600160e01b03909316835263ffffffff90911660208301528051918290030190f35b61045560048036036020811015610c7957600080fd5b50356001600160a01b031661267c565b610548600480360360a0811015610c9f57600080fd5b506001600160a01b0381358116916020810135821691604082013581169160608101359091169060800135611612565b61045560048036036020811015610ce557600080fd5b50356001600160a01b0316612691565b6105966126a6565b6105f26126b1565b6104556126c0565b610c3b60048036036020811015610d2357600080fd5b50356001600160a01b03166126d0565b610d5960048036036020811015610d4957600080fd5b50356001600160a01b03166126fa565b6040805193151584526020840192909252151582820152519081900360600190f35b61045560048036036020811015610d9157600080fd5b50351515612720565b61045560048036036040811015610db057600080fd5b506001600160a01b0381358116916020013516612859565b61059661288c565b6105f2612892565b61059660048036036020811015610dee57600080fd5b50356001600160a01b03166128aa565b610e06612a07565b604080516001600160e01b039092168252519081900360200190f35b610596612a1a565b610e5060048036036020811015610e4057600080fd5b50356001600160a01b0316612a20565b60408051602080825283518183015283519192839290830191858101910280838360005b83811015610e8c578181015183820152602001610e74565b505050509050019250505060405180910390f35b610455612aa9565b610e50612ab9565b61059660048036036040811015610ec657600080fd5b506001600160a01b0381358116916020013516612b1b565b6105f2612b38565b61059660048036036080811015610efc57600080fd5b506001600160a01b03813581169160208101358216916040820135169060600135612b47565b610e5060048036036020811015610f3857600080fd5b810190602081018135600160201b811115610f5257600080fd5b820183602082011115610f6457600080fd5b803590602001918460208302840111600160201b83111715610f8557600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550612bdb945050505050565b610ff960048036036060811015610fd957600080fd5b506001600160a01b03813581169160208101359091169060400135612c72565b6040805192835260208301919091528051918290030190f35b6105966004803603604081101561102857600080fd5b506001600160a01b0381358116916020013516612ee7565b6105966004803603602081101561105657600080fd5b50356001600160a01b0316612f04565b6105486004803603602081101561107c57600080fd5b810190602081018135600160201b81111561109657600080fd5b8201836020820111156110a857600080fd5b803590602001918460208302840111600160201b831117156110c957600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550612f16945050505050565b610596600480360360a081101561111d57600080fd5b506001600160a01b0381358116916020810135821691604082013581169160608101359091169060800135612fa8565b6105966004803603602081101561116357600080fd5b5035613160565b6105966004803603606081101561118057600080fd5b506001600160a01b038135811691602081013590911690604001356131c9565b6105f2600480360360408110156111b657600080fd5b506001600160a01b038135169060200135613603565b6105f2613638565b610596600480360360408110156111ea57600080fd5b506001600160a01b038135169060200135613647565b6104556137f7565b610596613807565b6105486004803603602081101561122657600080fd5b50356001600160a01b031661380d565b6105966004803603606081101561124c57600080fd5b506001600160a01b03813581169160208101359091169060400135613871565b6105966004803603602081101561128257600080fd5b50356001600160a01b03166138ae565b6105f2613bc1565b600181565b6001600160a01b03821660009081526009602052604081205460ff166112f65760405162461bcd60e51b8152600401808060200182810382526028815260200180615e196028913960400191505060405180910390fd5b600a546001600160a01b031633148061131957506000546001600160a01b031633145b6113545760405162461bcd60e51b8152600401808060200182810382526027815260200180615e726027913960400191505060405180910390fd5b6000546001600160a01b031633148061136f57506001821515145b6113b9576040805162461bcd60e51b81526020600482015260166024820152756f6e6c792061646d696e2063616e20756e706175736560501b604482015290519081900360640190fd5b6001600160a01b0383166000818152600c6020908152604091829020805486151560ff199091168117909155825193845283830152606090830181905260069083015265426f72726f7760d01b6080830152517f71aec636243f9709bb0007ae15e9afb8150ab01716d75fd7573be5cc096e03b09181900360a00190a150805b92915050565b60408051600180825281830190925260609160208083019080388339019050509050828160008151811061146f57fe5b60200260200101906001600160a01b031690816001600160a01b03168152505061149c8183600180612405565b505050565b806001600160a01b031663f851a4406040518163ffffffff1660e01b815260040160206040518083038186803b1580156114da57600080fd5b505afa1580156114ee573d6000803e3d6000fd5b505050506040513d602081101561150457600080fd5b50516001600160a01b0316331461154c5760405162461bcd60e51b8152600401808060200182810382526027815260200180615f396027913960400191505060405180910390fd5b806001600160a01b031663c1e803346040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561158757600080fd5b505af115801561159b573d6000803e3d6000fd5b505050506040513d60208110156115b157600080fd5b5051156115fd576040805162461bcd60e51b815260206004820152601560248201527418da185b99d9481b9bdd08185d5d1a1bdc9a5e9959605a1b604482015290519081900360640190fd5b50565b600f6020526000908152604090205481565b5050505050565b6015546001600160a01b031681565b6001600160a01b03841660009081526009602052604081205460ff16611650575060096116e9565b611658615d59565b6040518060200160405280876001600160a01b031663aa5af0fd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561169c57600080fd5b505afa1580156116b0573d6000803e3d6000fd5b505050506040513d60208110156116c657600080fd5b5051905290506116d68682613bd0565b6116e38685836000613e58565b60009150505b949350505050565b600a546001600160a01b031681565b6001546001600160a01b031681565b600a546000906001600160a01b031633148061173557506000546001600160a01b031633145b6117705760405162461bcd60e51b8152600401808060200182810382526027815260200180615e726027913960400191505060405180910390fd5b6000546001600160a01b031633148061178b57506001821515145b6117d5576040805162461bcd60e51b81526020600482015260166024820152756f6e6c792061646d696e2063616e20756e706175736560501b604482015290519081900360640190fd5b600a8054831515600160b81b810260ff60b81b1990921691909117909155604080516020810192909252808252600582820152645365697a6560d81b6060830152517fef159d9a32b2472e32b098f954f3ce62d232939f1c207070b584df1814de2de09181900360800190a150805b919050565b600080546001600160a01b0316331461186f5761186860016004614042565b9050611844565b611877615d59565b50604080516020810190915282815261188e615d59565b50604080516020810190915266b1a2bc2ec5000081526118ae82826140a8565b156118c7576118be600580614042565b92505050611844565b6118cf615d59565b506040805160208101909152670c7d713b49da000081526118f081846140b0565b1561190a57611900600580614042565b9350505050611844565b6005805490869055604080518281526020810188905281517f3b9670cf975d26958e754b57098eaa2ac914d8d2a31b83257997b9f346110fd9929181900390910190a160005b9695505050505050565b6000546001600160a01b031633146119a35760405162461bcd60e51b8152600401808060200182810382526026815260200180615e996026913960400191505060405180910390fd5b601580546001600160a01b038381166001600160a01b0319831681179093556040805191909216808252602082019390935281517feda98690e518e9a05f8ec6837663e188211b2da8f4906648b323f2c1d4434e29929181900390910190a15050565b6000546001600160a01b03163314611a65576040805162461bcd60e51b815260206004820152601f60248201527f6f6e6c792061646d696e2063616e2064726f7020636f6d70206d61726b657400604482015290519081900360640190fd5b6001600160a01b0381166000908152600960205260409020600381015460ff161515600114611adb576040805162461bcd60e51b815260206004820152601b60248201527f6d61726b6574206973206e6f74206120636f6d70206d61726b65740000000000604482015290519081900360640190fd5b60038101805460ff19169055604080516001600160a01b03841681526000602082015281517f93c1f3e36ed71139f466a4ce8c9751790e2e33f5afb2df0dcfb3aeabe55d5aa2929181900390910190a1611b336140b7565b5050565b6001600160a01b03821660009081526009602052604081205460ff16611b8e5760405162461bcd60e51b8152600401808060200182810382526028815260200180615e196028913960400191505060405180910390fd5b600a546001600160a01b0316331480611bb157506000546001600160a01b031633145b611bec5760405162461bcd60e51b8152600401808060200182810382526027815260200180615e726027913960400191505060405180910390fd5b6000546001600160a01b0316331480611c0757506001821515145b611c51576040805162461bcd60e51b81526020600482015260166024820152756f6e6c792061646d696e2063616e20756e706175736560501b604482015290519081900360640190fd5b6001600160a01b0383166000818152600b6020908152604091829020805486151560ff199091168117909155825193845283830152606090830181905260049083015263135a5b9d60e21b6080830152517f71aec636243f9709bb0007ae15e9afb8150ab01716d75fd7573be5cc096e03b09181900360a00190a150919050565b600a54600160a01b900460ff1681565b50505050565b435b90565b505050505050565b60166020526000908152604090205481565b60065481565b333214611d4b5760405162461bcd60e51b8152600401808060200182810382526031815260200180615e416031913960400191505060405180910390fd5b611d536140b7565b565b600080600080600080611d6a8a8a8a8a61447c565b925092509250826011811115611d7c57fe5b95509093509150505b9450945094915050565b6001600160a01b0383166000908152600b602052604081205460ff1615611dee576040805162461bcd60e51b815260206004820152600e60248201526d1b5a5b9d081a5cc81c185d5cd95960921b604482015290519081900360640190fd5b6001600160a01b03841660009081526009602052604090205460ff16611e185760095b9050611e33565b611e2184614897565b611e2d84846000614b15565b60005b90505b9392505050565b600080546001600160a01b03163314611e59576118686001600b614042565b611e61615d59565b506040805160208101909152828152611e78615d59565b506040805160208101909152670de0b6b3a76400008152611e9982826140b0565b15611eaa576118be6007600c614042565b611eb2615d59565b5060408051602081019091526714d1120d7b1600008152611ed381846140b0565b15611ee4576119006007600c614042565b6006805490869055604080518281526020810188905281517faeba5a6c40a8ac138134bff1aaa65debf25971188a58804bad717f82f0ec1316929181900390910190a16000611950565b80158015611f3c5750600082115b15611ce2576040805162461bcd60e51b815260206004820152601160248201527072656465656d546f6b656e73207a65726f60781b604482015290519081900360640190fd5b600d8181548110611f8f57fe5b6000918252602090912001546001600160a01b0316905081565b600080546001600160a01b03163314611fc85761186860016010614042565b600480546001600160a01b038481166001600160a01b0319831681179093556040805191909216808252602082019390935281517fd52b2b9b7e9ee655fcb95d2e5b9e0c9f69e7ef2b8e9d2d0ea78402d576d22e22929181900390910190a160009392505050565b61149c565b60008060008060008061204c87600080600061447c565b92509250925082601181111561205e57fe5b97919650945092505050565b600080546001600160a01b031633146120895761186860016013614042565b600a80546001600160a01b038481166001600160a01b0319831617928390556040805192821680845293909116602083015280517f0613b6ee6a04f0d09f390e4d9318894b9f6ac7fd83897cd8d18896ba579c401e9281900390910190a16000611e33565b6001600160a01b03851660009081526009602052604081205460ff16158061212f57506001600160a01b03851660009081526009602052604090205460ff16155b1561213e5760095b905061226c565b60008061214a85614d0d565b9193509091506000905082601181111561216057fe5b1461217a5781601181111561217157fe5b9250505061226c565b80612186576003612171565b6000886001600160a01b03166395dd9193876040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b1580156121de57600080fd5b505afa1580156121f2573d6000803e3d6000fd5b505050506040513d602081101561220857600080fd5b505160408051602081019091526005548152909150600090819061222c9084614d2d565b9092509050600082600381111561223f57fe5b1461225357600b5b9550505050505061226c565b80871115612262576011612247565b6000955050505050505b95945050505050565b6000546001600160a01b031633148061229857506015546001600160a01b031633145b6122d35760405162461bcd60e51b8152600401808060200182810382526035815260200180615ebf6035913960400191505060405180910390fd5b828181158015906122e357508082145b612324576040805162461bcd60e51b815260206004820152600d60248201526c1a5b9d985b1a59081a5b9c1d5d609a1b604482015290519081900360640190fd5b60005b828110156123fc5784848281811061233b57fe5b905060200201356016600089898581811061235257fe5b905060200201356001600160a01b03166001600160a01b03166001600160a01b031681526020019081526020016000208190555086868281811061239257fe5b905060200201356001600160a01b03166001600160a01b03167f6f1951b2aad10f3fc81b86d91105b413a5b3f847a34bbc5ce1904201b14438f68686848181106123d857fe5b905060200201356040518082815260200191505060405180910390a2600101612327565b50505050505050565b60005b835181101561161257600084828151811061241f57fe5b6020908102919091018101516001600160a01b0381166000908152600990925260409091205490915060ff16612494576040805162461bcd60e51b81526020600482015260156024820152741b585c9ad95d081b5d5cdd081899481b1a5cdd1959605a1b604482015290519081900360640190fd5b6001841515141561255c576124a7615d59565b6040518060200160405280836001600160a01b031663aa5af0fd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156124eb57600080fd5b505afa1580156124ff573d6000803e3d6000fd5b505050506040513d602081101561251557600080fd5b5051905290506125258282613bd0565b60005b8751811015612559576125518389838151811061254157fe5b6020026020010151846001613e58565b600101612528565b50505b600183151514156125a55761257081614897565b60005b86518110156125a35761259b8288838151811061258c57fe5b60200260200101516001614b15565b600101612573565b505b50600101612408565b6125b6614d81565b612607576040805162461bcd60e51b815260206004820152601f60248201527f6f6e6c792061646d696e2063616e206368616e676520636f6d70207261746500604482015290519081900360640190fd5b600e805490829055604080518281526020810184905281517fc227c9272633c3a307d9845bf2bc2509cefb20d655b5f3c1002d8e1e3f22c8b0929181900390910190a1611b336140b7565b6010602052600090815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b600c6020526000908152604090205460ff1681565b600b6020526000908152604090205460ff1681565b66038d7ea4c6800081565b6004546001600160a01b031681565b600a54600160b01b900460ff1681565b6011602052600090815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b60096020526000908152604090208054600182015460039092015460ff91821692911683565b600a546000906001600160a01b031633148061274657506000546001600160a01b031633145b6127815760405162461bcd60e51b8152600401808060200182810382526027815260200180615e726027913960400191505060405180910390fd5b6000546001600160a01b031633148061279c57506001821515145b6127e6576040805162461bcd60e51b81526020600482015260166024820152756f6e6c792061646d696e2063616e20756e706175736560501b604482015290519081900360640190fd5b600a8054831515600160b01b810260ff60b01b1990921691909117909155604080516020810192909252808252600882820152672a3930b739b332b960c11b6060830152517fef159d9a32b2472e32b098f954f3ce62d232939f1c207070b584df1814de2de09181900360800190a15090565b6001600160a01b038082166000908152600960209081526040808320938616835260029093019052205460ff1692915050565b60075481565b73c00e94cb662c3520282e6f5717214004a7f2688890565b600080546001600160a01b031633146128c95761186860016012614042565b6001600160a01b03821660009081526009602052604090205460ff16156128f657611868600a6011614042565b816001600160a01b031663fe9c44ae6040518163ffffffff1660e01b815260040160206040518083038186803b15801561292f57600080fd5b505afa158015612943573d6000803e3d6000fd5b505050506040513d602081101561295957600080fd5b5050604080516060810182526001808252600060208381018281528486018381526001600160a01b03891684526009909252949091209251835490151560ff199182161784559351918301919091555160039091018054911515919092161790556129c382614daa565b604080516001600160a01b038416815290517fcf583bb0c569eb967f806b11601c4cb93c10310485c67add5f8362c2f212321f9181900360200190a1600092915050565b6ec097ce7bc90715b34b9f100000000081565b600e5481565b60608060086000846001600160a01b03166001600160a01b03168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015612a9c57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612a7e575b5093979650505050505050565b600a54600160b81b900460ff1681565b6060600d805480602002602001604051908101604052809291908181526020018280548015612b1157602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612af3575b5050505050905090565b601260209081526000928352604080842090915290825290205481565b6002546001600160a01b031681565b600a54600090600160b01b900460ff1615612b9e576040805162461bcd60e51b81526020600482015260126024820152711d1c985b9cd9995c881a5cc81c185d5cd95960721b604482015290519081900360640190fd5b6000612bab868685614e88565b90508015612bba5790506116e9565b612bc386614897565b612bcf86866000614b15565b6116e386856000614b15565b6060600082519050606081604051908082528060200260200182016040528015612c0f578160200160208202803883390190505b50905060005b82811015612c6a576000858281518110612c2b57fe5b60200260200101519050612c3f8133614f34565b6011811115612c4a57fe5b838381518110612c5657fe5b602090810291909101015250600101612c15565b509392505050565b600480546040805163fc57d4df60e01b81526001600160a01b038781169482019490945290516000938493849391169163fc57d4df91602480820192602092909190829003018186803b158015612cc857600080fd5b505afa158015612cdc573d6000803e3d6000fd5b505050506040513d6020811015612cf257600080fd5b5051600480546040805163fc57d4df60e01b81526001600160a01b038a8116948201949094529051939450600093929091169163fc57d4df91602480820192602092909190829003018186803b158015612d4b57600080fd5b505afa158015612d5f573d6000803e3d6000fd5b505050506040513d6020811015612d7557600080fd5b50519050811580612d84575080155b15612d9957600d935060009250612edf915050565b6000866001600160a01b031663182df0f56040518163ffffffff1660e01b815260040160206040518083038186803b158015612dd457600080fd5b505afa158015612de8573d6000803e3d6000fd5b505050506040513d6020811015612dfe57600080fd5b505190506000612e0c615d59565b612e14615d59565b612e1c615d59565b6000612e2a60065489615055565b945090506000816003811115612e3c57fe5b14612e5857600b5b995060009850612edf975050505050505050565b612e628787615055565b935090506000816003811115612e7457fe5b14612e8057600b612e44565b612e8a8484615090565b925090506000816003811115612e9c57fe5b14612ea857600b612e44565b612eb2828c614d2d565b955090506000816003811115612ec457fe5b14612ed057600b612e44565b60009950939750505050505050505b935093915050565b601360209081526000928352604080842090915290825290205481565b60146020526000908152604090205481565b612f1e614d81565b612f6f576040805162461bcd60e51b815260206004820152601e60248201527f6f6e6c792061646d696e2063616e2061646420636f6d70206d61726b65740000604482015290519081900360640190fd5b60005b8151811015612f9f57612f97828281518110612f8a57fe5b60200260200101516150a8565b600101612f72565b506115fd6140b7565b600a54600090600160b81b900460ff1615612ffc576040805162461bcd60e51b815260206004820152600f60248201526e1cd95a5e99481a5cc81c185d5cd959608a1b604482015290519081900360640190fd5b6001600160a01b03861660009081526009602052604090205460ff16158061303d57506001600160a01b03851660009081526009602052604090205460ff16155b15613049576009612137565b846001600160a01b0316635fe3b5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561308257600080fd5b505afa158015613096573d6000803e3d6000fd5b505050506040513d60208110156130ac57600080fd5b505160408051635fe3b56760e01b815290516001600160a01b0392831692891691635fe3b567916004808301926020929190829003018186803b1580156130f257600080fd5b505afa158015613106573d6000803e3d6000fd5b505050506040513d602081101561311c57600080fd5b50516001600160a01b031614613133576002612137565b61313c86614897565b61314886846000614b15565b61315486856000614b15565b60009695505050505050565b600080546001600160a01b0316331461317f576118686001600d614042565b6007805490839055604080518281526020810185905281517f7093cf1eb653f749c3ff531d6df7f92764536a7fa0d13530cd26e070780c32ea929181900390910190a16000611e33565b6001600160a01b0383166000908152600c602052604081205460ff161561322a576040805162461bcd60e51b815260206004820152601060248201526f189bdc9c9bddc81a5cc81c185d5cd95960821b604482015290519081900360640190fd5b6001600160a01b03841660009081526009602052604090205460ff16613251576009611e11565b6001600160a01b038085166000908152600960209081526040808320938716835260029093019052205460ff1661334157336001600160a01b038516146132d7576040805162461bcd60e51b815260206004820152601560248201527439b2b73232b91036bab9ba1031329031aa37b5b2b760591b604482015290519081900360640190fd5b60006132e33385614f34565b905060008160118111156132f357fe5b1461330c5780601181111561330457fe5b915050611e33565b6001600160a01b038086166000908152600960209081526040808320938816835260029093019052205460ff1661333f57fe5b505b600480546040805163fc57d4df60e01b81526001600160a01b03888116948201949094529051929091169163fc57d4df91602480820192602092909190829003018186803b15801561339257600080fd5b505afa1580156133a6573d6000803e3d6000fd5b505050506040513d60208110156133bc57600080fd5b50516133c957600d611e11565b6001600160a01b0384166000908152601660205260409020548015613514576000856001600160a01b03166347bd37186040518163ffffffff1660e01b815260040160206040518083038186803b15801561342357600080fd5b505afa158015613437573d6000803e3d6000fd5b505050506040513d602081101561344d57600080fd5b5051905060008061345e83876153c3565b9092509050600082600381111561347157fe5b146134bc576040805162461bcd60e51b8152602060048201526016602482015275746f74616c20626f72726f7773206f766572666c6f7760501b604482015290519081900360640190fd5b838110613510576040805162461bcd60e51b815260206004820152601960248201527f6d61726b657420626f72726f7720636170207265616368656400000000000000604482015290519081900360640190fd5b5050505b600080613524868860008861447c565b9193509091506000905082601181111561353a57fe5b146135555781601181111561354b57fe5b9350505050611e33565b801561356257600461354b565b61356a615d59565b6040518060200160405280896001600160a01b031663aa5af0fd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156135ae57600080fd5b505afa1580156135c2573d6000803e3d6000fd5b505050506040513d60208110156135d857600080fd5b5051905290506135e88882613bd0565b6135f58888836000613e58565b600098975050505050505050565b6008602052816000526040600020818154811061361c57fe5b6000918252602090912001546001600160a01b03169150829050565b6003546001600160a01b031681565b600080546001600160a01b0316331461366d5761366660016006614042565b9050611439565b6001600160a01b0383166000908152600960205260409020805460ff166136a25761369a60096007614042565b915050611439565b6136aa615d59565b5060408051602081019091528381526136c1615d59565b506040805160208101909152670c7d713b49da000081526136e281836140b0565b156136fd576136f360066008614042565b9350505050611439565b84158015906137865750600480546040805163fc57d4df60e01b81526001600160a01b038a8116948201949094529051929091169163fc57d4df91602480820192602092909190829003018186803b15801561375857600080fd5b505afa15801561376c573d6000803e3d6000fd5b505050506040513d602081101561378257600080fd5b5051155b15613797576136f3600d6009614042565b60018301805490869055604080516001600160a01b03891681526020810183905280820188905290517f70483e6592cd5182d45ac970e05bc62cdcc90e9d8ef2c2dbe686cf383bcd7fc59181900360600190a16000979650505050505050565b600a54600160a81b900460ff1681565b60055481565b6115fd81600d80548060200260200160405190810160405280929190818152602001828054801561386757602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311613849575b505050505061143f565b60008061387f858585614e88565b9050801561388e579050611e33565b61389785614897565b6138a385856000614b15565b600095945050505050565b6000808290506000806000836001600160a01b031663c37f68e2336040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060806040518083038186803b15801561390f57600080fd5b505afa158015613923573d6000803e3d6000fd5b505050506040513d608081101561393957600080fd5b50805160208201516040909201519094509092509050821561398c5760405162461bcd60e51b8152600401808060200182810382526025815260200180615ef46025913960400191505060405180910390fd5b80156139a95761399e600c6002614042565b945050505050611844565b60006139b6873385614e88565b905080156139d7576139cb600e6003836153e9565b95505050505050611844565b6001600160a01b0385166000908152600960209081526040808320338452600281019092529091205460ff16613a165760009650505050505050611844565b3360009081526002820160209081526040808320805460ff191690556008825291829020805483518184028101840190945280845260609392830182828015613a8857602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311613a6a575b5050835193945083925060009150505b82811015613add57896001600160a01b0316848281518110613ab657fe5b60200260200101516001600160a01b03161415613ad557809150613add565b600101613a98565b50818110613ae757fe5b336000908152600860205260409020805481906000198101908110613b0857fe5b9060005260206000200160009054906101000a90046001600160a01b0316818381548110613b3257fe5b600091825260209091200180546001600160a01b0319166001600160a01b03929092169190911790558054613b6b826000198301615d6c565b50604080516001600160a01b038c16815233602082015281517fe699a64c18b07ac5b7301aa273f36a2287239eb9501d81950672794afba29a0d929181900390910190a160009c9b505050505050505050505050565b6000546001600160a01b031681565b6001600160a01b0382166000908152601160209081526040808320600f9092528220549091613bfd611ce8565b8354909150600090613c1d908390600160e01b900463ffffffff1661544f565b9050600081118015613c2f5750600083115b15613dfe576000613ca4876001600160a01b03166347bd37186040518163ffffffff1660e01b815260040160206040518083038186803b158015613c7257600080fd5b505afa158015613c86573d6000803e3d6000fd5b505050506040513d6020811015613c9c57600080fd5b505187615489565b90506000613cb283866154a7565b9050613cbc615d59565b60008311613cd95760405180602001604052806000815250613ce3565b613ce382846154e9565b9050613ced615d59565b604080516020810190915288546001600160e01b03168152613d0f9083615527565b90506040518060400160405280613d5f83600001516040518060400160405280601a81526020017f6e657720696e646578206578636565647320323234206269747300000000000081525061554c565b6001600160e01b03168152602001613d9a886040518060400160405280601c8152602001600080516020615f198339815191528152506155e6565b63ffffffff9081169091526001600160a01b038c166000908152601160209081526040909120835181549490920151909216600160e01b026001600160e01b039182166001600160e01b0319909416939093171691909117905550611ced92505050565b8015611ced57613e31826040518060400160405280601c8152602001600080516020615f198339815191528152506155e6565b845463ffffffff91909116600160e01b026001600160e01b03909116178455505050505050565b6001600160a01b0384166000908152601160205260409020613e78615d59565b50604080516020810190915281546001600160e01b03168152613e99615d59565b5060408051602080820183526001600160a01b03808a16600090815260138352848120918a16808252828452948120805485528651959091529152919091558051156123fc57613ee7615d59565b613ef1838361563b565b90506000613f80896001600160a01b03166395dd91938a6040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015613f4e57600080fd5b505afa158015613f62573d6000803e3d6000fd5b505050506040513d6020811015613f7857600080fd5b505188615489565b90506000613f8e8284615660565b6001600160a01b038a1660009081526014602052604081205491925090613fb5908361568f565b9050613fd68a828a613fce5766038d7ea4c68000613fd1565b60005b6156c5565b6001600160a01b03808c1660008181526014602090815260409182902094909455895181518781529485015280519193928f16927f1fc3ecc087d8d2d15e23d0032af5a47059c3892d003d8e139fdcb6bb327c99a6929081900390910190a35050505050505050505050565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa083601181111561407157fe5b83601381111561407d57fe5b604080519283526020830191909152600082820152519081900360600190a1826011811115611e3357fe5b519051111590565b5190511090565b6060600d80548060200260200160405190810160405280929190818152602001828054801561410f57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116140f1575b50939450600093505050505b81518110156141d557600082828151811061413257fe5b60200260200101519050614144615d59565b6040518060200160405280836001600160a01b031663aa5af0fd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561418857600080fd5b505afa15801561419c573d6000803e3d6000fd5b505050506040513d60208110156141b257600080fd5b5051905290506141c182614897565b6141cb8282613bd0565b505060010161411b565b506141de615d59565b6040518060200160405280600081525090506060825160405190808252806020026020018201604052801561422d57816020015b61421a615d59565b8152602001906001900390816142125790505b50905060005b83518110156143b357600084828151811061424a57fe5b6020908102919091018101516001600160a01b0381166000908152600990925260409091206003015490915060ff16156143aa57614286615d59565b60408051602080820180845260045463fc57d4df60e01b9091526001600160a01b03868116602485015293519293849391169163fc57d4df916044808601929190818703018186803b1580156142db57600080fd5b505afa1580156142ef573d6000803e3d6000fd5b505050506040513d602081101561430557600080fd5b505190529050614313615d59565b61438182846001600160a01b03166347bd37186040518163ffffffff1660e01b815260040160206040518083038186803b15801561435057600080fd5b505afa158015614364573d6000803e3d6000fd5b505050506040513d602081101561437a57600080fd5b505161580a565b90508085858151811061439057fe5b60200260200101819052506143a58682615527565b955050505b50600101614233565b5060005b8351811015611ce2576000600d82815481106143cf57fe5b600091825260208220015485516001600160a01b0390911692506143f457600061441c565b61441c600e5461441786868151811061440957fe5b60200260200101518861582b565b61585e565b6001600160a01b0383166000818152600f60209081526040918290208490558151848152915193945091927f2ab93f65628379309f36cb125e90d7c902454a545c4f8b8cb0794af75c24b807929181900390910190a250506001016143b7565b6000806000614489615d90565b6001600160a01b0388166000908152600860209081526040808320805482518185028101850190935280835284936060939291908301828280156144f657602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116144d8575b50939450600093505050505b815181101561485257600082828151811061451957fe5b60200260200101519050806001600160a01b031663c37f68e28e6040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060806040518083038186803b15801561457957600080fd5b505afa15801561458d573d6000803e3d6000fd5b505050506040513d60808110156145a357600080fd5b508051602082015160408084015160609485015160808c0152938a019390935291880191909152945084156145e95750600f975060009650869550611d85945050505050565b60408051602080820183526001600160a01b0380851660008181526009845285902060010154845260c08b01939093528351808301855260808b0151815260e08b015260048054855163fc57d4df60e01b815291820194909452935192169263fc57d4df9260248083019392829003018186803b15801561466957600080fd5b505afa15801561467d573d6000803e3d6000fd5b505050506040513d602081101561469357600080fd5b505160a087018190526146b75750600d975060009650869550611d85945050505050565b604080516020810190915260a08701518152610100870181905260c087015160e08801516146e492615877565b610120880152935060008460038111156146fa57fe5b146147165750600b975060009650869550611d85945050505050565b61472e866101200151876040015188600001516158cf565b87529350600084600381111561474057fe5b1461475c5750600b975060009650869550611d85945050505050565b614774866101000151876060015188602001516158cf565b60208801529350600084600381111561478957fe5b146147a55750600b975060009650869550611d85945050505050565b8b6001600160a01b0316816001600160a01b03161415614849576147d38661012001518c88602001516158cf565b6020880152935060008460038111156147e857fe5b146148045750600b975060009650869550611d85945050505050565b6148188661010001518b88602001516158cf565b60208801529350600084600381111561482d57fe5b146148495750600b975060009650869550611d85945050505050565b50600101614502565b50602084015184511115614879575050506020810151905160009450039150829050611d85565b5050815160209092015160009550859450919091039150611d859050565b6001600160a01b0381166000908152601060209081526040808320600f90925282205490916148c4611ce8565b83549091506000906148e4908390600160e01b900463ffffffff1661544f565b90506000811180156148f65750600083115b15614abc576000856001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561493657600080fd5b505afa15801561494a573d6000803e3d6000fd5b505050506040513d602081101561496057600080fd5b50519050600061497083866154a7565b905061497a615d59565b6000831161499757604051806020016040528060008152506149a1565b6149a182846154e9565b90506149ab615d59565b604080516020810190915288546001600160e01b031681526149cd9083615527565b90506040518060400160405280614a1d83600001516040518060400160405280601a81526020017f6e657720696e646578206578636565647320323234206269747300000000000081525061554c565b6001600160e01b03168152602001614a58886040518060400160405280601c8152602001600080516020615f198339815191528152506155e6565b63ffffffff9081169091526001600160a01b038b166000908152601060209081526040909120835181549490920151909216600160e01b026001600160e01b039182166001600160e01b031990941693909317169190911790555061161292505050565b801561161257614aef826040518060400160405280601c8152602001600080516020615f198339815191528152506155e6565b845463ffffffff91909116600160e01b026001600160e01b039091161784555050505050565b6001600160a01b0383166000908152601060205260409020614b35615d59565b50604080516020810190915281546001600160e01b03168152614b56615d59565b5060408051602080820183526001600160a01b03808916600090815260128352848120918916808252828452948120805485528651959091529152919091558051158015614ba45750815115155b15614bbc576ec097ce7bc90715b34b9f100000000081525b614bc4615d59565b614bce838361563b565b90506000876001600160a01b03166370a08231886040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015614c2857600080fd5b505afa158015614c3c573d6000803e3d6000fd5b505050506040513d6020811015614c5257600080fd5b505190506000614c628284615660565b6001600160a01b03891660009081526014602052604081205491925090614c89908361568f565b9050614ca289828a613fce5766038d7ea4c68000613fd1565b6001600160a01b03808b1660008181526014602090815260409182902094909455895181518781529485015280519193928e16927f2caecd17d02f56fa897705dcc740da2d237c373f70686f4e0d9bd3bf0400ea7a929081900390910190a350505050505050505050565b6000806000614d2084600080600061447c565b9250925092509193909250565b6000806000614d3a615d59565b614d44868661591c565b90925090506000826003811115614d5757fe5b14614d685750915060009050614d7a565b6000614d7382615984565b9350935050505b9250929050565b600080546001600160a01b0316331480614da557506002546001600160a01b031633145b905090565b60005b600d54811015614e3557816001600160a01b0316600d8281548110614dce57fe5b6000918252602090912001546001600160a01b03161415614e2d576040805162461bcd60e51b81526020600482015260146024820152731b585c9ad95d08185b1c9958591e48185919195960621b604482015290519081900360640190fd5b600101614dad565b50600d80546001810182556000919091527fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb50180546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b03831660009081526009602052604081205460ff16614eaf576009611e11565b6001600160a01b038085166000908152600960209081526040808320938716835260029093019052205460ff16614ee7576000611e11565b600080614ef7858786600061447c565b91935090915060009050826011811115614f0d57fe5b14614f2757816011811115614f1e57fe5b92505050611e33565b8015613154576004614f1e565b6001600160a01b0382166000908152600960205260408120805460ff16614f5f576009915050611439565b6001600160a01b038316600090815260028201602052604090205460ff16151560011415614f91576000915050611439565b6007546001600160a01b03841660009081526008602052604090205410614fbc576010915050611439565b6001600160a01b0380841660008181526002840160209081526040808320805460ff19166001908117909155600883528184208054918201815584529282902090920180549489166001600160a01b031990951685179055815193845283019190915280517f3ab23ab0d51cccc0c3085aec51f99228625aa1a922b3a8ca89a26b0f2027a1a59281900390910190a15060009392505050565b600061505f615d59565b615085604051806020016040528086815250604051806020016040528086815250615993565b915091509250929050565b600061509a615d59565b835183516150859190615a7c565b6001600160a01b0381166000908152600960205260409020805460ff16151560011461511b576040805162461bcd60e51b815260206004820152601960248201527f636f6d70206d61726b6574206973206e6f74206c697374656400000000000000604482015290519081900360640190fd5b600381015460ff1615615175576040805162461bcd60e51b815260206004820152601960248201527f636f6d70206d61726b657420616c726561647920616464656400000000000000604482015290519081900360640190fd5b60038101805460ff19166001908117909155604080516001600160a01b0385168152602081019290925280517f93c1f3e36ed71139f466a4ce8c9751790e2e33f5afb2df0dcfb3aeabe55d5aa29281900390910190a16001600160a01b0382166000908152601060205260409020546001600160e01b031615801561521d57506001600160a01b038216600090815260106020526040902054600160e01b900463ffffffff16155b156152da5760405180604001604052806ec097ce7bc90715b34b9f10000000006001600160e01b0316815260200161527f615256611ce8565b6040518060400160405280601c8152602001600080516020615f198339815191528152506155e6565b63ffffffff9081169091526001600160a01b0384166000908152601060209081526040909120835181549490920151909216600160e01b026001600160e01b039182166001600160e01b031990941693909317169190911790555b6001600160a01b0382166000908152601160205260409020546001600160e01b031615801561532c57506001600160a01b038216600090815260116020526040902054600160e01b900463ffffffff16155b15611b335760405180604001604052806ec097ce7bc90715b34b9f10000000006001600160e01b03168152602001615365615256611ce8565b63ffffffff9081169091526001600160a01b0384166000908152601160209081526040909120835181549490920151909216600160e01b026001600160e01b039182166001600160e01b031990941693909317169190911790555050565b6000808383018481106153db57600092509050614d7a565b506002915060009050614d7a565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa084601181111561541857fe5b84601381111561542457fe5b604080519283526020830191909152818101859052519081900360600190a1836011811115611e3057fe5b6000611e338383604051806040016040528060158152602001747375627472616374696f6e20756e646572666c6f7760581b815250615b2c565b6000611e336154a084670de0b6b3a76400006154a7565b8351615b86565b6000611e3383836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f77000000000000000000815250615bb9565b6154f1615d59565b604051806020016040528061551e615518866ec097ce7bc90715b34b9f10000000006154a7565b85615b86565b90529392505050565b61552f615d59565b604051806020016040528061551e8560000151856000015161568f565b600081600160e01b84106155de5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156155a357818101518382015260200161558b565b50505050905090810190601f1680156155d05780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b509192915050565b600081600160201b84106155de5760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156155a357818101518382015260200161558b565b615643615d59565b604051806020016040528061551e8560000151856000015161544f565b60006ec097ce7bc90715b34b9f10000000006156808484600001516154a7565b8161568757fe5b049392505050565b6000611e338383604051806040016040528060118152602001706164646974696f6e206f766572666c6f7760781b815250615c38565b60008183101580156156d75750600083115b156158025760006156e6612892565b604080516370a0823160e01b815230600482015290519192506000916001600160a01b038416916370a08231916024808301926020929190829003018186803b15801561573257600080fd5b505afa158015615746573d6000803e3d6000fd5b505050506040513d602081101561575c57600080fd5b505190508085116157ff57816001600160a01b031663a9059cbb87876040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b1580156157c757600080fd5b505af11580156157db573d6000803e3d6000fd5b505050506040513d60208110156157f157600080fd5b5060009350611e3392505050565b50505b509092915050565b615812615d59565b604051806020016040528061551e8560000151856154a7565b615833615d59565b604051806020016040528061551e6158578660000151670de0b6b3a76400006154a7565b8551615b86565b6000670de0b6b3a76400006156808484600001516154a7565b6000615881615d59565b600061588b615d59565b6158958787615993565b909250905060008260038111156158a857fe5b146158b7579092509050612edf565b6158c18186615993565b935093505050935093915050565b60008060006158dc615d59565b6158e6878761591c565b909250905060008260038111156158f957fe5b1461590a5750915060009050612edf565b6158c161591682615984565b866153c3565b6000615926615d59565b600080615937866000015186615c8d565b9092509050600082600381111561594a57fe5b1461596957506040805160208101909152600081529092509050614d7a565b60408051602081019091529081526000969095509350505050565b51670de0b6b3a7640000900490565b600061599d615d59565b6000806159b286600001518660000151615c8d565b909250905060008260038111156159c557fe5b146159e457506040805160208101909152600081529092509050614d7a565b6000806159f96706f05b59d3b20000846153c3565b90925090506000826003811115615a0c57fe5b14615a2e57506040805160208101909152600081529094509250614d7a915050565b600080615a4383670de0b6b3a7640000615ccc565b90925090506000826003811115615a5657fe5b14615a5d57fe5b604080516020810190915290815260009a909950975050505050505050565b6000615a86615d59565b600080615a9b86670de0b6b3a7640000615c8d565b90925090506000826003811115615aae57fe5b14615acd57506040805160208101909152600081529092509050614d7a565b600080615ada8388615ccc565b90925090506000826003811115615aed57fe5b14615b0f57506040805160208101909152600081529094509250614d7a915050565b604080516020810190915290815260009890975095505050505050565b60008184841115615b7e5760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156155a357818101518382015260200161558b565b505050900390565b6000611e3383836040518060400160405280600e81526020016d646976696465206279207a65726f60901b815250615cf7565b6000831580615bc6575082155b15615bd357506000611e33565b83830283858281615be057fe5b04148390615c2f5760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156155a357818101518382015260200161558b565b50949350505050565b60008383018285821015615c2f5760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156155a357818101518382015260200161558b565b60008083615ca057506000905080614d7a565b83830283858281615cad57fe5b0414615cc157506002915060009050614d7a565b600092509050614d7a565b60008082615ce05750600190506000614d7a565b6000838581615ceb57fe5b04915091509250929050565b60008183615d465760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156155a357818101518382015260200161558b565b50828481615d5057fe5b04949350505050565b6040518060200160405280600081525090565b81548183558181111561149c5760008381526020902061149c918101908301615dfa565b604051806101400160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001615dce615d59565b8152602001615ddb615d59565b8152602001615de8615d59565b8152602001615df5615d59565b905290565b611cea91905b80821115615e145760008155600101615e00565b509056fe63616e6e6f742070617573652061206d61726b65742074686174206973206e6f74206c69737465646f6e6c792065787465726e616c6c79206f776e6564206163636f756e7473206d61792072656672657368207370656564736f6e6c7920706175736520677561726469616e20616e642061646d696e2063616e2070617573656f6e6c792061646d696e2063616e2073657420626f72726f772063617020677561726469616e6f6e6c792061646d696e206f7220626f72726f772063617020677561726469616e2063616e2073657420626f72726f772063617073657869744d61726b65743a206765744163636f756e74536e617073686f74206661696c6564626c6f636b206e756d62657220657863656564732033322062697473000000006f6e6c7920756e6974726f6c6c65722061646d696e2063616e206368616e676520627261696e73a265627a7a723158202d8e045893807cf1ba82a1b1501c056c4cd7ec60fecf714bbd975e76c9098ab164736f6c63430005100032", + "metadata": "{\"compiler\":{\"version\":\"0.5.16+commit.9c3226ce\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"action\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"pauseState\",\"type\":\"bool\"}],\"name\":\"ActionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"action\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"pauseState\",\"type\":\"bool\"}],\"name\":\"ActionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSpeed\",\"type\":\"uint256\"}],\"name\":\"CompSpeedUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compBorrowIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedBorrowerComp\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"supplier\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compSupplyIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedSupplierComp\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isComped\",\"type\":\"bool\"}],\"name\":\"MarketComped\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketEntered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketExited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"MarketListed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newBorrowCap\",\"type\":\"uint256\"}],\"name\":\"NewBorrowCap\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldBorrowCapGuardian\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newBorrowCapGuardian\",\"type\":\"address\"}],\"name\":\"NewBorrowCapGuardian\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCloseFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCloseFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCollateralFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCollateralFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCompRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCompRate\",\"type\":\"uint256\"}],\"name\":\"NewCompRate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldLiquidationIncentiveMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"NewLiquidationIncentive\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMaxAssets\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMaxAssets\",\"type\":\"uint256\"}],\"name\":\"NewMaxAssets\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldPauseGuardian\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"NewPauseGuardian\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"oldPriceOracle\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"newPriceOracle\",\"type\":\"address\"}],\"name\":\"NewPriceOracle\",\"type\":\"event\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"_addCompMarkets\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract Unitroller\",\"name\":\"unitroller\",\"type\":\"address\"}],\"name\":\"_become\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"_dropCompMarket\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"newBorrowCapGuardian\",\"type\":\"address\"}],\"name\":\"_setBorrowCapGuardian\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setBorrowPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCloseFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCollateralFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"compRate_\",\"type\":\"uint256\"}],\"name\":\"_setCompRate\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"_setLiquidationIncentive\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"cTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"newBorrowCaps\",\"type\":\"uint256[]\"}],\"name\":\"_setMarketBorrowCaps\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newMaxAssets\",\"type\":\"uint256\"}],\"name\":\"_setMaxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setMintPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"_setPauseGuardian\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"newOracle\",\"type\":\"address\"}],\"name\":\"_setPriceOracle\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setSeizePaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setTransferPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"_supportMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allMarkets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"borrowCapGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"checkMembership\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"},{\"internalType\":\"contract CToken[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"holders\",\"type\":\"address[]\"},{\"internalType\":\"contract CToken[]\",\"name\":\"cTokens\",\"type\":\"address[]\"},{\"internalType\":\"bool\",\"name\":\"borrowers\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"suppliers\",\"type\":\"bool\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compAccrued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compBorrowState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compBorrowerIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compClaimThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compInitialIndex\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSupplierIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSupplyState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"enterMarkets\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenAddress\",\"type\":\"address\"}],\"name\":\"exitMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getAllMarkets\",\"outputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAssetsIn\",\"outputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getCompAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenModify\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"getHypotheticalAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"isComptroller\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateCalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"liquidationIncentiveMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"markets\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isComped\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"mintAmount\",\"type\":\"uint256\"}],\"name\":\"mintAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualMintAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"mintTokens\",\"type\":\"uint256\"}],\"name\":\"mintVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"refreshCompSpeeds\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"repayBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowerIndex\",\"type\":\"uint256\"}],\"name\":\"repayBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"seizeGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"transferGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Compound (modified by Arr00)\",\"methods\":{\"_addCompMarkets(address[])\":{\"params\":{\"cTokens\":\"The addresses of the markets to add\"}},\"_dropCompMarket(address)\":{\"params\":{\"cToken\":\"The address of the market to drop\"}},\"_setBorrowCapGuardian(address)\":{\"params\":{\"newBorrowCapGuardian\":\"The address of the new Borrow Cap Guardian\"}},\"_setCloseFactor(uint256)\":{\"details\":\"Admin function to set closeFactor\",\"params\":{\"newCloseFactorMantissa\":\"New close factor, scaled by 1e18\"},\"return\":\"uint 0=success, otherwise a failure. (See ErrorReporter for details)\"},\"_setCollateralFactor(address,uint256)\":{\"details\":\"Admin function to set per-market collateralFactor\",\"params\":{\"cToken\":\"The market to set the factor on\",\"newCollateralFactorMantissa\":\"The new collateral factor, scaled by 1e18\"},\"return\":\"uint 0=success, otherwise a failure. (See ErrorReporter for details)\"},\"_setCompRate(uint256)\":{\"params\":{\"compRate_\":\"The amount of COMP wei per block to distribute\"}},\"_setLiquidationIncentive(uint256)\":{\"details\":\"Admin function to set liquidationIncentive\",\"params\":{\"newLiquidationIncentiveMantissa\":\"New liquidationIncentive scaled by 1e18\"},\"return\":\"uint 0=success, otherwise a failure. (See ErrorReporter for details)\"},\"_setMarketBorrowCaps(address[],uint256[])\":{\"details\":\"Admin or borrowCapGuardian function to set the borrow caps. A borrow cap of 0 corresponds to unlimited borrowing.\",\"params\":{\"cTokens\":\"The addresses of the markets (tokens) to change the borrow caps for\",\"newBorrowCaps\":\"The new borrow cap values in underlying to be set. A value of 0 corresponds to unlimited borrowing.\"}},\"_setMaxAssets(uint256)\":{\"details\":\"Admin function to set maxAssets\",\"params\":{\"newMaxAssets\":\"New max assets\"},\"return\":\"uint 0=success, otherwise a failure. (See ErrorReporter for details)\"},\"_setPauseGuardian(address)\":{\"params\":{\"newPauseGuardian\":\"The address of the new Pause Guardian\"},\"return\":\"uint 0=success, otherwise a failure. (See enum Error for details)\"},\"_setPriceOracle(address)\":{\"details\":\"Admin function to set a new price oracle\",\"return\":\"uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\"},\"_supportMarket(address)\":{\"details\":\"Admin function to set isListed and add support for the market\",\"params\":{\"cToken\":\"The address of the market (token) to list\"},\"return\":\"uint 0=success, otherwise a failure. (See enum Error for details)\"},\"borrowAllowed(address,address,uint256)\":{\"params\":{\"borrowAmount\":\"The amount of underlying the account would borrow\",\"borrower\":\"The account which would borrow the asset\",\"cToken\":\"The market to verify the borrow against\"},\"return\":\"0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"borrowVerify(address,address,uint256)\":{\"params\":{\"borrowAmount\":\"The amount of the underlying asset requested to borrow\",\"borrower\":\"The address borrowing the underlying\",\"cToken\":\"Asset whose underlying is being borrowed\"}},\"checkMembership(address,address)\":{\"params\":{\"account\":\"The address of the account to check\",\"cToken\":\"The cToken to check\"},\"return\":\"True if the account is in the asset, otherwise false.\"},\"claimComp(address)\":{\"params\":{\"holder\":\"The address to claim COMP for\"}},\"claimComp(address,address[])\":{\"params\":{\"cTokens\":\"The list of markets to claim COMP in\",\"holder\":\"The address to claim COMP for\"}},\"claimComp(address[],address[],bool,bool)\":{\"params\":{\"borrowers\":\"Whether or not to claim COMP earned by borrowing\",\"cTokens\":\"The list of markets to claim COMP in\",\"holders\":\"The addresses to claim COMP for\",\"suppliers\":\"Whether or not to claim COMP earned by supplying\"}},\"enterMarkets(address[])\":{\"params\":{\"cTokens\":\"The list of addresses of the cToken markets to be enabled\"},\"return\":\"Success indicator for whether each corresponding market was entered\"},\"exitMarket(address)\":{\"details\":\"Sender must not have an outstanding borrow balance in the asset, or be providing necessary collateral for an outstanding borrow.\",\"params\":{\"cTokenAddress\":\"The address of the asset to be removed\"},\"return\":\"Whether or not the account successfully exited the market\"},\"getAccountLiquidity(address)\":{\"return\":\"(possible error code (semi-opaque), account liquidity in excess of collateral requirements, account shortfall below collateral requirements)\"},\"getAllMarkets()\":{\"details\":\"The automatic getter may be used to access an individual market.\",\"return\":\"The list of market addresses\"},\"getAssetsIn(address)\":{\"params\":{\"account\":\"The address of the account to pull assets for\"},\"return\":\"A dynamic list with the assets the account has entered\"},\"getCompAddress()\":{\"return\":\"The address of COMP\"},\"getHypotheticalAccountLiquidity(address,address,uint256,uint256)\":{\"params\":{\"account\":\"The account to determine liquidity for\",\"borrowAmount\":\"The amount of underlying to hypothetically borrow\",\"cTokenModify\":\"The market to hypothetically redeem/borrow in\",\"redeemTokens\":\"The number of tokens to hypothetically redeem\"},\"return\":\"(possible error code (semi-opaque), hypothetical account liquidity in excess of collateral requirements, hypothetical account shortfall below collateral requirements)\"},\"liquidateBorrowAllowed(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"repayAmount\":\"The amount of underlying being repaid\"}},\"liquidateBorrowVerify(address,address,address,address,uint256,uint256)\":{\"params\":{\"actualRepayAmount\":\"The amount of underlying being repaid\",\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\"}},\"liquidateCalculateSeizeTokens(address,address,uint256)\":{\"details\":\"Used in liquidation (called in cToken.liquidateBorrowFresh)\",\"params\":{\"actualRepayAmount\":\"The amount of cTokenBorrowed underlying to convert into cTokenCollateral tokens\",\"cTokenBorrowed\":\"The address of the borrowed cToken\",\"cTokenCollateral\":\"The address of the collateral cToken\"},\"return\":\"(errorCode, number of cTokenCollateral tokens to be seized in a liquidation)\"},\"mintAllowed(address,address,uint256)\":{\"params\":{\"cToken\":\"The market to verify the mint against\",\"mintAmount\":\"The amount of underlying being supplied to the market in exchange for tokens\",\"minter\":\"The account which would get the minted tokens\"},\"return\":\"0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"mintVerify(address,address,uint256,uint256)\":{\"params\":{\"actualMintAmount\":\"The amount of the underlying asset being minted\",\"cToken\":\"Asset being minted\",\"mintTokens\":\"The number of tokens being minted\",\"minter\":\"The address minting the tokens\"}},\"redeemAllowed(address,address,uint256)\":{\"params\":{\"cToken\":\"The market to verify the redeem against\",\"redeemTokens\":\"The number of cTokens to exchange for the underlying asset in the market\",\"redeemer\":\"The account which would redeem the tokens\"},\"return\":\"0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"redeemVerify(address,address,uint256,uint256)\":{\"params\":{\"cToken\":\"Asset being redeemed\",\"redeemAmount\":\"The amount of the underlying asset being redeemed\",\"redeemTokens\":\"The number of tokens being redeemed\",\"redeemer\":\"The address redeeming the tokens\"}},\"repayBorrowAllowed(address,address,address,uint256)\":{\"params\":{\"borrower\":\"The account which would borrowed the asset\",\"cToken\":\"The market to verify the repay against\",\"payer\":\"The account which would repay the asset\",\"repayAmount\":\"The amount of the underlying asset the account would repay\"},\"return\":\"0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"repayBorrowVerify(address,address,address,uint256,uint256)\":{\"params\":{\"actualRepayAmount\":\"The amount of underlying being repaid\",\"borrower\":\"The address of the borrower\",\"cToken\":\"Asset being repaid\",\"payer\":\"The address repaying the borrow\"}},\"seizeAllowed(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"seizeTokens\":\"The number of collateral tokens to seize\"}},\"seizeVerify(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"seizeTokens\":\"The number of collateral tokens to seize\"}},\"transferAllowed(address,address,address,uint256)\":{\"params\":{\"cToken\":\"The market to verify the transfer against\",\"dst\":\"The account which receives the tokens\",\"src\":\"The account which sources the tokens\",\"transferTokens\":\"The number of cTokens to transfer\"},\"return\":\"0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"transferVerify(address,address,address,uint256)\":{\"params\":{\"cToken\":\"Asset being transferred\",\"dst\":\"The account which receives the tokens\",\"src\":\"The account which sources the tokens\",\"transferTokens\":\"The number of cTokens to transfer\"}}},\"title\":\"Compound's Comptroller Contract\"},\"userdoc\":{\"methods\":{\"_addCompMarkets(address[])\":{\"notice\":\"Add markets to compMarkets, allowing them to earn COMP in the flywheel\"},\"_dropCompMarket(address)\":{\"notice\":\"Remove a market from compMarkets, preventing it from earning COMP in the flywheel\"},\"_setBorrowCapGuardian(address)\":{\"notice\":\"Admin function to change the Borrow Cap Guardian\"},\"_setCloseFactor(uint256)\":{\"notice\":\"Sets the closeFactor used when liquidating borrows\"},\"_setCollateralFactor(address,uint256)\":{\"notice\":\"Sets the collateralFactor for a market\"},\"_setCompRate(uint256)\":{\"notice\":\"Set the amount of COMP distributed per block\"},\"_setLiquidationIncentive(uint256)\":{\"notice\":\"Sets liquidationIncentive\"},\"_setMarketBorrowCaps(address[],uint256[])\":{\"notice\":\"Set the given borrow caps for the given cToken markets. Borrowing that brings total borrows to or above borrow cap will revert.\"},\"_setMaxAssets(uint256)\":{\"notice\":\"Sets maxAssets which controls how many markets can be entered\"},\"_setPauseGuardian(address)\":{\"notice\":\"Admin function to change the Pause Guardian\"},\"_setPriceOracle(address)\":{\"notice\":\"Sets a new price oracle for the comptroller\"},\"_supportMarket(address)\":{\"notice\":\"Add the market to the markets mapping and set it as listed\"},\"borrowAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to borrow the underlying asset of the given market\"},\"borrowVerify(address,address,uint256)\":{\"notice\":\"Validates borrow and reverts on rejection. May emit logs.\"},\"checkMembership(address,address)\":{\"notice\":\"Returns whether the given account is entered in the given asset\"},\"claimComp(address)\":{\"notice\":\"Claim all the comp accrued by holder in all markets\"},\"claimComp(address,address[])\":{\"notice\":\"Claim all the comp accrued by holder in the specified markets\"},\"claimComp(address[],address[],bool,bool)\":{\"notice\":\"Claim all comp accrued by the holders\"},\"enterMarkets(address[])\":{\"notice\":\"Add assets to be included in account liquidity calculation\"},\"exitMarket(address)\":{\"notice\":\"Removes asset from sender's account liquidity calculation\"},\"getAccountLiquidity(address)\":{\"notice\":\"Determine the current account liquidity wrt collateral requirements\"},\"getAllMarkets()\":{\"notice\":\"Return all of the markets\"},\"getAssetsIn(address)\":{\"notice\":\"Returns the assets an account has entered\"},\"getCompAddress()\":{\"notice\":\"Return the address of the COMP token\"},\"getHypotheticalAccountLiquidity(address,address,uint256,uint256)\":{\"notice\":\"Determine what the account liquidity would be if the given amounts were redeemed/borrowed\"},\"liquidateBorrowAllowed(address,address,address,address,uint256)\":{\"notice\":\"Checks if the liquidation should be allowed to occur\"},\"liquidateBorrowVerify(address,address,address,address,uint256,uint256)\":{\"notice\":\"Validates liquidateBorrow and reverts on rejection. May emit logs.\"},\"liquidateCalculateSeizeTokens(address,address,uint256)\":{\"notice\":\"Calculate number of tokens of collateral asset to seize given an underlying amount\"},\"mintAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to mint tokens in the given market\"},\"mintVerify(address,address,uint256,uint256)\":{\"notice\":\"Validates mint and reverts on rejection. May emit logs.\"},\"redeemAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to redeem tokens in the given market\"},\"redeemVerify(address,address,uint256,uint256)\":{\"notice\":\"Validates redeem and reverts on rejection. May emit logs.\"},\"refreshCompSpeeds()\":{\"notice\":\"Recalculate and update COMP speeds for all COMP markets\"},\"repayBorrowAllowed(address,address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to repay a borrow in the given market\"},\"repayBorrowVerify(address,address,address,uint256,uint256)\":{\"notice\":\"Validates repayBorrow and reverts on rejection. May emit logs.\"},\"seizeAllowed(address,address,address,address,uint256)\":{\"notice\":\"Checks if the seizing of assets should be allowed to occur\"},\"seizeVerify(address,address,address,address,uint256)\":{\"notice\":\"Validates seize and reverts on rejection. May emit logs.\"},\"transferAllowed(address,address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to transfer tokens in the given market\"},\"transferVerify(address,address,address,uint256)\":{\"notice\":\"Validates transfer and reverts on rejection. May emit logs.\"}}}},\"settings\":{\"compilationTarget\":{\"contracts/ComptrollerG5.sol\":\"ComptrollerG5\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/CToken.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./CTokenInterfaces.sol\\\";\\nimport \\\"./ErrorReporter.sol\\\";\\nimport \\\"./Exponential.sol\\\";\\nimport \\\"./EIP20Interface.sol\\\";\\nimport \\\"./InterestRateModel.sol\\\";\\n\\n/**\\n * @title Compound's CToken Contract\\n * @notice Abstract base for CTokens\\n * @author Compound\\n */\\ncontract CToken is CTokenInterface, Exponential, TokenErrorReporter {\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_) public {\\n require(msg.sender == admin, \\\"only admin may initialize the market\\\");\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = getBlockNumber();\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Transfer `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = uint(-1);\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srcTokensNew;\\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, srcTokensNew) = 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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srcTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != uint(-1)) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n // unused function\\n // comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transfer(address dst, uint256 amount) external nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferFrom(address src, address dst, uint256 amount) external nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (-1 means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool) {\\n address src = msg.sender;\\n transferAllowances[src][spender] = amount;\\n emit Approval(src, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (-1 means infinite)\\n */\\n function allowance(address owner, address spender) external view returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external returns (uint) {\\n Exp memory exchangeRate = Exp({mantissa: exchangeRateCurrent()});\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n require(mErr == MathError.NO_ERROR, \\\"balance could not be calculated\\\");\\n return balance;\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view returns (uint, uint, uint, uint) {\\n uint cTokenBalance = accountTokens[account];\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), cTokenBalance, borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @dev Function to simply retrieve block number\\n * This exists mainly for inheriting test contracts to stub this result.\\n */\\n function getBlockNumber() internal view returns (uint) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this cToken\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view returns (uint) {\\n return interestRateModel.getBorrowRate(getCashPrior(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this cToken\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view returns (uint) {\\n return interestRateModel.getSupplyRate(getCashPrior(), totalBorrows, totalReserves, reserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n require(err == MathError.NO_ERROR, \\\"borrowBalanceStored: borrowBalanceStoredInternal failed\\\");\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return (error code, the calculated balance or 0 if error code is non-zero)\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the CToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n require(err == MathError.NO_ERROR, \\\"exchangeRateStored: exchangeRateStoredInternal failed\\\");\\n return result;\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the CToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return (error code, calculated exchange rate scaled by 1e18)\\n */\\n function exchangeRateStoredInternal() internal view returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows - totalReserves) / totalSupply\\n */\\n uint totalCash = getCashPrior();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Get cash balance of this cToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage.\\n */\\n function accrueInterest() public returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = getBlockNumber();\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = getCashPrior();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n require(mathErr == MathError.NO_ERROR, \\\"could not calculate block delta\\\");\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({mantissa: borrowRateMantissa}), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(Exp({mantissa: reserveFactorMantissa}), interestAccumulated, reservesPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives cTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n struct MintLocalVars {\\n Error err;\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives cTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, 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's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the cToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of cTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.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 cTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED\\\");\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\\");\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender redeems cTokens in exchange for the underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemTokens The number of cTokens to redeem into underlying\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemInternal(uint redeemTokens) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(msg.sender, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems cTokens in exchange for a specified amount of underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemAmount The amount of underlying to receive from redeeming cTokens\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemUnderlyingInternal(uint redeemAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(msg.sender, 0, redeemAmount);\\n }\\n\\n struct RedeemLocalVars {\\n Error err;\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n /**\\n * @notice User redeems cTokens in exchange for the underlying asset\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param redeemTokensIn The number of cTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming cTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemFresh(address payable redeemer, uint redeemTokensIn, uint redeemAmountIn) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr));\\n }\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(Exp({mantissa: vars.exchangeRateMantissa}), redeemTokensIn);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(redeemAmountIn, Exp({mantissa: vars.exchangeRateMantissa}));\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REDEEM_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDEEM_FRESHNESS_CHECK);\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDEEM_TRANSFER_OUT_NOT_POSSIBLE);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We invoke doTransferOut for the redeemer and the redeemAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(redeemer, vars.redeemAmount);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n /* We call the defense hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender borrows assets from the protocol to their own address\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function borrowInternal(uint borrowAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(msg.sender, borrowAmount);\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n /**\\n * @notice Users borrow assets from the protocol to their own address\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function borrowFresh(address payable borrower, uint borrowAmount) internal returns (uint) {\\n /* Fail if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.BORROW_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.BORROW_FRESHNESS_CHECK);\\n }\\n\\n /* Fail gracefully if protocol has insufficient underlying cash */\\n if (getCashPrior() < borrowAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.BORROW_CASH_NOT_AVAILABLE);\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We invoke doTransferOut for the borrower and the borrowAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(borrower, borrowAmount);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to borrower\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer the account paying off the borrow\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount the amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED\\\");\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED\\\");\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this cToken to be liquidated\\n * @param cTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) 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 = cTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, cTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this cToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param cTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowFresh(address liquidator, address borrower, uint repayAmount, CTokenInterface cTokenCollateral) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(address(this), address(cTokenCollateral), liquidator, borrower, repayAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify cTokenCollateral market's block number equals current block number */\\n if (cTokenCollateral.accrualBlockNumber() != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = -1 */\\n if (repayAmount == uint(-1)) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & 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(cTokenCollateral), actualRepayAmount);\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(cTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(cTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = cTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(cTokenCollateral), seizeTokens);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.liquidateBorrowVerify(address(this), address(cTokenCollateral), liquidator, borrower, actualRepayAmount, seizeTokens);\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another cToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed cToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of cTokens to seize\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function seize(address liquidator, address borrower, uint seizeTokens) external nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n struct SeizeInternalLocalVars {\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n uint liquidatorSeizeTokens;\\n uint protocolSeizeTokens;\\n uint protocolSeizeAmount;\\n uint exchangeRateMantissa;\\n uint totalReservesNew;\\n uint totalSupplyNew;\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another CToken.\\n * Its absolutely critical to use msg.sender as the seizer cToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed cToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of cTokens to seize\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function seizeInternal(address seizerToken, address liquidator, address borrower, uint seizeTokens) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n SeizeInternalLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (vars.mathErr, vars.borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(vars.mathErr));\\n }\\n\\n vars.protocolSeizeTokens = mul_(seizeTokens, Exp({mantissa: protocolSeizeShareMantissa}));\\n vars.liquidatorSeizeTokens = sub_(seizeTokens, vars.protocolSeizeTokens);\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n require(vars.mathErr == MathError.NO_ERROR, \\\"exchange rate math error\\\");\\n\\n vars.protocolSeizeAmount = mul_ScalarTruncate(Exp({mantissa: vars.exchangeRateMantissa}), vars.protocolSeizeTokens);\\n\\n vars.totalReservesNew = add_(totalReserves, vars.protocolSeizeAmount);\\n vars.totalSupplyNew = sub_(totalSupply, vars.protocolSeizeTokens);\\n\\n (vars.mathErr, vars.liquidatorTokensNew) = addUInt(accountTokens[liquidator], vars.liquidatorSeizeTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(vars.mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n totalReserves = vars.totalReservesNew;\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[borrower] = vars.borrowerTokensNew;\\n accountTokens[liquidator] = vars.liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, vars.liquidatorSeizeTokens);\\n emit Transfer(borrower, address(this), vars.protocolSeizeTokens);\\n emit ReservesAdded(address(this), vars.protocolSeizeAmount, vars.totalReservesNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n\\n /*** Admin Functions ***/\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPendingAdmin(address payable newPendingAdmin) external returns (uint) {\\n // Check caller = admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\\n }\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptAdmin() external returns (uint) {\\n // Check caller is pendingAdmin and pendingAdmin \\u2260 address(0)\\n if (msg.sender != pendingAdmin || msg.sender == address(0)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = address(0);\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setComptroller(ComptrollerInterface newComptroller) public returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_COMPTROLLER_OWNER_CHECK);\\n }\\n\\n ComptrollerInterface oldComptroller = comptroller;\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(oldComptroller, newComptroller);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh\\n * @dev Admin function to accrue interest and set a new reserve factor\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setReserveFactor(uint newReserveFactorMantissa) external nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\\n * @dev Admin function to set a new reserve factor\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_RESERVE_FACTOR_ADMIN_CHECK);\\n }\\n\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring from msg.sender\\n * @param addAmount Amount of addition to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to admin\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _reduceReserves(uint reduceAmount) external nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to admin\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _reduceReservesFresh(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's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n totalReservesNew = totalReserves - reduceAmount;\\n // We checked reduceAmount <= totalReserves above, so this should never revert.\\n require(totalReservesNew <= 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't be sure if side effects occurred.\\n doTransferOut(admin, reduceAmount);\\n\\n emit ReservesReduced(admin, reduceAmount, totalReservesNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Admin function to accrue interest and update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel);\\n }\\n\\n /**\\n * @notice updates the interest rate model (*requires fresh interest accrual)\\n * @dev Admin function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal returns (uint) {\\n\\n // Used to store old model for use in the event that is emitted on success\\n InterestRateModel oldInterestRateModel;\\n\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_INTEREST_RATE_MODEL_OWNER_CHECK);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Track the market's current interest rate model\\n oldInterestRateModel = interestRateModel;\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view returns (uint);\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure tather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal;\\n\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n}\\n\",\"keccak256\":\"0x436ec2e309682995f8a82dfdd9e8f75928599c10a9a680dddbee6c275014008d\"},\"contracts/CTokenInterfaces.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./InterestRateModel.sol\\\";\\nimport \\\"./EIP20NonStandardInterface.sol\\\";\\n\\ncontract CTokenStorage {\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-cToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModel public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first CTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping (address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping (address => mapping (address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Share of seized collateral that is added to reserves\\n */\\n uint public constant protocolSeizeShareMantissa = 2.8e16; //2.8%\\n\\n}\\n\\ncontract CTokenInterface is CTokenStorage {\\n /**\\n * @notice Indicator that this is a CToken contract (for inspection)\\n */\\n bool public constant isCToken = true;\\n\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(address liquidator, address borrower, uint repayAmount, address cTokenCollateral, uint seizeTokens);\\n\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin is updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(InterestRateModel oldInterestRateModel, InterestRateModel newInterestRateModel);\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address admin, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Failure event\\n */\\n event Failure(uint error, uint info, uint detail);\\n\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external returns (bool);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function approve(address spender, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function balanceOfUnderlying(address owner) external returns (uint);\\n function getAccountSnapshot(address account) external view returns (uint, uint, uint, uint);\\n function borrowRatePerBlock() external view returns (uint);\\n function supplyRatePerBlock() external view returns (uint);\\n function totalBorrowsCurrent() external returns (uint);\\n function borrowBalanceCurrent(address account) external returns (uint);\\n function borrowBalanceStored(address account) public view returns (uint);\\n function exchangeRateCurrent() public returns (uint);\\n function exchangeRateStored() public view returns (uint);\\n function getCash() external view returns (uint);\\n function accrueInterest() public returns (uint);\\n function seize(address liquidator, address borrower, uint seizeTokens) external returns (uint);\\n\\n\\n /*** Admin Functions ***/\\n\\n function _setPendingAdmin(address payable newPendingAdmin) external returns (uint);\\n function _acceptAdmin() external returns (uint);\\n function _setComptroller(ComptrollerInterface newComptroller) public returns (uint);\\n function _setReserveFactor(uint newReserveFactorMantissa) external returns (uint);\\n function _reduceReserves(uint reduceAmount) external returns (uint);\\n function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint);\\n}\\n\\ncontract CErc20Storage {\\n /**\\n * @notice Underlying asset for this CToken\\n */\\n address public underlying;\\n}\\n\\ncontract CErc20Interface is CErc20Storage {\\n\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n function redeem(uint redeemTokens) external returns (uint);\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n function borrow(uint borrowAmount) external returns (uint);\\n function repayBorrow(uint repayAmount) external returns (uint);\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n function liquidateBorrow(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) external returns (uint);\\n function sweepToken(EIP20NonStandardInterface token) external;\\n\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ncontract CDelegationStorage {\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n}\\n\\ncontract CDelegatorInterface is CDelegationStorage {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(address implementation_, bool allowResign, bytes memory becomeImplementationData) public;\\n}\\n\\ncontract CDelegateInterface is CDelegationStorage {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) public;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() public;\\n}\\n\",\"keccak256\":\"0x963bbf60b4c0b76900b3fcb2db8c8be634934b37b4113f1055e57a308197d21a\"},\"contracts/CarefulMath.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Careful Math\\n * @author Compound\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c = a * b;\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n return (MathError.NO_ERROR, a - b);\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c = a + b;\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\",\"keccak256\":\"0x0647348f27e41d22555d99eebd217dee02a4d737df6accd7cce5347a7487c7de\"},\"contracts/ComptrollerG5.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.sol\\\";\\nimport \\\"./ErrorReporter.sol\\\";\\nimport \\\"./Exponential.sol\\\";\\nimport \\\"./PriceOracle.sol\\\";\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./ComptrollerStorage.sol\\\";\\nimport \\\"./Unitroller.sol\\\";\\nimport \\\"./Governance/Comp.sol\\\";\\n\\n/**\\n * @title Compound's Comptroller Contract\\n * @author Compound (modified by Arr00)\\n */\\ncontract ComptrollerG5 is ComptrollerV4Storage, ComptrollerInterface, ComptrollerErrorReporter, Exponential {\\n /// @notice Emitted when an admin supports a market\\n event MarketListed(CToken cToken);\\n\\n /// @notice Emitted when an account enters a market\\n event MarketEntered(CToken cToken, address account);\\n\\n /// @notice Emitted when an account exits a market\\n event MarketExited(CToken cToken, 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(CToken cToken, 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 maxAssets is changed by admin\\n event NewMaxAssets(uint oldMaxAssets, uint newMaxAssets);\\n\\n /// @notice Emitted when price oracle is changed\\n event NewPriceOracle(PriceOracle oldPriceOracle, PriceOracle newPriceOracle);\\n\\n /// @notice Emitted when pause guardian is changed\\n event NewPauseGuardian(address oldPauseGuardian, address newPauseGuardian);\\n\\n /// @notice Emitted when an action is paused globally\\n event ActionPaused(string action, bool pauseState);\\n\\n /// @notice Emitted when an action is paused on a market\\n event ActionPaused(CToken cToken, string action, bool pauseState);\\n\\n /// @notice Emitted when market comped status is changed\\n event MarketComped(CToken cToken, bool isComped);\\n\\n /// @notice Emitted when COMP rate is changed\\n event NewCompRate(uint oldCompRate, uint newCompRate);\\n\\n /// @notice Emitted when a new COMP speed is calculated for a market\\n event CompSpeedUpdated(CToken indexed cToken, uint newSpeed);\\n\\n /// @notice Emitted when COMP is distributed to a supplier\\n event DistributedSupplierComp(CToken indexed cToken, address indexed supplier, uint compDelta, uint compSupplyIndex);\\n\\n /// @notice Emitted when COMP is distributed to a borrower\\n event DistributedBorrowerComp(CToken indexed cToken, address indexed borrower, uint compDelta, uint compBorrowIndex);\\n\\n /// @notice Emitted when borrow cap for a cToken is changed\\n event NewBorrowCap(CToken indexed cToken, uint newBorrowCap);\\n\\n /// @notice Emitted when borrow cap guardian is changed\\n event NewBorrowCapGuardian(address oldBorrowCapGuardian, address newBorrowCapGuardian);\\n\\n /// @notice The threshold above which the flywheel transfers COMP, in wei\\n uint public constant compClaimThreshold = 0.001e18;\\n\\n /// @notice The initial COMP index for a market\\n uint224 public constant compInitialIndex = 1e36;\\n\\n // closeFactorMantissa must be strictly greater than this value\\n uint internal constant closeFactorMinMantissa = 0.05e18; // 0.05\\n\\n // closeFactorMantissa must not exceed this value\\n uint internal constant closeFactorMaxMantissa = 0.9e18; // 0.9\\n\\n // No collateralFactorMantissa may exceed this value\\n uint internal constant collateralFactorMaxMantissa = 0.9e18; // 0.9\\n\\n // liquidationIncentiveMantissa must be no less than this value\\n uint internal constant liquidationIncentiveMinMantissa = 1.0e18; // 1.0\\n\\n // liquidationIncentiveMantissa must be no greater than this value\\n uint internal constant liquidationIncentiveMaxMantissa = 1.5e18; // 1.5\\n\\n constructor() public {\\n admin = msg.sender;\\n }\\n\\n /*** Assets You Are In ***/\\n\\n /**\\n * @notice Returns the assets an account has entered\\n * @param account The address of the account to pull assets for\\n * @return A dynamic list with the assets the account has entered\\n */\\n function getAssetsIn(address account) external view returns (CToken[] memory) {\\n CToken[] memory assetsIn = accountAssets[account];\\n\\n return assetsIn;\\n }\\n\\n /**\\n * @notice Returns whether the given account is entered in the given asset\\n * @param account The address of the account to check\\n * @param cToken The cToken to check\\n * @return True if the account is in the asset, otherwise false.\\n */\\n function checkMembership(address account, CToken cToken) external view returns (bool) {\\n return markets[address(cToken)].accountMembership[account];\\n }\\n\\n /**\\n * @notice Add assets to be included in account liquidity calculation\\n * @param cTokens The list of addresses of the cToken markets to be enabled\\n * @return Success indicator for whether each corresponding market was entered\\n */\\n function enterMarkets(address[] memory cTokens) public returns (uint[] memory) {\\n uint len = cTokens.length;\\n\\n uint[] memory results = new uint[](len);\\n for (uint i = 0; i < len; i++) {\\n CToken cToken = CToken(cTokens[i]);\\n\\n results[i] = uint(addToMarketInternal(cToken, msg.sender));\\n }\\n\\n return results;\\n }\\n\\n /**\\n * @notice Add the market to the borrower's \\\"assets in\\\" for liquidity calculations\\n * @param cToken The market to enter\\n * @param borrower The address of the account to modify\\n * @return Success indicator for whether the market was entered\\n */\\n function addToMarketInternal(CToken cToken, address borrower) internal returns (Error) {\\n Market storage marketToJoin = markets[address(cToken)];\\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 if (accountAssets[borrower].length >= maxAssets) {\\n // no space, cannot join\\n return Error.TOO_MANY_ASSETS;\\n }\\n\\n // survived the gauntlet, add to list\\n // NOTE: we store these somewhat redundantly as a significant optimization\\n // this avoids having to iterate through the list for the most common use cases\\n // that is, only when we need to perform liquidity checks\\n // and not whenever we want to check if an account is in a particular market\\n marketToJoin.accountMembership[borrower] = true;\\n accountAssets[borrower].push(cToken);\\n\\n emit MarketEntered(cToken, borrower);\\n\\n return Error.NO_ERROR;\\n }\\n\\n /**\\n * @notice Removes asset from sender's 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 cTokenAddress The address of the asset to be removed\\n * @return Whether or not the account successfully exited the market\\n */\\n function exitMarket(address cTokenAddress) external returns (uint) {\\n CToken cToken = CToken(cTokenAddress);\\n /* Get sender tokensHeld and amountOwed underlying from the cToken */\\n (uint oErr, uint tokensHeld, uint amountOwed, ) = cToken.getAccountSnapshot(msg.sender);\\n require(oErr == 0, \\\"exitMarket: getAccountSnapshot failed\\\"); // semi-opaque error code\\n\\n /* Fail if the sender has a borrow balance */\\n if (amountOwed != 0) {\\n return fail(Error.NONZERO_BORROW_BALANCE, FailureInfo.EXIT_MARKET_BALANCE_OWED);\\n }\\n\\n /* Fail if the sender is not permitted to redeem all of their tokens */\\n uint allowed = redeemAllowedInternal(cTokenAddress, msg.sender, tokensHeld);\\n if (allowed != 0) {\\n return failOpaque(Error.REJECTION, FailureInfo.EXIT_MARKET_REJECTION, allowed);\\n }\\n\\n Market storage marketToExit = markets[address(cToken)];\\n\\n /* Return true if the sender is not already \\u2018in\\u2019 the market */\\n if (!marketToExit.accountMembership[msg.sender]) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Set cToken account membership to false */\\n delete marketToExit.accountMembership[msg.sender];\\n\\n /* Delete cToken from the account\\u2019s list of assets */\\n // load into memory for faster iteration\\n CToken[] memory userAssetList = accountAssets[msg.sender];\\n uint len = userAssetList.length;\\n uint assetIndex = len;\\n for (uint i = 0; i < len; i++) {\\n if (userAssetList[i] == cToken) {\\n assetIndex = i;\\n break;\\n }\\n }\\n\\n // We *must* have found the asset in the list or our redundant data structure is broken\\n assert(assetIndex < len);\\n\\n // copy last item in list to location of item to be removed, reduce length by 1\\n CToken[] storage storedList = accountAssets[msg.sender];\\n storedList[assetIndex] = storedList[storedList.length - 1];\\n storedList.length--;\\n\\n emit MarketExited(cToken, 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 cToken The market to verify the mint against\\n * @param minter The account which would get the minted tokens\\n * @param mintAmount The amount of underlying being supplied to the market in exchange for tokens\\n * @return 0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function mintAllowed(address cToken, address minter, uint mintAmount) external returns (uint) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n require(!mintGuardianPaused[cToken], \\\"mint is paused\\\");\\n\\n // Shh - currently unused\\n minter;\\n mintAmount;\\n\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n // Keep the flywheel moving\\n updateCompSupplyIndex(cToken);\\n distributeSupplierComp(cToken, minter, false);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates mint and reverts on rejection. May emit logs.\\n * @param cToken Asset being minted\\n * @param minter The address minting the tokens\\n * @param actualMintAmount The amount of the underlying asset being minted\\n * @param mintTokens The number of tokens being minted\\n */\\n function mintVerify(address cToken, address minter, uint actualMintAmount, uint mintTokens) external {\\n // Shh - currently unused\\n cToken;\\n minter;\\n actualMintAmount;\\n mintTokens;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to redeem tokens in the given market\\n * @param cToken The market to verify the redeem against\\n * @param redeemer The account which would redeem the tokens\\n * @param redeemTokens The number of cTokens to exchange for the underlying asset in the market\\n * @return 0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function redeemAllowed(address cToken, address redeemer, uint redeemTokens) external returns (uint) {\\n uint allowed = redeemAllowedInternal(cToken, redeemer, redeemTokens);\\n if (allowed != uint(Error.NO_ERROR)) {\\n return allowed;\\n }\\n\\n // Keep the flywheel moving\\n updateCompSupplyIndex(cToken);\\n distributeSupplierComp(cToken, redeemer, false);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n function redeemAllowedInternal(address cToken, address redeemer, uint redeemTokens) internal view returns (uint) {\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!markets[cToken].accountMembership[redeemer]) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n (Error err, , uint shortfall) = getHypotheticalAccountLiquidityInternal(redeemer, CToken(cToken), redeemTokens, 0);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n if (shortfall > 0) {\\n return uint(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates redeem and reverts on rejection. May emit logs.\\n * @param cToken Asset being redeemed\\n * @param redeemer The address redeeming the tokens\\n * @param redeemAmount The amount of the underlying asset being redeemed\\n * @param redeemTokens The number of tokens being redeemed\\n */\\n function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) external {\\n // Shh - currently unused\\n cToken;\\n redeemer;\\n\\n // Require tokens is zero or amount is also zero\\n if (redeemTokens == 0 && redeemAmount > 0) {\\n revert(\\\"redeemTokens zero\\\");\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to borrow the underlying asset of the given market\\n * @param cToken The market to verify the borrow against\\n * @param borrower The account which would borrow the asset\\n * @param borrowAmount The amount of underlying the account would borrow\\n * @return 0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function borrowAllowed(address cToken, address borrower, uint borrowAmount) external returns (uint) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n require(!borrowGuardianPaused[cToken], \\\"borrow is paused\\\");\\n\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n if (!markets[cToken].accountMembership[borrower]) {\\n // only cTokens may call borrowAllowed if borrower not in market\\n require(msg.sender == cToken, \\\"sender must be cToken\\\");\\n\\n // attempt to add borrower to the market\\n Error err = addToMarketInternal(CToken(msg.sender), borrower);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n\\n // it should be impossible to break the important invariant\\n assert(markets[cToken].accountMembership[borrower]);\\n }\\n\\n if (oracle.getUnderlyingPrice(CToken(cToken)) == 0) {\\n return uint(Error.PRICE_ERROR);\\n }\\n\\n\\n uint borrowCap = borrowCaps[cToken];\\n // Borrow cap of 0 corresponds to unlimited borrowing\\n if (borrowCap != 0) {\\n uint totalBorrows = CToken(cToken).totalBorrows();\\n (MathError mathErr, uint nextTotalBorrows) = addUInt(totalBorrows, borrowAmount);\\n require(mathErr == MathError.NO_ERROR, \\\"total borrows overflow\\\");\\n require(nextTotalBorrows < borrowCap, \\\"market borrow cap reached\\\");\\n }\\n\\n (Error err, , uint shortfall) = getHypotheticalAccountLiquidityInternal(borrower, CToken(cToken), 0, borrowAmount);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n if (shortfall > 0) {\\n return uint(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n\\n // Keep the flywheel moving\\n Exp memory borrowIndex = Exp({mantissa: CToken(cToken).borrowIndex()});\\n updateCompBorrowIndex(cToken, borrowIndex);\\n distributeBorrowerComp(cToken, borrower, borrowIndex, false);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates borrow and reverts on rejection. May emit logs.\\n * @param cToken Asset whose underlying is being borrowed\\n * @param borrower The address borrowing the underlying\\n * @param borrowAmount The amount of the underlying asset requested to borrow\\n */\\n function borrowVerify(address cToken, address borrower, uint borrowAmount) external {\\n // Shh - currently unused\\n cToken;\\n borrower;\\n borrowAmount;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to repay a borrow in the given market\\n * @param cToken The market to verify the repay against\\n * @param payer The account which would repay the asset\\n * @param borrower The account which would borrowed the asset\\n * @param repayAmount The amount of the underlying asset the account would repay\\n * @return 0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function repayBorrowAllowed(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount) external returns (uint) {\\n // Shh - currently unused\\n payer;\\n borrower;\\n repayAmount;\\n\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n // Keep the flywheel moving\\n Exp memory borrowIndex = Exp({mantissa: CToken(cToken).borrowIndex()});\\n updateCompBorrowIndex(cToken, borrowIndex);\\n distributeBorrowerComp(cToken, borrower, borrowIndex, false);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates repayBorrow and reverts on rejection. May emit logs.\\n * @param cToken Asset being repaid\\n * @param payer The address repaying the borrow\\n * @param borrower The address of the borrower\\n * @param actualRepayAmount The amount of underlying being repaid\\n */\\n function repayBorrowVerify(\\n address cToken,\\n address payer,\\n address borrower,\\n uint actualRepayAmount,\\n uint borrowerIndex) external {\\n // Shh - currently unused\\n cToken;\\n payer;\\n borrower;\\n actualRepayAmount;\\n borrowerIndex;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the liquidation should be allowed to occur\\n * @param cTokenBorrowed Asset which was borrowed by the borrower\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param repayAmount The amount of underlying being repaid\\n */\\n function liquidateBorrowAllowed(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount) external returns (uint) {\\n // Shh - currently unused\\n liquidator;\\n\\n if (!markets[cTokenBorrowed].isListed || !markets[cTokenCollateral].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n /* The borrower must have shortfall in order to be liquidatable */\\n (Error err, , uint shortfall) = getAccountLiquidityInternal(borrower);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n if (shortfall == 0) {\\n return uint(Error.INSUFFICIENT_SHORTFALL);\\n }\\n\\n /* The liquidator may not repay more than what is allowed by the closeFactor */\\n uint borrowBalance = CToken(cTokenBorrowed).borrowBalanceStored(borrower);\\n (MathError mathErr, uint maxClose) = mulScalarTruncate(Exp({mantissa: closeFactorMantissa}), borrowBalance);\\n if (mathErr != MathError.NO_ERROR) {\\n return uint(Error.MATH_ERROR);\\n }\\n if (repayAmount > 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 cTokenBorrowed Asset which was borrowed by the borrower\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param actualRepayAmount The amount of underlying being repaid\\n */\\n function liquidateBorrowVerify(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint actualRepayAmount,\\n uint seizeTokens) external {\\n // Shh - currently unused\\n cTokenBorrowed;\\n cTokenCollateral;\\n liquidator;\\n borrower;\\n actualRepayAmount;\\n seizeTokens;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the seizing of assets should be allowed to occur\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param cTokenBorrowed Asset which was borrowed by the borrower\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param seizeTokens The number of collateral tokens to seize\\n */\\n function seizeAllowed(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external returns (uint) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n require(!seizeGuardianPaused, \\\"seize is paused\\\");\\n\\n // Shh - currently unused\\n seizeTokens;\\n\\n if (!markets[cTokenCollateral].isListed || !markets[cTokenBorrowed].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n if (CToken(cTokenCollateral).comptroller() != CToken(cTokenBorrowed).comptroller()) {\\n return uint(Error.COMPTROLLER_MISMATCH);\\n }\\n\\n // Keep the flywheel moving\\n updateCompSupplyIndex(cTokenCollateral);\\n distributeSupplierComp(cTokenCollateral, borrower, false);\\n distributeSupplierComp(cTokenCollateral, liquidator, false);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates seize and reverts on rejection. May emit logs.\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param cTokenBorrowed Asset which was borrowed by the borrower\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param seizeTokens The number of collateral tokens to seize\\n */\\n function seizeVerify(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external {\\n // Shh - currently unused\\n cTokenCollateral;\\n cTokenBorrowed;\\n liquidator;\\n borrower;\\n seizeTokens;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to transfer tokens in the given market\\n * @param cToken The market to verify the transfer against\\n * @param src The account which sources the tokens\\n * @param dst The account which receives the tokens\\n * @param transferTokens The number of cTokens to transfer\\n * @return 0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function transferAllowed(address cToken, address src, address dst, uint transferTokens) external returns (uint) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n require(!transferGuardianPaused, \\\"transfer is paused\\\");\\n\\n // Currently the only consideration is whether or not\\n // the src is allowed to redeem this many tokens\\n uint allowed = redeemAllowedInternal(cToken, src, transferTokens);\\n if (allowed != uint(Error.NO_ERROR)) {\\n return allowed;\\n }\\n\\n // Keep the flywheel moving\\n updateCompSupplyIndex(cToken);\\n distributeSupplierComp(cToken, src, false);\\n distributeSupplierComp(cToken, dst, false);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates transfer and reverts on rejection. May emit logs.\\n * @param cToken Asset being transferred\\n * @param src The account which sources the tokens\\n * @param dst The account which receives the tokens\\n * @param transferTokens The number of cTokens to transfer\\n */\\n function transferVerify(address cToken, address src, address dst, uint transferTokens) external {\\n // Shh - currently unused\\n cToken;\\n src;\\n dst;\\n transferTokens;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n /**\\n * @dev Local vars for avoiding stack-depth limits in calculating account liquidity.\\n * Note that `cTokenBalance` is the number of cTokens the account owns in the market,\\n * whereas `borrowBalance` is the amount of underlying that the account has borrowed.\\n */\\n struct AccountLiquidityLocalVars {\\n uint sumCollateral;\\n uint sumBorrowPlusEffects;\\n uint cTokenBalance;\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n uint oraclePriceMantissa;\\n Exp collateralFactor;\\n Exp exchangeRate;\\n Exp oraclePrice;\\n Exp tokensToDenom;\\n }\\n\\n /**\\n * @notice Determine the current account liquidity wrt collateral requirements\\n * @return (possible error code (semi-opaque),\\n account liquidity in excess of collateral requirements,\\n * account shortfall below collateral requirements)\\n */\\n function getAccountLiquidity(address account) public view returns (uint, uint, uint) {\\n (Error err, uint liquidity, uint shortfall) = getHypotheticalAccountLiquidityInternal(account, CToken(0), 0, 0);\\n\\n return (uint(err), liquidity, shortfall);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity wrt collateral requirements\\n * @return (possible error code,\\n account liquidity in excess of collateral requirements,\\n * account shortfall below collateral requirements)\\n */\\n function getAccountLiquidityInternal(address account) internal view returns (Error, uint, uint) {\\n return getHypotheticalAccountLiquidityInternal(account, CToken(0), 0, 0);\\n }\\n\\n /**\\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\\n * @param cTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @return (possible error code (semi-opaque),\\n hypothetical account liquidity in excess of collateral requirements,\\n * hypothetical account shortfall below collateral requirements)\\n */\\n function getHypotheticalAccountLiquidity(\\n address account,\\n address cTokenModify,\\n uint redeemTokens,\\n uint borrowAmount) public view returns (uint, uint, uint) {\\n (Error err, uint liquidity, uint shortfall) = getHypotheticalAccountLiquidityInternal(account, CToken(cTokenModify), 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 cTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @dev Note that we calculate the exchangeRateStored for each collateral cToken using stored data,\\n * without calculating accumulated interest.\\n * @return (possible error code,\\n hypothetical account liquidity in excess of collateral requirements,\\n * hypothetical account shortfall below collateral requirements)\\n */\\n function getHypotheticalAccountLiquidityInternal(\\n address account,\\n CToken cTokenModify,\\n uint redeemTokens,\\n uint borrowAmount) internal view returns (Error, uint, uint) {\\n\\n AccountLiquidityLocalVars memory vars; // Holds all our calculation results\\n uint oErr;\\n MathError mErr;\\n\\n // For each asset the account is in\\n CToken[] memory assets = accountAssets[account];\\n for (uint i = 0; i < assets.length; i++) {\\n CToken asset = assets[i];\\n\\n // Read the balances and exchange rate from the cToken\\n (oErr, vars.cTokenBalance, vars.borrowBalance, vars.exchangeRateMantissa) = asset.getAccountSnapshot(account);\\n if (oErr != 0) { // semi-opaque error code, we assume NO_ERROR == 0 is invariant between upgrades\\n return (Error.SNAPSHOT_ERROR, 0, 0);\\n }\\n vars.collateralFactor = Exp({mantissa: markets[address(asset)].collateralFactorMantissa});\\n vars.exchangeRate = Exp({mantissa: vars.exchangeRateMantissa});\\n\\n // Get the normalized price of the asset\\n vars.oraclePriceMantissa = oracle.getUnderlyingPrice(asset);\\n if (vars.oraclePriceMantissa == 0) {\\n return (Error.PRICE_ERROR, 0, 0);\\n }\\n vars.oraclePrice = Exp({mantissa: vars.oraclePriceMantissa});\\n\\n // Pre-compute a conversion factor from tokens -> 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 * cTokenBalance\\n (mErr, vars.sumCollateral) = mulScalarTruncateAddUInt(vars.tokensToDenom, vars.cTokenBalance, 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 cTokenModify\\n if (asset == cTokenModify) {\\n // redeem effect\\n // sumBorrowPlusEffects += tokensToDenom * redeemTokens\\n (mErr, vars.sumBorrowPlusEffects) = mulScalarTruncateAddUInt(vars.tokensToDenom, redeemTokens, vars.sumBorrowPlusEffects);\\n if (mErr != MathError.NO_ERROR) {\\n return (Error.MATH_ERROR, 0, 0);\\n }\\n\\n // borrow effect\\n // sumBorrowPlusEffects += oraclePrice * borrowAmount\\n (mErr, vars.sumBorrowPlusEffects) = mulScalarTruncateAddUInt(vars.oraclePrice, borrowAmount, vars.sumBorrowPlusEffects);\\n if (mErr != MathError.NO_ERROR) {\\n return (Error.MATH_ERROR, 0, 0);\\n }\\n }\\n }\\n\\n // These are safe, as the underflow condition is checked first\\n if (vars.sumCollateral > vars.sumBorrowPlusEffects) {\\n return (Error.NO_ERROR, vars.sumCollateral - vars.sumBorrowPlusEffects, 0);\\n } else {\\n return (Error.NO_ERROR, 0, vars.sumBorrowPlusEffects - vars.sumCollateral);\\n }\\n }\\n\\n /**\\n * @notice Calculate number of tokens of collateral asset to seize given an underlying amount\\n * @dev Used in liquidation (called in cToken.liquidateBorrowFresh)\\n * @param cTokenBorrowed The address of the borrowed cToken\\n * @param cTokenCollateral The address of the collateral cToken\\n * @param actualRepayAmount The amount of cTokenBorrowed underlying to convert into cTokenCollateral tokens\\n * @return (errorCode, number of cTokenCollateral tokens to be seized in a liquidation)\\n */\\n function liquidateCalculateSeizeTokens(address cTokenBorrowed, address cTokenCollateral, uint actualRepayAmount) external view returns (uint, uint) {\\n /* Read oracle prices for borrowed and collateral markets */\\n uint priceBorrowedMantissa = oracle.getUnderlyingPrice(CToken(cTokenBorrowed));\\n uint priceCollateralMantissa = oracle.getUnderlyingPrice(CToken(cTokenCollateral));\\n if (priceBorrowedMantissa == 0 || priceCollateralMantissa == 0) {\\n return (uint(Error.PRICE_ERROR), 0);\\n }\\n\\n /*\\n * Get the exchange rate and calculate the number of collateral tokens to seize:\\n * seizeAmount = actualRepayAmount * liquidationIncentive * priceBorrowed / priceCollateral\\n * seizeTokens = seizeAmount / exchangeRate\\n * = actualRepayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate)\\n */\\n uint exchangeRateMantissa = CToken(cTokenCollateral).exchangeRateStored(); // Note: reverts on error\\n uint seizeTokens;\\n Exp memory numerator;\\n Exp memory denominator;\\n Exp memory ratio;\\n MathError mathErr;\\n\\n (mathErr, numerator) = mulExp(liquidationIncentiveMantissa, priceBorrowedMantissa);\\n if (mathErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0);\\n }\\n\\n (mathErr, denominator) = mulExp(priceCollateralMantissa, exchangeRateMantissa);\\n if (mathErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0);\\n }\\n\\n (mathErr, ratio) = divExp(numerator, denominator);\\n if (mathErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0);\\n }\\n\\n (mathErr, seizeTokens) = mulScalarTruncate(ratio, actualRepayAmount);\\n if (mathErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0);\\n }\\n\\n return (uint(Error.NO_ERROR), seizeTokens);\\n }\\n\\n /*** Admin Functions ***/\\n\\n /**\\n * @notice Sets a new price oracle for the comptroller\\n * @dev Admin function to set a new price oracle\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPriceOracle(PriceOracle newOracle) public returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PRICE_ORACLE_OWNER_CHECK);\\n }\\n\\n // Track the old oracle for the comptroller\\n PriceOracle oldOracle = oracle;\\n\\n // Set comptroller's oracle to newOracle\\n oracle = newOracle;\\n\\n // Emit NewPriceOracle(oldOracle, newOracle)\\n emit NewPriceOracle(oldOracle, newOracle);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets the closeFactor used when liquidating borrows\\n * @dev Admin function to set closeFactor\\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\\n * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function _setCloseFactor(uint newCloseFactorMantissa) external returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_CLOSE_FACTOR_OWNER_CHECK);\\n }\\n\\n Exp memory newCloseFactorExp = Exp({mantissa: newCloseFactorMantissa});\\n Exp memory lowLimit = Exp({mantissa: closeFactorMinMantissa});\\n if (lessThanOrEqualExp(newCloseFactorExp, lowLimit)) {\\n return fail(Error.INVALID_CLOSE_FACTOR, FailureInfo.SET_CLOSE_FACTOR_VALIDATION);\\n }\\n\\n Exp memory highLimit = Exp({mantissa: closeFactorMaxMantissa});\\n if (lessThanExp(highLimit, newCloseFactorExp)) {\\n return fail(Error.INVALID_CLOSE_FACTOR, FailureInfo.SET_CLOSE_FACTOR_VALIDATION);\\n }\\n\\n uint oldCloseFactorMantissa = closeFactorMantissa;\\n closeFactorMantissa = newCloseFactorMantissa;\\n emit NewCloseFactor(oldCloseFactorMantissa, closeFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets the collateralFactor for a market\\n * @dev Admin function to set per-market collateralFactor\\n * @param cToken The market to set the factor on\\n * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18\\n * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function _setCollateralFactor(CToken cToken, 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(cToken)];\\n if (!market.isListed) {\\n return fail(Error.MARKET_NOT_LISTED, FailureInfo.SET_COLLATERAL_FACTOR_NO_EXISTS);\\n }\\n\\n Exp memory newCollateralFactorExp = Exp({mantissa: newCollateralFactorMantissa});\\n\\n // Check collateral factor <= 0.9\\n Exp memory highLimit = Exp({mantissa: collateralFactorMaxMantissa});\\n if (lessThanExp(highLimit, newCollateralFactorExp)) {\\n return fail(Error.INVALID_COLLATERAL_FACTOR, FailureInfo.SET_COLLATERAL_FACTOR_VALIDATION);\\n }\\n\\n // If collateral factor != 0, fail if price == 0\\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(cToken) == 0) {\\n return fail(Error.PRICE_ERROR, FailureInfo.SET_COLLATERAL_FACTOR_WITHOUT_PRICE);\\n }\\n\\n // Set market's collateral factor to new collateral factor, remember old value\\n uint oldCollateralFactorMantissa = market.collateralFactorMantissa;\\n market.collateralFactorMantissa = newCollateralFactorMantissa;\\n\\n // Emit event with asset, old collateral factor, and new collateral factor\\n emit NewCollateralFactor(cToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets maxAssets which controls how many markets can be entered\\n * @dev Admin function to set maxAssets\\n * @param newMaxAssets New max assets\\n * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function _setMaxAssets(uint newMaxAssets) external returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_MAX_ASSETS_OWNER_CHECK);\\n }\\n\\n uint oldMaxAssets = maxAssets;\\n maxAssets = newMaxAssets;\\n emit NewMaxAssets(oldMaxAssets, newMaxAssets);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets liquidationIncentive\\n * @dev Admin function to set liquidationIncentive\\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\\n * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function _setLiquidationIncentive(uint newLiquidationIncentiveMantissa) external returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_LIQUIDATION_INCENTIVE_OWNER_CHECK);\\n }\\n\\n // Check de-scaled min <= newLiquidationIncentive <= max\\n Exp memory newLiquidationIncentive = Exp({mantissa: newLiquidationIncentiveMantissa});\\n Exp memory minLiquidationIncentive = Exp({mantissa: liquidationIncentiveMinMantissa});\\n if (lessThanExp(newLiquidationIncentive, minLiquidationIncentive)) {\\n return fail(Error.INVALID_LIQUIDATION_INCENTIVE, FailureInfo.SET_LIQUIDATION_INCENTIVE_VALIDATION);\\n }\\n\\n Exp memory maxLiquidationIncentive = Exp({mantissa: liquidationIncentiveMaxMantissa});\\n if (lessThanExp(maxLiquidationIncentive, newLiquidationIncentive)) {\\n return fail(Error.INVALID_LIQUIDATION_INCENTIVE, FailureInfo.SET_LIQUIDATION_INCENTIVE_VALIDATION);\\n }\\n\\n // Save current value for use in log\\n uint oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa;\\n\\n // Set liquidation incentive to new incentive\\n liquidationIncentiveMantissa = newLiquidationIncentiveMantissa;\\n\\n // Emit event with old incentive, new incentive\\n emit NewLiquidationIncentive(oldLiquidationIncentiveMantissa, newLiquidationIncentiveMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Add the market to the markets mapping and set it as listed\\n * @dev Admin function to set isListed and add support for the market\\n * @param cToken The address of the market (token) to list\\n * @return uint 0=success, otherwise a failure. (See enum Error for details)\\n */\\n function _supportMarket(CToken cToken) external returns (uint) {\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SUPPORT_MARKET_OWNER_CHECK);\\n }\\n\\n if (markets[address(cToken)].isListed) {\\n return fail(Error.MARKET_ALREADY_LISTED, FailureInfo.SUPPORT_MARKET_EXISTS);\\n }\\n\\n cToken.isCToken(); // Sanity check to make sure its really a CToken\\n\\n markets[address(cToken)] = Market({isListed: true, isComped: false, collateralFactorMantissa: 0});\\n\\n _addMarketInternal(address(cToken));\\n\\n emit MarketListed(cToken);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n function _addMarketInternal(address cToken) internal {\\n for (uint i = 0; i < allMarkets.length; i ++) {\\n require(allMarkets[i] != CToken(cToken), \\\"market already added\\\");\\n }\\n allMarkets.push(CToken(cToken));\\n }\\n\\n\\n /**\\n * @notice Set the given borrow caps for the given cToken markets. Borrowing that brings total borrows to or above borrow cap will revert.\\n * @dev Admin or borrowCapGuardian function to set the borrow caps. A borrow cap of 0 corresponds to unlimited borrowing.\\n * @param cTokens The addresses of the markets (tokens) to change the borrow caps for\\n * @param newBorrowCaps The new borrow cap values in underlying to be set. A value of 0 corresponds to unlimited borrowing.\\n */\\n function _setMarketBorrowCaps(CToken[] calldata cTokens, uint[] calldata newBorrowCaps) external {\\n \\trequire(msg.sender == admin || msg.sender == borrowCapGuardian, \\\"only admin or borrow cap guardian can set borrow caps\\\"); \\n\\n uint numMarkets = cTokens.length;\\n uint numBorrowCaps = newBorrowCaps.length;\\n\\n require(numMarkets != 0 && numMarkets == numBorrowCaps, \\\"invalid input\\\");\\n\\n for(uint i = 0; i < numMarkets; i++) {\\n borrowCaps[address(cTokens[i])] = newBorrowCaps[i];\\n emit NewBorrowCap(cTokens[i], newBorrowCaps[i]);\\n }\\n }\\n\\n /**\\n * @notice Admin function to change the Borrow Cap Guardian\\n * @param newBorrowCapGuardian The address of the new Borrow Cap Guardian\\n */\\n function _setBorrowCapGuardian(address newBorrowCapGuardian) external {\\n require(msg.sender == admin, \\\"only admin can set borrow cap guardian\\\");\\n\\n // Save current value for inclusion in log\\n address oldBorrowCapGuardian = borrowCapGuardian;\\n\\n // Store borrowCapGuardian with value newBorrowCapGuardian\\n borrowCapGuardian = newBorrowCapGuardian;\\n\\n // Emit NewBorrowCapGuardian(OldBorrowCapGuardian, NewBorrowCapGuardian)\\n emit NewBorrowCapGuardian(oldBorrowCapGuardian, newBorrowCapGuardian);\\n }\\n\\n /**\\n * @notice Admin function to change the Pause Guardian\\n * @param newPauseGuardian The address of the new Pause Guardian\\n * @return uint 0=success, otherwise a failure. (See enum Error for details)\\n */\\n function _setPauseGuardian(address newPauseGuardian) public returns (uint) {\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PAUSE_GUARDIAN_OWNER_CHECK);\\n }\\n\\n // Save current value for inclusion in log\\n address oldPauseGuardian = pauseGuardian;\\n\\n // Store pauseGuardian with value newPauseGuardian\\n pauseGuardian = newPauseGuardian;\\n\\n // Emit NewPauseGuardian(OldPauseGuardian, NewPauseGuardian)\\n emit NewPauseGuardian(oldPauseGuardian, pauseGuardian);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n function _setMintPaused(CToken cToken, bool state) public returns (bool) {\\n require(markets[address(cToken)].isListed, \\\"cannot pause a market that is not listed\\\");\\n require(msg.sender == pauseGuardian || msg.sender == admin, \\\"only pause guardian and admin can pause\\\");\\n require(msg.sender == admin || state == true, \\\"only admin can unpause\\\");\\n\\n mintGuardianPaused[address(cToken)] = state;\\n emit ActionPaused(cToken, \\\"Mint\\\", state);\\n return state;\\n }\\n\\n function _setBorrowPaused(CToken cToken, bool state) public returns (bool) {\\n require(markets[address(cToken)].isListed, \\\"cannot pause a market that is not listed\\\");\\n require(msg.sender == pauseGuardian || msg.sender == admin, \\\"only pause guardian and admin can pause\\\");\\n require(msg.sender == admin || state == true, \\\"only admin can unpause\\\");\\n\\n borrowGuardianPaused[address(cToken)] = state;\\n emit ActionPaused(cToken, \\\"Borrow\\\", state);\\n return state;\\n }\\n\\n function _setTransferPaused(bool state) public returns (bool) {\\n require(msg.sender == pauseGuardian || msg.sender == admin, \\\"only pause guardian and admin can pause\\\");\\n require(msg.sender == admin || state == true, \\\"only admin can unpause\\\");\\n\\n transferGuardianPaused = state;\\n emit ActionPaused(\\\"Transfer\\\", state);\\n return state;\\n }\\n\\n function _setSeizePaused(bool state) public returns (bool) {\\n require(msg.sender == pauseGuardian || msg.sender == admin, \\\"only pause guardian and admin can pause\\\");\\n require(msg.sender == admin || state == true, \\\"only admin can unpause\\\");\\n\\n seizeGuardianPaused = state;\\n emit ActionPaused(\\\"Seize\\\", state);\\n return state;\\n }\\n\\n function _become(Unitroller unitroller) public {\\n require(msg.sender == unitroller.admin(), \\\"only unitroller admin can change brains\\\");\\n require(unitroller._acceptImplementation() == 0, \\\"change not authorized\\\");\\n }\\n\\n /**\\n * @notice Checks caller is admin, or this contract is becoming the new implementation\\n */\\n function adminOrInitializing() internal view returns (bool) {\\n return msg.sender == admin || msg.sender == comptrollerImplementation;\\n }\\n\\n /*** Comp Distribution ***/\\n\\n /**\\n * @notice Recalculate and update COMP speeds for all COMP markets\\n */\\n function refreshCompSpeeds() public {\\n require(msg.sender == tx.origin, \\\"only externally owned accounts may refresh speeds\\\");\\n refreshCompSpeedsInternal();\\n }\\n\\n function refreshCompSpeedsInternal() internal {\\n CToken[] memory allMarkets_ = allMarkets;\\n\\n for (uint i = 0; i < allMarkets_.length; i++) {\\n CToken cToken = allMarkets_[i];\\n Exp memory borrowIndex = Exp({mantissa: cToken.borrowIndex()});\\n updateCompSupplyIndex(address(cToken));\\n updateCompBorrowIndex(address(cToken), borrowIndex);\\n }\\n\\n Exp memory totalUtility = Exp({mantissa: 0});\\n Exp[] memory utilities = new Exp[](allMarkets_.length);\\n for (uint i = 0; i < allMarkets_.length; i++) {\\n CToken cToken = allMarkets_[i];\\n if (markets[address(cToken)].isComped) {\\n Exp memory assetPrice = Exp({mantissa: oracle.getUnderlyingPrice(cToken)});\\n Exp memory utility = mul_(assetPrice, cToken.totalBorrows());\\n utilities[i] = utility;\\n totalUtility = add_(totalUtility, utility);\\n }\\n }\\n\\n for (uint i = 0; i < allMarkets_.length; i++) {\\n CToken cToken = allMarkets[i];\\n uint newSpeed = totalUtility.mantissa > 0 ? mul_(compRate, div_(utilities[i], totalUtility)) : 0;\\n compSpeeds[address(cToken)] = newSpeed;\\n emit CompSpeedUpdated(cToken, newSpeed);\\n }\\n }\\n\\n /**\\n * @notice Accrue COMP to the market by updating the supply index\\n * @param cToken The market whose supply index to update\\n */\\n function updateCompSupplyIndex(address cToken) internal {\\n CompMarketState storage supplyState = compSupplyState[cToken];\\n uint supplySpeed = compSpeeds[cToken];\\n uint blockNumber = getBlockNumber();\\n uint deltaBlocks = sub_(blockNumber, uint(supplyState.block));\\n if (deltaBlocks > 0 && supplySpeed > 0) {\\n uint supplyTokens = CToken(cToken).totalSupply();\\n uint compAccrued = mul_(deltaBlocks, supplySpeed);\\n Double memory ratio = supplyTokens > 0 ? fraction(compAccrued, supplyTokens) : Double({mantissa: 0});\\n Double memory index = add_(Double({mantissa: supplyState.index}), ratio);\\n compSupplyState[cToken] = CompMarketState({\\n index: safe224(index.mantissa, \\\"new index exceeds 224 bits\\\"),\\n block: safe32(blockNumber, \\\"block number exceeds 32 bits\\\")\\n });\\n } else if (deltaBlocks > 0) {\\n supplyState.block = safe32(blockNumber, \\\"block number exceeds 32 bits\\\");\\n }\\n }\\n\\n /**\\n * @notice Accrue COMP to the market by updating the borrow index\\n * @param cToken The market whose borrow index to update\\n */\\n function updateCompBorrowIndex(address cToken, Exp memory marketBorrowIndex) internal {\\n CompMarketState storage borrowState = compBorrowState[cToken];\\n uint borrowSpeed = compSpeeds[cToken];\\n uint blockNumber = getBlockNumber();\\n uint deltaBlocks = sub_(blockNumber, uint(borrowState.block));\\n if (deltaBlocks > 0 && borrowSpeed > 0) {\\n uint borrowAmount = div_(CToken(cToken).totalBorrows(), marketBorrowIndex);\\n uint compAccrued = mul_(deltaBlocks, borrowSpeed);\\n Double memory ratio = borrowAmount > 0 ? fraction(compAccrued, borrowAmount) : Double({mantissa: 0});\\n Double memory index = add_(Double({mantissa: borrowState.index}), ratio);\\n compBorrowState[cToken] = CompMarketState({\\n index: safe224(index.mantissa, \\\"new index exceeds 224 bits\\\"),\\n block: safe32(blockNumber, \\\"block number exceeds 32 bits\\\")\\n });\\n } else if (deltaBlocks > 0) {\\n borrowState.block = safe32(blockNumber, \\\"block number exceeds 32 bits\\\");\\n }\\n }\\n\\n /**\\n * @notice Calculate COMP accrued by a supplier and possibly transfer it to them\\n * @param cToken The market in which the supplier is interacting\\n * @param supplier The address of the supplier to distribute COMP to\\n */\\n function distributeSupplierComp(address cToken, address supplier, bool distributeAll) internal {\\n CompMarketState storage supplyState = compSupplyState[cToken];\\n Double memory supplyIndex = Double({mantissa: supplyState.index});\\n Double memory supplierIndex = Double({mantissa: compSupplierIndex[cToken][supplier]});\\n compSupplierIndex[cToken][supplier] = supplyIndex.mantissa;\\n\\n if (supplierIndex.mantissa == 0 && supplyIndex.mantissa > 0) {\\n supplierIndex.mantissa = compInitialIndex;\\n }\\n\\n Double memory deltaIndex = sub_(supplyIndex, supplierIndex);\\n uint supplierTokens = CToken(cToken).balanceOf(supplier);\\n uint supplierDelta = mul_(supplierTokens, deltaIndex);\\n uint supplierAccrued = add_(compAccrued[supplier], supplierDelta);\\n compAccrued[supplier] = transferComp(supplier, supplierAccrued, distributeAll ? 0 : compClaimThreshold);\\n emit DistributedSupplierComp(CToken(cToken), supplier, supplierDelta, supplyIndex.mantissa);\\n }\\n\\n /**\\n * @notice Calculate COMP accrued by a borrower and possibly transfer it to them\\n * @dev Borrowers will not begin to accrue until after the first interaction with the protocol.\\n * @param cToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute COMP to\\n */\\n function distributeBorrowerComp(address cToken, address borrower, Exp memory marketBorrowIndex, bool distributeAll) internal {\\n CompMarketState storage borrowState = compBorrowState[cToken];\\n Double memory borrowIndex = Double({mantissa: borrowState.index});\\n Double memory borrowerIndex = Double({mantissa: compBorrowerIndex[cToken][borrower]});\\n compBorrowerIndex[cToken][borrower] = borrowIndex.mantissa;\\n\\n if (borrowerIndex.mantissa > 0) {\\n Double memory deltaIndex = sub_(borrowIndex, borrowerIndex);\\n uint borrowerAmount = div_(CToken(cToken).borrowBalanceStored(borrower), marketBorrowIndex);\\n uint borrowerDelta = mul_(borrowerAmount, deltaIndex);\\n uint borrowerAccrued = add_(compAccrued[borrower], borrowerDelta);\\n compAccrued[borrower] = transferComp(borrower, borrowerAccrued, distributeAll ? 0 : compClaimThreshold);\\n emit DistributedBorrowerComp(CToken(cToken), borrower, borrowerDelta, borrowIndex.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Transfer COMP to the user, if they are above the threshold\\n * @dev Note: If there is not enough COMP, we do not perform the transfer all.\\n * @param user The address of the user to transfer COMP to\\n * @param userAccrued The amount of COMP to (possibly) transfer\\n * @return The amount of COMP which was NOT transferred to the user\\n */\\n function transferComp(address user, uint userAccrued, uint threshold) internal returns (uint) {\\n if (userAccrued >= threshold && userAccrued > 0) {\\n Comp comp = Comp(getCompAddress());\\n uint compRemaining = comp.balanceOf(address(this));\\n if (userAccrued <= compRemaining) {\\n comp.transfer(user, userAccrued);\\n return 0;\\n }\\n }\\n return userAccrued;\\n }\\n\\n /**\\n * @notice Claim all the comp accrued by holder in all markets\\n * @param holder The address to claim COMP for\\n */\\n function claimComp(address holder) public {\\n return claimComp(holder, allMarkets);\\n }\\n\\n /**\\n * @notice Claim all the comp accrued by holder in the specified markets\\n * @param holder The address to claim COMP for\\n * @param cTokens The list of markets to claim COMP in\\n */\\n function claimComp(address holder, CToken[] memory cTokens) public {\\n address[] memory holders = new address[](1);\\n holders[0] = holder;\\n claimComp(holders, cTokens, true, true);\\n }\\n\\n /**\\n * @notice Claim all comp accrued by the holders\\n * @param holders The addresses to claim COMP for\\n * @param cTokens The list of markets to claim COMP in\\n * @param borrowers Whether or not to claim COMP earned by borrowing\\n * @param suppliers Whether or not to claim COMP earned by supplying\\n */\\n function claimComp(address[] memory holders, CToken[] memory cTokens, bool borrowers, bool suppliers) public {\\n for (uint i = 0; i < cTokens.length; i++) {\\n CToken cToken = cTokens[i];\\n require(markets[address(cToken)].isListed, \\\"market must be listed\\\");\\n if (borrowers == true) {\\n Exp memory borrowIndex = Exp({mantissa: cToken.borrowIndex()});\\n updateCompBorrowIndex(address(cToken), borrowIndex);\\n for (uint j = 0; j < holders.length; j++) {\\n distributeBorrowerComp(address(cToken), holders[j], borrowIndex, true);\\n }\\n }\\n if (suppliers == true) {\\n updateCompSupplyIndex(address(cToken));\\n for (uint j = 0; j < holders.length; j++) {\\n distributeSupplierComp(address(cToken), holders[j], true);\\n }\\n }\\n }\\n }\\n\\n /*** Comp Distribution Admin ***/\\n\\n /**\\n * @notice Set the amount of COMP distributed per block\\n * @param compRate_ The amount of COMP wei per block to distribute\\n */\\n function _setCompRate(uint compRate_) public {\\n require(adminOrInitializing(), \\\"only admin can change comp rate\\\");\\n\\n uint oldRate = compRate;\\n compRate = compRate_;\\n emit NewCompRate(oldRate, compRate_);\\n\\n refreshCompSpeedsInternal();\\n }\\n\\n /**\\n * @notice Add markets to compMarkets, allowing them to earn COMP in the flywheel\\n * @param cTokens The addresses of the markets to add\\n */\\n function _addCompMarkets(address[] memory cTokens) public {\\n require(adminOrInitializing(), \\\"only admin can add comp market\\\");\\n\\n for (uint i = 0; i < cTokens.length; i++) {\\n _addCompMarketInternal(cTokens[i]);\\n }\\n\\n refreshCompSpeedsInternal();\\n }\\n\\n function _addCompMarketInternal(address cToken) internal {\\n Market storage market = markets[cToken];\\n require(market.isListed == true, \\\"comp market is not listed\\\");\\n require(market.isComped == false, \\\"comp market already added\\\");\\n\\n market.isComped = true;\\n emit MarketComped(CToken(cToken), true);\\n\\n if (compSupplyState[cToken].index == 0 && compSupplyState[cToken].block == 0) {\\n compSupplyState[cToken] = CompMarketState({\\n index: compInitialIndex,\\n block: safe32(getBlockNumber(), \\\"block number exceeds 32 bits\\\")\\n });\\n }\\n\\n if (compBorrowState[cToken].index == 0 && compBorrowState[cToken].block == 0) {\\n compBorrowState[cToken] = CompMarketState({\\n index: compInitialIndex,\\n block: safe32(getBlockNumber(), \\\"block number exceeds 32 bits\\\")\\n });\\n }\\n }\\n\\n /**\\n * @notice Remove a market from compMarkets, preventing it from earning COMP in the flywheel\\n * @param cToken The address of the market to drop\\n */\\n function _dropCompMarket(address cToken) public {\\n require(msg.sender == admin, \\\"only admin can drop comp market\\\");\\n\\n Market storage market = markets[cToken];\\n require(market.isComped == true, \\\"market is not a comp market\\\");\\n\\n market.isComped = false;\\n emit MarketComped(CToken(cToken), false);\\n\\n refreshCompSpeedsInternal();\\n }\\n\\n /**\\n * @notice Return all of the markets\\n * @dev The automatic getter may be used to access an individual market.\\n * @return The list of market addresses\\n */\\n function getAllMarkets() public view returns (CToken[] memory) {\\n return allMarkets;\\n }\\n\\n function getBlockNumber() public view returns (uint) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Return the address of the COMP token\\n * @return The address of COMP\\n */\\n function getCompAddress() public view returns (address) {\\n return 0xc00e94Cb662C3520282E6f5717214004A7f26888;\\n }\\n}\\n\",\"keccak256\":\"0x9d5ce154d0a488926be966885160d2ff0442cd067056d08ecae47d65b1979528\"},\"contracts/ComptrollerInterface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\ncontract ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n bool public constant isComptroller = true;\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata cTokens) external returns (uint[] memory);\\n function exitMarket(address cToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address cToken, address minter, uint mintAmount) external returns (uint);\\n function mintVerify(address cToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address cToken, address redeemer, uint redeemTokens) external returns (uint);\\n function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address cToken, address borrower, uint borrowAmount) external returns (uint);\\n function borrowVerify(address cToken, address borrower, uint borrowAmount) external;\\n\\n function repayBorrowAllowed(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount) external returns (uint);\\n function repayBorrowVerify(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex) external;\\n\\n function liquidateBorrowAllowed(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount) external returns (uint);\\n function liquidateBorrowVerify(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens) external;\\n\\n function seizeAllowed(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external returns (uint);\\n function seizeVerify(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external;\\n\\n function transferAllowed(address cToken, address src, address dst, uint transferTokens) external returns (uint);\\n function transferVerify(address cToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n uint repayAmount) external view returns (uint, uint);\\n}\\n\",\"keccak256\":\"0xede7670d2dd7b25d0187aecd2c28b7b5ca7d7c1bdac144fbedecf5d4bdd92a6b\"},\"contracts/ComptrollerStorage.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.sol\\\";\\nimport \\\"./PriceOracle.sol\\\";\\n\\ncontract UnitrollerAdminStorage {\\n /**\\n * @notice Administrator for this contract\\n */\\n address public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address public pendingAdmin;\\n\\n /**\\n * @notice Active brains of Unitroller\\n */\\n address public comptrollerImplementation;\\n\\n /**\\n * @notice Pending brains of Unitroller\\n */\\n address public pendingComptrollerImplementation;\\n}\\n\\ncontract ComptrollerV1Storage is UnitrollerAdminStorage {\\n\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n PriceOracle public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives\\n */\\n uint public liquidationIncentiveMantissa;\\n\\n /**\\n * @notice Max number of assets a single account can participate in (borrow or use as collateral)\\n */\\n uint public maxAssets;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\\n */\\n mapping(address => CToken[]) public accountAssets;\\n\\n}\\n\\ncontract ComptrollerV2Storage is ComptrollerV1Storage {\\n struct Market {\\n /// @notice Whether or not this market is listed\\n bool isListed;\\n\\n /**\\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\\n * For instance, 0.9 to allow borrowing 90% of collateral value.\\n * Must be between 0 and 1, and stored as a mantissa.\\n */\\n uint collateralFactorMantissa;\\n\\n /// @notice Per-market mapping of \\\"accounts in this asset\\\"\\n mapping(address => bool) accountMembership;\\n\\n /// @notice Whether or not this market receives COMP\\n bool isComped;\\n }\\n\\n /**\\n * @notice Official mapping of cTokens -> Market metadata\\n * @dev Used e.g. to determine if a market is supported\\n */\\n mapping(address => Market) public markets;\\n\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n * Actions which allow users to remove their own assets cannot be paused.\\n * Liquidation / seizing / transfer can only be paused globally, not by market.\\n */\\n address public pauseGuardian;\\n bool public _mintGuardianPaused;\\n bool public _borrowGuardianPaused;\\n bool public transferGuardianPaused;\\n bool public seizeGuardianPaused;\\n mapping(address => bool) public mintGuardianPaused;\\n mapping(address => bool) public borrowGuardianPaused;\\n}\\n\\ncontract ComptrollerV3Storage is ComptrollerV2Storage {\\n struct CompMarketState {\\n /// @notice The market's last updated compBorrowIndex or compSupplyIndex\\n uint224 index;\\n\\n /// @notice The block number the index was last updated at\\n uint32 block;\\n }\\n\\n /// @notice A list of all markets\\n CToken[] public allMarkets;\\n\\n /// @notice The rate at which the flywheel distributes COMP, per block\\n uint public compRate;\\n\\n /// @notice The portion of compRate that each market currently receives\\n mapping(address => uint) public compSpeeds;\\n\\n /// @notice The COMP market supply state for each market\\n mapping(address => CompMarketState) public compSupplyState;\\n\\n /// @notice The COMP market borrow state for each market\\n mapping(address => CompMarketState) public compBorrowState;\\n\\n /// @notice The COMP borrow index for each market for each supplier as of the last time they accrued COMP\\n mapping(address => mapping(address => uint)) public compSupplierIndex;\\n\\n /// @notice The COMP borrow index for each market for each borrower as of the last time they accrued COMP\\n mapping(address => mapping(address => uint)) public compBorrowerIndex;\\n\\n /// @notice The COMP accrued but not yet transferred to each user\\n mapping(address => uint) public compAccrued;\\n}\\n\\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\\n // @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\\n address public borrowCapGuardian;\\n\\n // @notice Borrow caps enforced by borrowAllowed for each cToken address. Defaults to zero which corresponds to unlimited borrowing.\\n mapping(address => uint) public borrowCaps;\\n}\\n\\ncontract ComptrollerV5Storage is ComptrollerV4Storage {\\n /// @notice The portion of COMP that each contributor receives per block\\n mapping(address => uint) public compContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's COMP rewards have been allocated\\n mapping(address => uint) public lastContributorBlock;\\n}\\n\",\"keccak256\":\"0x5db970485549f493618b5e36bfd4d799d4f8701a136bf71ed6e0117e1ed8c254\"},\"contracts/EIP20Interface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title ERC 20 Token Standard Interface\\n * https://eips.ethereum.org/EIPS/eip-20\\n */\\ninterface EIP20Interface {\\n function name() external view returns (string memory);\\n function symbol() external view returns (string memory);\\n function decimals() external view returns (uint8);\\n\\n /**\\n * @notice Get the total number of tokens in circulation\\n * @return The supply of tokens\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @notice Gets the balance of the specified address\\n * @param owner The address from which the balance will be retrieved\\n * @return The balance\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transfer(address dst, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferFrom(address src, address dst, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (-1 means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (-1 means infinite)\\n */\\n function allowance(address owner, address spender) external view returns (uint256 remaining);\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n}\\n\",\"keccak256\":\"0xfd8ed2eac6d0b4d9ee6b32628ba68bae17544b66f190a5f7ce0c6ad024579dc8\"},\"contracts/EIP20NonStandardInterface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title EIP20NonStandardInterface\\n * @dev Version of ERC20 with no return values for `transfer` and `transferFrom`\\n * See https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\\n */\\ninterface EIP20NonStandardInterface {\\n\\n /**\\n * @notice Get the total number of tokens in circulation\\n * @return The supply of tokens\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @notice Gets the balance of the specified address\\n * @param owner The address from which the balance will be retrieved\\n * @return The balance\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n ///\\n /// !!!!!!!!!!!!!!\\n /// !!! NOTICE !!! `transfer` does not return a value, in violation of the ERC-20 specification\\n /// !!!!!!!!!!!!!!\\n ///\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n */\\n function transfer(address dst, uint256 amount) external;\\n\\n ///\\n /// !!!!!!!!!!!!!!\\n /// !!! NOTICE !!! `transferFrom` does not return a value, in violation of the ERC-20 specification\\n /// !!!!!!!!!!!!!!\\n ///\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n */\\n function transferFrom(address src, address dst, uint256 amount) external;\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent\\n */\\n function allowance(address owner, address spender) external view returns (uint256 remaining);\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n}\\n\",\"keccak256\":\"0x9719f12e4b80b51147ac195553a198cf8b0c516e7e4d04fc324a23ed15cbafb2\"},\"contracts/ErrorReporter.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\ncontract ComptrollerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\",\"keccak256\":\"0x5179afb1071c0fd555e5c1f1d2565f72dbe1740cc3dd02f6e52037f150afc5c9\"},\"contracts/Exponential.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CarefulMath.sol\\\";\\nimport \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @dev Legacy contract for compatibility reasons with existing contracts that still use MathError\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: rational}));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({mantissa: result}));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({mantissa: result}));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: scaledMantissa}));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: descaledMantissa}));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) pure internal returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({mantissa: 0}));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({mantissa: product}));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) pure internal returns (MathError, Exp memory) {\\n return mulExp(Exp({mantissa: a}), Exp({mantissa: b}));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) pure internal returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6ff054d65a0289dbb43c9f437d6909f9cf1207c9b8f984b3cb8e97a9de76a434\"},\"contracts/ExponentialNoError.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\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 Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) pure internal returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) pure internal returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) pure internal returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) pure internal returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) pure internal returns (uint224) {\\n require(n < 2**224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) pure internal returns (uint32) {\\n require(n < 2**32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: add_(a.mantissa, b.mantissa)});\\n }\\n\\n function add_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: add_(a.mantissa, b.mantissa)});\\n }\\n\\n function add_(uint a, uint b) pure internal returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: sub_(a.mantissa, b.mantissa)});\\n }\\n\\n function sub_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: sub_(a.mantissa, b.mantissa)});\\n }\\n\\n function sub_(uint a, uint b) pure internal returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: mul_(a.mantissa, b.mantissa) / expScale});\\n }\\n\\n function mul_(Exp memory a, uint b) pure internal returns (Exp memory) {\\n return Exp({mantissa: mul_(a.mantissa, b)});\\n }\\n\\n function mul_(uint a, Exp memory b) pure internal returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: mul_(a.mantissa, b.mantissa) / doubleScale});\\n }\\n\\n function mul_(Double memory a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: mul_(a.mantissa, b)});\\n }\\n\\n function mul_(uint a, Double memory b) pure internal returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) pure internal returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) pure internal 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) pure internal returns (Exp memory) {\\n return Exp({mantissa: div_(mul_(a.mantissa, expScale), b.mantissa)});\\n }\\n\\n function div_(Exp memory a, uint b) pure internal returns (Exp memory) {\\n return Exp({mantissa: div_(a.mantissa, b)});\\n }\\n\\n function div_(uint a, Exp memory b) pure internal returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa)});\\n }\\n\\n function div_(Double memory a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(a.mantissa, b)});\\n }\\n\\n function div_(uint a, Double memory b) pure internal returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) pure internal returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(mul_(a, doubleScale), b)});\\n }\\n}\\n\",\"keccak256\":\"0x7cb184b7cee71a5e707053dfba7eebbd46f11974004028100510ccce19b6694d\"},\"contracts/Governance/Comp.sol\":{\"content\":\"pragma solidity ^0.5.16;\\npragma experimental ABIEncoderV2;\\n\\ncontract Comp {\\n /// @notice EIP-20 token name for this token\\n string public constant name = \\\"Compound\\\";\\n\\n /// @notice EIP-20 token symbol for this token\\n string public constant symbol = \\\"COMP\\\";\\n\\n /// @notice EIP-20 token decimals for this token\\n uint8 public constant decimals = 18;\\n\\n /// @notice Total number of tokens in circulation\\n uint public constant totalSupply = 10000000e18; // 10 million Comp\\n\\n /// @notice Allowance amounts on behalf of others\\n mapping (address => mapping (address => uint96)) internal allowances;\\n\\n /// @notice Official record of token balances for each account\\n mapping (address => uint96) internal balances;\\n\\n /// @notice A record of each accounts delegate\\n mapping (address => address) public delegates;\\n\\n /// @notice A checkpoint for marking number of votes from a given block\\n struct Checkpoint {\\n uint32 fromBlock;\\n uint96 votes;\\n }\\n\\n /// @notice A record of votes checkpoints for each account, by index\\n mapping (address => mapping (uint32 => Checkpoint)) public checkpoints;\\n\\n /// @notice The number of checkpoints for each account\\n mapping (address => uint32) public numCheckpoints;\\n\\n /// @notice The EIP-712 typehash for the contract's domain\\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\\\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\\\");\\n\\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\\\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\\\");\\n\\n /// @notice A record of states for signing / validating signatures\\n mapping (address => uint) public nonces;\\n\\n /// @notice An event thats emitted when an account changes its delegate\\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\\n\\n /// @notice An event thats emitted when a delegate account's vote balance changes\\n event DelegateVotesChanged(address indexed delegate, uint previousBalance, uint newBalance);\\n\\n /// @notice The standard EIP-20 transfer event\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n\\n /// @notice The standard EIP-20 approval event\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n\\n /**\\n * @notice Construct a new Comp token\\n * @param account The initial account to grant all the tokens\\n */\\n constructor(address account) public {\\n balances[account] = uint96(totalSupply);\\n emit Transfer(address(0), account, totalSupply);\\n }\\n\\n /**\\n * @notice Get the number of tokens `spender` is approved to spend on behalf of `account`\\n * @param account The address of the account holding the funds\\n * @param spender The address of the account spending the funds\\n * @return The number of tokens approved\\n */\\n function allowance(address account, address spender) external view returns (uint) {\\n return allowances[account][spender];\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param rawAmount The number of tokens that are approved (2^256-1 means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint rawAmount) external returns (bool) {\\n uint96 amount;\\n if (rawAmount == uint(-1)) {\\n amount = uint96(-1);\\n } else {\\n amount = safe96(rawAmount, \\\"Comp::approve: amount exceeds 96 bits\\\");\\n }\\n\\n allowances[msg.sender][spender] = amount;\\n\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the number of tokens held by the `account`\\n * @param account The address of the account to get the balance of\\n * @return The number of tokens held\\n */\\n function balanceOf(address account) external view returns (uint) {\\n return balances[account];\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param rawAmount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transfer(address dst, uint rawAmount) external returns (bool) {\\n uint96 amount = safe96(rawAmount, \\\"Comp::transfer: amount exceeds 96 bits\\\");\\n _transferTokens(msg.sender, dst, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param rawAmount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferFrom(address src, address dst, uint rawAmount) external returns (bool) {\\n address spender = msg.sender;\\n uint96 spenderAllowance = allowances[src][spender];\\n uint96 amount = safe96(rawAmount, \\\"Comp::approve: amount exceeds 96 bits\\\");\\n\\n if (spender != src && spenderAllowance != uint96(-1)) {\\n uint96 newAllowance = sub96(spenderAllowance, amount, \\\"Comp::transferFrom: transfer amount exceeds spender allowance\\\");\\n allowances[src][spender] = newAllowance;\\n\\n emit Approval(src, spender, newAllowance);\\n }\\n\\n _transferTokens(src, dst, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Delegate votes from `msg.sender` to `delegatee`\\n * @param delegatee The address to delegate votes to\\n */\\n function delegate(address delegatee) public {\\n return _delegate(msg.sender, delegatee);\\n }\\n\\n /**\\n * @notice Delegates votes from signatory to `delegatee`\\n * @param delegatee The address to delegate votes to\\n * @param nonce The contract state required to match the signature\\n * @param expiry The time at which to expire the signature\\n * @param v The recovery byte of the signature\\n * @param r Half of the ECDSA signature pair\\n * @param s Half of the ECDSA signature pair\\n */\\n function delegateBySig(address delegatee, uint nonce, uint expiry, uint8 v, bytes32 r, bytes32 s) public {\\n bytes32 domainSeparator = keccak256(abi.encode(DOMAIN_TYPEHASH, keccak256(bytes(name)), getChainId(), address(this)));\\n bytes32 structHash = keccak256(abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry));\\n bytes32 digest = keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash));\\n address signatory = ecrecover(digest, v, r, s);\\n require(signatory != address(0), \\\"Comp::delegateBySig: invalid signature\\\");\\n require(nonce == nonces[signatory]++, \\\"Comp::delegateBySig: invalid nonce\\\");\\n require(now <= expiry, \\\"Comp::delegateBySig: signature expired\\\");\\n return _delegate(signatory, delegatee);\\n }\\n\\n /**\\n * @notice Gets the current votes balance for `account`\\n * @param account The address to get votes balance\\n * @return The number of current votes for `account`\\n */\\n function getCurrentVotes(address account) external view returns (uint96) {\\n uint32 nCheckpoints = numCheckpoints[account];\\n return nCheckpoints > 0 ? checkpoints[account][nCheckpoints - 1].votes : 0;\\n }\\n\\n /**\\n * @notice Determine the prior number of votes for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param account The address of the account to check\\n * @param blockNumber The block number to get the vote balance at\\n * @return The number of votes the account had as of the given block\\n */\\n function getPriorVotes(address account, uint blockNumber) public view returns (uint96) {\\n require(blockNumber < block.number, \\\"Comp::getPriorVotes: not yet determined\\\");\\n\\n uint32 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (checkpoints[account][nCheckpoints - 1].fromBlock <= blockNumber) {\\n return checkpoints[account][nCheckpoints - 1].votes;\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[account][0].fromBlock > blockNumber) {\\n return 0;\\n }\\n\\n uint32 lower = 0;\\n uint32 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[account][center];\\n if (cp.fromBlock == blockNumber) {\\n return cp.votes;\\n } else if (cp.fromBlock < blockNumber) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return checkpoints[account][lower].votes;\\n }\\n\\n function _delegate(address delegator, address delegatee) internal {\\n address currentDelegate = delegates[delegator];\\n uint96 delegatorBalance = balances[delegator];\\n delegates[delegator] = delegatee;\\n\\n emit DelegateChanged(delegator, currentDelegate, delegatee);\\n\\n _moveDelegates(currentDelegate, delegatee, delegatorBalance);\\n }\\n\\n function _transferTokens(address src, address dst, uint96 amount) internal {\\n require(src != address(0), \\\"Comp::_transferTokens: cannot transfer from the zero address\\\");\\n require(dst != address(0), \\\"Comp::_transferTokens: cannot transfer to the zero address\\\");\\n\\n balances[src] = sub96(balances[src], amount, \\\"Comp::_transferTokens: transfer amount exceeds balance\\\");\\n balances[dst] = add96(balances[dst], amount, \\\"Comp::_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 && amount > 0) {\\n if (srcRep != address(0)) {\\n uint32 srcRepNum = numCheckpoints[srcRep];\\n uint96 srcRepOld = srcRepNum > 0 ? checkpoints[srcRep][srcRepNum - 1].votes : 0;\\n uint96 srcRepNew = sub96(srcRepOld, amount, \\\"Comp::_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 > 0 ? checkpoints[dstRep][dstRepNum - 1].votes : 0;\\n uint96 dstRepNew = add96(dstRepOld, amount, \\\"Comp::_moveVotes: vote amount overflows\\\");\\n _writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew);\\n }\\n }\\n }\\n\\n function _writeCheckpoint(address delegatee, uint32 nCheckpoints, uint96 oldVotes, uint96 newVotes) internal {\\n uint32 blockNumber = safe32(block.number, \\\"Comp::_writeCheckpoint: block number exceeds 32 bits\\\");\\n\\n if (nCheckpoints > 0 && checkpoints[delegatee][nCheckpoints - 1].fromBlock == blockNumber) {\\n checkpoints[delegatee][nCheckpoints - 1].votes = newVotes;\\n } else {\\n checkpoints[delegatee][nCheckpoints] = Checkpoint(blockNumber, newVotes);\\n numCheckpoints[delegatee] = nCheckpoints + 1;\\n }\\n\\n emit DelegateVotesChanged(delegatee, oldVotes, newVotes);\\n }\\n\\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\\n require(n < 2**32, errorMessage);\\n return uint32(n);\\n }\\n\\n function safe96(uint n, string memory errorMessage) internal pure returns (uint96) {\\n require(n < 2**96, errorMessage);\\n return uint96(n);\\n }\\n\\n function add96(uint96 a, uint96 b, string memory errorMessage) internal pure returns (uint96) {\\n uint96 c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub96(uint96 a, uint96 b, string memory errorMessage) internal pure returns (uint96) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function getChainId() internal pure returns (uint) {\\n uint256 chainId;\\n assembly { chainId := chainid() }\\n return chainId;\\n }\\n}\\n\",\"keccak256\":\"0x539f7158013dd91efd3ad42dc6a56e0f7aebdca06063d40ce7b6e9a981b726a3\"},\"contracts/InterestRateModel.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Compound's InterestRateModel Interface\\n * @author Compound\\n */\\ncontract InterestRateModel {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint cash, uint borrows, uint reserves) external view returns (uint);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) external view returns (uint);\\n\\n}\\n\",\"keccak256\":\"0x929282d73c79e6d700ebe79f9fafc1e414b3848acff5a56d6740afd1dc908678\"},\"contracts/PriceOracle.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.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 cToken asset\\n * @param cToken The cToken to get the underlying price of\\n * @return The underlying asset price mantissa (scaled by 1e18).\\n * Zero means the price is unavailable.\\n */\\n function getUnderlyingPrice(CToken cToken) external view returns (uint);\\n}\\n\",\"keccak256\":\"0xe79ebc23bba508eb2479e7b3340abf566da1ab62131f106aee1aac3dc53816ef\"},\"contracts/Unitroller.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ErrorReporter.sol\\\";\\nimport \\\"./ComptrollerStorage.sol\\\";\\n/**\\n * @title ComptrollerCore\\n * @dev Storage for the comptroller is at this address, while execution is delegated to the `comptrollerImplementation`.\\n * CTokens should reference this contract as their comptroller.\\n */\\ncontract Unitroller is UnitrollerAdminStorage, ComptrollerErrorReporter {\\n\\n /**\\n * @notice Emitted when pendingComptrollerImplementation is changed\\n */\\n event NewPendingImplementation(address oldPendingImplementation, address newPendingImplementation);\\n\\n /**\\n * @notice Emitted when pendingComptrollerImplementation is accepted, which means comptroller implementation is updated\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Emitted when pendingAdmin is accepted, which means admin is updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n constructor() public {\\n // Set admin to caller\\n admin = msg.sender;\\n }\\n\\n /*** Admin Functions ***/\\n function _setPendingImplementation(address newPendingImplementation) public returns (uint) {\\n\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_IMPLEMENTATION_OWNER_CHECK);\\n }\\n\\n address oldPendingImplementation = pendingComptrollerImplementation;\\n\\n pendingComptrollerImplementation = newPendingImplementation;\\n\\n emit NewPendingImplementation(oldPendingImplementation, pendingComptrollerImplementation);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts new implementation of comptroller. msg.sender must be pendingImplementation\\n * @dev Admin function for new implementation to accept it's role as implementation\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptImplementation() public returns (uint) {\\n // Check caller is pendingImplementation and pendingImplementation \\u2260 address(0)\\n if (msg.sender != pendingComptrollerImplementation || pendingComptrollerImplementation == address(0)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldImplementation = comptrollerImplementation;\\n address oldPendingImplementation = pendingComptrollerImplementation;\\n\\n comptrollerImplementation = pendingComptrollerImplementation;\\n\\n pendingComptrollerImplementation = address(0);\\n\\n emit NewImplementation(oldImplementation, comptrollerImplementation);\\n emit NewPendingImplementation(oldPendingImplementation, pendingComptrollerImplementation);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPendingAdmin(address newPendingAdmin) public returns (uint) {\\n // Check caller = admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\\n }\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptAdmin() public returns (uint) {\\n // Check caller is pendingAdmin and pendingAdmin \\u2260 address(0)\\n if (msg.sender != pendingAdmin || msg.sender == address(0)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = address(0);\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return 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 () payable external {\\n // delegate all other functions to current implementation\\n (bool success, ) = comptrollerImplementation.delegatecall(msg.data);\\n\\n assembly {\\n let free_mem_ptr := mload(0x40)\\n returndatacopy(free_mem_ptr, 0, returndatasize)\\n\\n switch success\\n case 0 { revert(free_mem_ptr, returndatasize) }\\n default { return(free_mem_ptr, returndatasize) }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x51f81451eab9d5c4849507e724f2b2c53e41f54e5359fdbeae89432a727c16df\"}},\"version\":1}" + }, + "contracts/ComptrollerG6.sol:ComptrollerG6": { + "abi": "[{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"action\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"pauseState\",\"type\":\"bool\"}],\"name\":\"ActionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"action\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"pauseState\",\"type\":\"bool\"}],\"name\":\"ActionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"CompGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSpeed\",\"type\":\"uint256\"}],\"name\":\"CompSpeedUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"contributor\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSpeed\",\"type\":\"uint256\"}],\"name\":\"ContributorCompSpeedUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compBorrowIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedBorrowerComp\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"supplier\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compSupplyIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedSupplierComp\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isComped\",\"type\":\"bool\"}],\"name\":\"MarketComped\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketEntered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketExited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"MarketListed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newBorrowCap\",\"type\":\"uint256\"}],\"name\":\"NewBorrowCap\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldBorrowCapGuardian\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newBorrowCapGuardian\",\"type\":\"address\"}],\"name\":\"NewBorrowCapGuardian\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCloseFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCloseFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCollateralFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCollateralFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCompRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCompRate\",\"type\":\"uint256\"}],\"name\":\"NewCompRate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldLiquidationIncentiveMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"NewLiquidationIncentive\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldPauseGuardian\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"NewPauseGuardian\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"oldPriceOracle\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"newPriceOracle\",\"type\":\"address\"}],\"name\":\"NewPriceOracle\",\"type\":\"event\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"_addCompMarkets\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract Unitroller\",\"name\":\"unitroller\",\"type\":\"address\"}],\"name\":\"_become\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"_dropCompMarket\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"_grantComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"newBorrowCapGuardian\",\"type\":\"address\"}],\"name\":\"_setBorrowCapGuardian\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setBorrowPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCloseFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCollateralFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"compRate_\",\"type\":\"uint256\"}],\"name\":\"_setCompRate\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"contributor\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"compSpeed\",\"type\":\"uint256\"}],\"name\":\"_setContributorCompSpeed\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"_setLiquidationIncentive\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"cTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"newBorrowCaps\",\"type\":\"uint256[]\"}],\"name\":\"_setMarketBorrowCaps\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setMintPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"_setPauseGuardian\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"newOracle\",\"type\":\"address\"}],\"name\":\"_setPriceOracle\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setSeizePaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setTransferPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"_supportMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allMarkets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"borrowCapGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"checkMembership\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"},{\"internalType\":\"contract CToken[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"holders\",\"type\":\"address[]\"},{\"internalType\":\"contract CToken[]\",\"name\":\"cTokens\",\"type\":\"address[]\"},{\"internalType\":\"bool\",\"name\":\"borrowers\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"suppliers\",\"type\":\"bool\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compAccrued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compBorrowState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compBorrowerIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compClaimThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compContributorSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compInitialIndex\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSupplierIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSupplyState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"enterMarkets\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenAddress\",\"type\":\"address\"}],\"name\":\"exitMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getAllMarkets\",\"outputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAssetsIn\",\"outputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getCompAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenModify\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"getHypotheticalAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"isComptroller\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"lastContributorBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateCalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"liquidationIncentiveMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"markets\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isComped\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"mintAmount\",\"type\":\"uint256\"}],\"name\":\"mintAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualMintAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"mintTokens\",\"type\":\"uint256\"}],\"name\":\"mintVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"refreshCompSpeeds\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"repayBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowerIndex\",\"type\":\"uint256\"}],\"name\":\"repayBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"seizeGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"transferGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"contributor\",\"type\":\"address\"}],\"name\":\"updateContributorRewards\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + "bin": "608060405234801561001057600080fd5b50600080546001600160a01b03191633179055615dda80620000336000396000f3fe608060405234801561001057600080fd5b50600436106104745760003560e01c80636d154ea511610257578063b21be7fd11610146578063da3d454c116100c3578063e875544611610087578063e8755446146112e1578063e9af0292146112e9578063eabe7d911461130f578063ede4edd014611345578063f851a4401461136b57610474565b8063da3d454c14611243578063dce1544914611279578063dcfbc0c7146112a5578063e4028eee146112ad578063e6653f3d146112d957610474565b8063c488847b1161010a578063c488847b146110b9578063ca0af04314611108578063cc7ebdc414611136578063ce485c5e1461115c578063d02f7351146111fd57610474565b8063b21be7fd14610f80578063bb82aa5e14610fae578063bdcdc25814610fb6578063bea6b8b814610ff2578063c29982381461101857610474565b8063929fe9a1116101d4578063a7f0e23111610198578063a7f0e23114610ece578063aa90075414610ef2578063abfceffc14610efa578063ac0b0bb714610f70578063b0772d0b14610f7857610474565b8063929fe9a114610e4457806394b2294b14610e72578063986ab83814610e7a5780639d1b5a0a14610ea0578063a76b3fda14610ea857610474565b80637dc0d1d01161021b5780637dc0d1d014610da757806387f7630314610daf5780638c57804e14610db75780638e8f294b14610ddd5780638ebf636414610e2557610474565b80636d154ea514610ce75780636d35bf9114610d0d578063731f0c2b14610d53578063741b252514610d79578063747026c914610d9f57610474565b806347ef3b3b11610373578063598ee1cb116102f0578063607ef6c1116102b4578063607ef6c114610a565780636810dfa614610b145780636a49111214610c405780636a56947e14610c5d5780636b79c38d14610c9957610474565b8063598ee1cb146109625780635c7786051461098e5780635ec88c79146109c45780635f5af1aa146109ea5780635fc7e71e14610a1057610474565b80634ef4c3e1116103375780634ef4c3e1146108905780634fd42e17146108c657806351dff989146108e357806352d84d1e1461091f57806355ee1fe11461093c57610474565b806347ef3b3b146107b45780634a584432146108005780634ada90af146108265780634d8e50371461082e5780634e79238f1461083657610474565b806326782247116104015780633aa729b4116103c55780633aa729b4146107145780633bcf7ec11461073a5780633c94786f1461076857806341c728b91461077057806342cbb15c146107ac57610474565b8063267822471461067e57806327efe3cb146106865780632d70db78146106b2578063317b0b77146106d1578063391957d7146106ee57610474565b80631d7b33d7116104485780631d7b33d71461059c5780631ededc91146105d457806321af45691461061657806324008a621461063a57806324a3d6221461067657610474565b80627e3dd21461047957806318c882a5146104955780631c3db2e0146104c35780631d504dc614610576575b600080fd5b610481611373565b604080519115158252519081900360200190f35b610481600480360360408110156104ab57600080fd5b506001600160a01b0381351690602001351515611378565b610574600480360360408110156104d957600080fd5b6001600160a01b038235169190810190604081016020820135600160201b81111561050357600080fd5b82018360208201111561051557600080fd5b803590602001918460208302840111600160201b8311171561053657600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550611518945050505050565b005b6105746004803603602081101561058c57600080fd5b50356001600160a01b031661157a565b6105c2600480360360208110156105b257600080fd5b50356001600160a01b03166116d9565b60408051918252519081900360200190f35b610574600480360360a08110156105ea57600080fd5b506001600160a01b038135811691602081013582169160408201351690606081013590608001356116eb565b61061e6116f2565b604080516001600160a01b039092168252519081900360200190f35b6105c26004803603608081101561065057600080fd5b506001600160a01b03813581169160208101358216916040820135169060600135611701565b61061e6117ca565b61061e6117d9565b6105746004803603604081101561069c57600080fd5b506001600160a01b0381351690602001356117e8565b610481600480360360208110156106c857600080fd5b503515156118eb565b6105c2600480360360208110156106e757600080fd5b5035611a25565b6105746004803603602081101561070457600080fd5b50356001600160a01b0316611ad2565b6105746004803603602081101561072a57600080fd5b50356001600160a01b0316611b7e565b6104816004803603604081101561075057600080fd5b506001600160a01b0381351690602001351515611caf565b610481611e4a565b6105746004803603608081101561078657600080fd5b506001600160a01b03813581169160208101359091169060408101359060600135611e5a565b6105c2611e60565b610574600480360360c08110156107ca57600080fd5b506001600160a01b0381358116916020810135821691604082013581169160608101359091169060808101359060a00135611e65565b6105c26004803603602081101561081657600080fd5b50356001600160a01b0316611e6d565b6105c2611e7f565b610574611e85565b6108726004803603608081101561084c57600080fd5b506001600160a01b03813581169160208101359091169060408101359060600135611ecd565b60408051938452602084019290925282820152519081900360600190f35b6105c2600480360360608110156108a657600080fd5b506001600160a01b03813581169160208101359091169060400135611f07565b6105c2600480360360208110156108dc57600080fd5b5035611faf565b610574600480360360808110156108f957600080fd5b506001600160a01b0381358116916020810135909116906040810135906060013561201f565b61061e6004803603602081101561093557600080fd5b5035612073565b6105c26004803603602081101561095257600080fd5b50356001600160a01b031661209a565b6105746004803603604081101561097857600080fd5b506001600160a01b03813516906020013561211f565b610574600480360360608110156109a457600080fd5b506001600160a01b0381358116916020810135909116906040013561220a565b610872600480360360208110156109da57600080fd5b50356001600160a01b031661220f565b6105c260048036036020811015610a0057600080fd5b50356001600160a01b0316612244565b6105c2600480360360a0811015610a2657600080fd5b506001600160a01b03813581169160208101358216916040820135811691606081013590911690608001356122c8565b61057460048036036040811015610a6c57600080fd5b810190602081018135600160201b811115610a8657600080fd5b820183602082011115610a9857600080fd5b803590602001918460208302840111600160201b83111715610ab957600080fd5b919390929091602081019035600160201b811115610ad657600080fd5b820183602082011115610ae857600080fd5b803590602001918460208302840111600160201b83111715610b0957600080fd5b50909250905061242d565b61057460048036036080811015610b2a57600080fd5b810190602081018135600160201b811115610b4457600080fd5b820183602082011115610b5657600080fd5b803590602001918460208302840111600160201b83111715610b7757600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b811115610bc657600080fd5b820183602082011115610bd857600080fd5b803590602001918460208302840111600160201b83111715610bf957600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295505050508035151591506020013515156125bd565b61057460048036036020811015610c5657600080fd5b5035612766565b61057460048036036080811015610c7357600080fd5b506001600160a01b03813581169160208101358216916040820135169060600135611e5a565b610cbf60048036036020811015610caf57600080fd5b50356001600160a01b031661280a565b604080516001600160e01b03909316835263ffffffff90911660208301528051918290030190f35b61048160048036036020811015610cfd57600080fd5b50356001600160a01b0316612834565b610574600480360360a0811015610d2357600080fd5b506001600160a01b03813581169160208101358216916040820135811691606081013590911690608001356116eb565b61048160048036036020811015610d6957600080fd5b50356001600160a01b0316612849565b61057460048036036020811015610d8f57600080fd5b50356001600160a01b031661285e565b6105c2612921565b61061e61292c565b61048161293b565b610cbf60048036036020811015610dcd57600080fd5b50356001600160a01b031661294b565b610e0360048036036020811015610df357600080fd5b50356001600160a01b0316612975565b6040805193151584526020840192909252151582820152519081900360600190f35b61048160048036036020811015610e3b57600080fd5b5035151561299b565b61048160048036036040811015610e5a57600080fd5b506001600160a01b0381358116916020013516612ad4565b6105c2612b07565b6105c260048036036020811015610e9057600080fd5b50356001600160a01b0316612b0d565b61061e612b1f565b6105c260048036036020811015610ebe57600080fd5b50356001600160a01b0316612b37565b610ed6612c94565b604080516001600160e01b039092168252519081900360200190f35b6105c2612ca7565b610f2060048036036020811015610f1057600080fd5b50356001600160a01b0316612cad565b60408051602080825283518183015283519192839290830191858101910280838360005b83811015610f5c578181015183820152602001610f44565b505050509050019250505060405180910390f35b610481612d36565b610f20612d46565b6105c260048036036040811015610f9657600080fd5b506001600160a01b0381358116916020013516612da8565b61061e612dc5565b6105c260048036036080811015610fcc57600080fd5b506001600160a01b03813581169160208101358216916040820135169060600135612dd4565b6105c26004803603602081101561100857600080fd5b50356001600160a01b0316612e68565b610f206004803603602081101561102e57600080fd5b810190602081018135600160201b81111561104857600080fd5b82018360208201111561105a57600080fd5b803590602001918460208302840111600160201b8311171561107b57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550612e7a945050505050565b6110ef600480360360608110156110cf57600080fd5b506001600160a01b03813581169160208101359091169060400135612f11565b6040805192835260208301919091528051918290030190f35b6105c26004803603604081101561111e57600080fd5b506001600160a01b0381358116916020013516613139565b6105c26004803603602081101561114c57600080fd5b50356001600160a01b0316613156565b6105746004803603602081101561117257600080fd5b810190602081018135600160201b81111561118c57600080fd5b82018360208201111561119e57600080fd5b803590602001918460208302840111600160201b831117156111bf57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550613168945050505050565b6105c2600480360360a081101561121357600080fd5b506001600160a01b03813581169160208101358216916040820135811691606081013590911690608001356131fa565b6105c26004803603606081101561125957600080fd5b506001600160a01b038135811691602081013590911690604001356133b2565b61061e6004803603604081101561128f57600080fd5b506001600160a01b03813516906020013561378e565b61061e6137c3565b6105c2600480360360408110156112c357600080fd5b506001600160a01b0381351690602001356137d2565b610481613982565b6105c2613992565b610574600480360360208110156112ff57600080fd5b50356001600160a01b0316613998565b6105c26004803603606081101561132557600080fd5b506001600160a01b038135811691602081013590911690604001356139fc565b6105c26004803603602081101561135b57600080fd5b50356001600160a01b0316613a39565b61061e613d4c565b600181565b6001600160a01b03821660009081526009602052604081205460ff166113cf5760405162461bcd60e51b8152600401808060200182810382526028815260200180615c5f6028913960400191505060405180910390fd5b600a546001600160a01b03163314806113f257506000546001600160a01b031633145b61142d5760405162461bcd60e51b8152600401808060200182810382526027815260200180615cb86027913960400191505060405180910390fd5b6000546001600160a01b031633148061144857506001821515145b611492576040805162461bcd60e51b81526020600482015260166024820152756f6e6c792061646d696e2063616e20756e706175736560501b604482015290519081900360640190fd5b6001600160a01b0383166000818152600c6020908152604091829020805486151560ff199091168117909155825193845283830152606090830181905260069083015265426f72726f7760d01b6080830152517f71aec636243f9709bb0007ae15e9afb8150ab01716d75fd7573be5cc096e03b09181900360a00190a150805b92915050565b60408051600180825281830190925260609160208083019080388339019050509050828160008151811061154857fe5b60200260200101906001600160a01b031690816001600160a01b03168152505061157581836001806125bd565b505050565b806001600160a01b031663f851a4406040518163ffffffff1660e01b815260040160206040518083038186803b1580156115b357600080fd5b505afa1580156115c7573d6000803e3d6000fd5b505050506040513d60208110156115dd57600080fd5b50516001600160a01b031633146116255760405162461bcd60e51b8152600401808060200182810382526027815260200180615d7f6027913960400191505060405180910390fd5b806001600160a01b031663c1e803346040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561166057600080fd5b505af1158015611674573d6000803e3d6000fd5b505050506040513d602081101561168a57600080fd5b5051156116d6576040805162461bcd60e51b815260206004820152601560248201527418da185b99d9481b9bdd08185d5d1a1bdc9a5e9959605a1b604482015290519081900360640190fd5b50565b600f6020526000908152604090205481565b5050505050565b6015546001600160a01b031681565b6001600160a01b03841660009081526009602052604081205460ff16611729575060096117c2565b611731615b9f565b6040518060200160405280876001600160a01b031663aa5af0fd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561177557600080fd5b505afa158015611789573d6000803e3d6000fd5b505050506040513d602081101561179f57600080fd5b5051905290506117af8682613d5b565b6117bc8685836000613fe3565b60009150505b949350505050565b600a546001600160a01b031681565b6001546001600160a01b031681565b6117f06141cd565b611841576040805162461bcd60e51b815260206004820152601960248201527f6f6e6c792061646d696e2063616e206772616e7420636f6d7000000000000000604482015290519081900360640190fd5b600061184d83836141f6565b905080156118a2576040805162461bcd60e51b815260206004820152601b60248201527f696e73756666696369656e7420636f6d7020666f72206772616e740000000000604482015290519081900360640190fd5b604080516001600160a01b03851681526020810184905281517f98b2f82a3a07f223a0be64b3d0f47711c64dccd1feafb94aa28156b38cd9695c929181900390910190a1505050565b600a546000906001600160a01b031633148061191157506000546001600160a01b031633145b61194c5760405162461bcd60e51b8152600401808060200182810382526027815260200180615cb86027913960400191505060405180910390fd5b6000546001600160a01b031633148061196757506001821515145b6119b1576040805162461bcd60e51b81526020600482015260166024820152756f6e6c792061646d696e2063616e20756e706175736560501b604482015290519081900360640190fd5b600a8054831515600160b81b810260ff60b81b1990921691909117909155604080516020810192909252808252600582820152645365697a6560d81b6060830152517fef159d9a32b2472e32b098f954f3ce62d232939f1c207070b584df1814de2de09181900360800190a150805b919050565b600080546001600160a01b03163314611a85576040805162461bcd60e51b815260206004820152601f60248201527f6f6e6c792061646d696e2063616e2073657420636c6f736520666163746f7200604482015290519081900360640190fd5b6005805490839055604080518281526020810185905281517f3b9670cf975d26958e754b57098eaa2ac914d8d2a31b83257997b9f346110fd9929181900390910190a160005b9392505050565b6000546001600160a01b03163314611b1b5760405162461bcd60e51b8152600401808060200182810382526026815260200180615cdf6026913960400191505060405180910390fd5b601580546001600160a01b038381166001600160a01b0319831681179093556040805191909216808252602082019390935281517feda98690e518e9a05f8ec6837663e188211b2da8f4906648b323f2c1d4434e29929181900390910190a15050565b6000546001600160a01b03163314611bdd576040805162461bcd60e51b815260206004820152601f60248201527f6f6e6c792061646d696e2063616e2064726f7020636f6d70206d61726b657400604482015290519081900360640190fd5b6001600160a01b0381166000908152600960205260409020600381015460ff161515600114611c53576040805162461bcd60e51b815260206004820152601b60248201527f6d61726b6574206973206e6f74206120636f6d70206d61726b65740000000000604482015290519081900360640190fd5b60038101805460ff19169055604080516001600160a01b03841681526000602082015281517f93c1f3e36ed71139f466a4ce8c9751790e2e33f5afb2df0dcfb3aeabe55d5aa2929181900390910190a1611cab614323565b5050565b6001600160a01b03821660009081526009602052604081205460ff16611d065760405162461bcd60e51b8152600401808060200182810382526028815260200180615c5f6028913960400191505060405180910390fd5b600a546001600160a01b0316331480611d2957506000546001600160a01b031633145b611d645760405162461bcd60e51b8152600401808060200182810382526027815260200180615cb86027913960400191505060405180910390fd5b6000546001600160a01b0316331480611d7f57506001821515145b611dc9576040805162461bcd60e51b81526020600482015260166024820152756f6e6c792061646d696e2063616e20756e706175736560501b604482015290519081900360640190fd5b6001600160a01b0383166000818152600b6020908152604091829020805486151560ff199091168117909155825193845283830152606090830181905260049083015263135a5b9d60e21b6080830152517f71aec636243f9709bb0007ae15e9afb8150ab01716d75fd7573be5cc096e03b09181900360a00190a150919050565b600a54600160a01b900460ff1681565b50505050565b435b90565b505050505050565b60166020526000908152604090205481565b60065481565b333214611ec35760405162461bcd60e51b8152600401808060200182810382526031815260200180615c876031913960400191505060405180910390fd5b611ecb614323565b565b600080600080600080611ee28a8a8a8a6146e8565b925092509250826011811115611ef457fe5b95509093509150505b9450945094915050565b6001600160a01b0383166000908152600b602052604081205460ff1615611f66576040805162461bcd60e51b815260206004820152600e60248201526d1b5a5b9d081a5cc81c185d5cd95960921b604482015290519081900360640190fd5b6001600160a01b03841660009081526009602052604090205460ff16611f905760095b9050611acb565b611f9984614a20565b611fa584846000614c9e565b6000949350505050565b600080546001600160a01b03163314611fd557611fce6001600b614e96565b9050611a20565b6006805490839055604080518281526020810185905281517faeba5a6c40a8ac138134bff1aaa65debf25971188a58804bad717f82f0ec1316929181900390910190a16000611acb565b8015801561202d5750600082115b15611e5a576040805162461bcd60e51b815260206004820152601160248201527072656465656d546f6b656e73207a65726f60781b604482015290519081900360640190fd5b600d818154811061208057fe5b6000918252602090912001546001600160a01b0316905081565b600080546001600160a01b031633146120b957611fce60016010614e96565b600480546001600160a01b038481166001600160a01b0319831681179093556040805191909216808252602082019390935281517fd52b2b9b7e9ee655fcb95d2e5b9e0c9f69e7ef2b8e9d2d0ea78402d576d22e22929181900390910190a16000611acb565b6121276141cd565b612178576040805162461bcd60e51b815260206004820152601d60248201527f6f6e6c792061646d696e2063616e2073657420636f6d70207370656564000000604482015290519081900360640190fd5b6121818261285e565b806121a0576001600160a01b0382166000908152601860205260408120555b6121a8611e60565b6001600160a01b03831660008181526018602090815260408083209490945560178152908390208490558251848152925191927f386537fa92edc3319af95f1f904dcf1900021e4f3f4e08169a577a09076e66b3929081900390910190a25050565b611575565b6000806000806000806122268760008060006146e8565b92509250925082601181111561223857fe5b97919650945092505050565b600080546001600160a01b0316331461226357611fce60016013614e96565b600a80546001600160a01b038481166001600160a01b0319831617928390556040805192821680845293909116602083015280517f0613b6ee6a04f0d09f390e4d9318894b9f6ac7fd83897cd8d18896ba579c401e9281900390910190a16000611acb565b6001600160a01b03851660009081526009602052604081205460ff16158061230957506001600160a01b03851660009081526009602052604090205460ff16155b156123185760095b9050612424565b60008061232485614efc565b9193509091506000905082601181111561233a57fe5b146123545781601181111561234b57fe5b92505050612424565b8061236057600361234b565b6000886001600160a01b03166395dd9193876040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b1580156123b857600080fd5b505afa1580156123cc573d6000803e3d6000fd5b505050506040513d60208110156123e257600080fd5b5051604080516020810190915260055481529091506000906124049083614f1c565b90508086111561241b576011945050505050612424565b60009450505050505b95945050505050565b6000546001600160a01b031633148061245057506015546001600160a01b031633145b61248b5760405162461bcd60e51b8152600401808060200182810382526035815260200180615d056035913960400191505060405180910390fd5b8281811580159061249b57508082145b6124dc576040805162461bcd60e51b815260206004820152600d60248201526c1a5b9d985b1a59081a5b9c1d5d609a1b604482015290519081900360640190fd5b60005b828110156125b4578484828181106124f357fe5b905060200201356016600089898581811061250a57fe5b905060200201356001600160a01b03166001600160a01b03166001600160a01b031681526020019081526020016000208190555086868281811061254a57fe5b905060200201356001600160a01b03166001600160a01b03167f6f1951b2aad10f3fc81b86d91105b413a5b3f847a34bbc5ce1904201b14438f686868481811061259057fe5b905060200201356040518082815260200191505060405180910390a26001016124df565b50505050505050565b60005b83518110156116eb5760008482815181106125d757fe5b6020908102919091018101516001600160a01b0381166000908152600990925260409091205490915060ff1661264c576040805162461bcd60e51b81526020600482015260156024820152741b585c9ad95d081b5d5cdd081899481b1a5cdd1959605a1b604482015290519081900360640190fd5b600184151514156127145761265f615b9f565b6040518060200160405280836001600160a01b031663aa5af0fd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156126a357600080fd5b505afa1580156126b7573d6000803e3d6000fd5b505050506040513d60208110156126cd57600080fd5b5051905290506126dd8282613d5b565b60005b875181101561271157612709838983815181106126f957fe5b6020026020010151846001613fe3565b6001016126e0565b50505b6001831515141561275d5761272881614a20565b60005b865181101561275b576127538288838151811061274457fe5b60200260200101516001614c9e565b60010161272b565b505b506001016125c0565b61276e6141cd565b6127bf576040805162461bcd60e51b815260206004820152601f60248201527f6f6e6c792061646d696e2063616e206368616e676520636f6d70207261746500604482015290519081900360640190fd5b600e805490829055604080518281526020810184905281517fc227c9272633c3a307d9845bf2bc2509cefb20d655b5f3c1002d8e1e3f22c8b0929181900390910190a1611cab614323565b6010602052600090815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b600c6020526000908152604090205460ff1681565b600b6020526000908152604090205460ff1681565b6001600160a01b03811660009081526017602052604081205490612880611e60565b6001600160a01b038416600090815260186020526040812054919250906128a8908390614f3b565b90506000811180156128ba5750600083115b15611e5a5760006128cb8285614f75565b6001600160a01b038616600090815260146020526040812054919250906128f29083614fb7565b6001600160a01b0387166000908152601460209081526040808320939093556018905220849055505050505050565b66038d7ea4c6800081565b6004546001600160a01b031681565b600a54600160b01b900460ff1681565b6011602052600090815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b60096020526000908152604090208054600182015460039092015460ff91821692911683565b600a546000906001600160a01b03163314806129c157506000546001600160a01b031633145b6129fc5760405162461bcd60e51b8152600401808060200182810382526027815260200180615cb86027913960400191505060405180910390fd5b6000546001600160a01b0316331480612a1757506001821515145b612a61576040805162461bcd60e51b81526020600482015260166024820152756f6e6c792061646d696e2063616e20756e706175736560501b604482015290519081900360640190fd5b600a8054831515600160b01b810260ff60b01b1990921691909117909155604080516020810192909252808252600882820152672a3930b739b332b960c11b6060830152517fef159d9a32b2472e32b098f954f3ce62d232939f1c207070b584df1814de2de09181900360800190a15090565b6001600160a01b038082166000908152600960209081526040808320938616835260029093019052205460ff1692915050565b60075481565b60176020526000908152604090205481565b73c00e94cb662c3520282e6f5717214004a7f2688890565b600080546001600160a01b03163314612b5657611fce60016012614e96565b6001600160a01b03821660009081526009602052604090205460ff1615612b8357611fce600a6011614e96565b816001600160a01b031663fe9c44ae6040518163ffffffff1660e01b815260040160206040518083038186803b158015612bbc57600080fd5b505afa158015612bd0573d6000803e3d6000fd5b505050506040513d6020811015612be657600080fd5b5050604080516060810182526001808252600060208381018281528486018381526001600160a01b03891684526009909252949091209251835490151560ff19918216178455935191830191909155516003909101805491151591909216179055612c5082614fed565b604080516001600160a01b038416815290517fcf583bb0c569eb967f806b11601c4cb93c10310485c67add5f8362c2f212321f9181900360200190a1600092915050565b6ec097ce7bc90715b34b9f100000000081565b600e5481565b60608060086000846001600160a01b03166001600160a01b03168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015612d2957602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612d0b575b5093979650505050505050565b600a54600160b81b900460ff1681565b6060600d805480602002602001604051908101604052809291908181526020018280548015612d9e57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612d80575b5050505050905090565b601260209081526000928352604080842090915290825290205481565b6002546001600160a01b031681565b600a54600090600160b01b900460ff1615612e2b576040805162461bcd60e51b81526020600482015260126024820152711d1c985b9cd9995c881a5cc81c185d5cd95960721b604482015290519081900360640190fd5b6000612e388686856150cb565b90508015612e475790506117c2565b612e5086614a20565b612e5c86866000614c9e565b6117bc86856000614c9e565b60186020526000908152604090205481565b6060600082519050606081604051908082528060200260200182016040528015612eae578160200160208202803883390190505b50905060005b82811015612f09576000858281518110612eca57fe5b60200260200101519050612ede8133615177565b6011811115612ee957fe5b838381518110612ef557fe5b602090810291909101015250600101612eb4565b509392505050565b600480546040805163fc57d4df60e01b81526001600160a01b038781169482019490945290516000938493849391169163fc57d4df91602480820192602092909190829003018186803b158015612f6757600080fd5b505afa158015612f7b573d6000803e3d6000fd5b505050506040513d6020811015612f9157600080fd5b5051600480546040805163fc57d4df60e01b81526001600160a01b038a8116948201949094529051939450600093929091169163fc57d4df91602480820192602092909190829003018186803b158015612fea57600080fd5b505afa158015612ffe573d6000803e3d6000fd5b505050506040513d602081101561301457600080fd5b50519050811580613023575080155b1561303857600d935060009250613131915050565b6000866001600160a01b031663182df0f56040518163ffffffff1660e01b815260040160206040518083038186803b15801561307357600080fd5b505afa158015613087573d6000803e3d6000fd5b505050506040513d602081101561309d57600080fd5b5051905060006130ab615b9f565b6130b3615b9f565b6130bb615b9f565b6130e3604051806020016040528060065481525060405180602001604052808a81525061526d565b925061310b60405180602001604052808881525060405180602001604052808881525061526d565b915061311783836152ac565b9050613123818b614f1c565b600099509750505050505050505b935093915050565b601360209081526000928352604080842090915290825290205481565b60146020526000908152604090205481565b6131706141cd565b6131c1576040805162461bcd60e51b815260206004820152601e60248201527f6f6e6c792061646d696e2063616e2061646420636f6d70206d61726b65740000604482015290519081900360640190fd5b60005b81518110156131f1576131e98282815181106131dc57fe5b60200260200101516152e8565b6001016131c4565b506116d6614323565b600a54600090600160b81b900460ff161561324e576040805162461bcd60e51b815260206004820152600f60248201526e1cd95a5e99481a5cc81c185d5cd959608a1b604482015290519081900360640190fd5b6001600160a01b03861660009081526009602052604090205460ff16158061328f57506001600160a01b03851660009081526009602052604090205460ff16155b1561329b576009612311565b846001600160a01b0316635fe3b5676040518163ffffffff1660e01b815260040160206040518083038186803b1580156132d457600080fd5b505afa1580156132e8573d6000803e3d6000fd5b505050506040513d60208110156132fe57600080fd5b505160408051635fe3b56760e01b815290516001600160a01b0392831692891691635fe3b567916004808301926020929190829003018186803b15801561334457600080fd5b505afa158015613358573d6000803e3d6000fd5b505050506040513d602081101561336e57600080fd5b50516001600160a01b031614613385576002612311565b61338e86614a20565b61339a86846000614c9e565b6133a686856000614c9e565b60009695505050505050565b6001600160a01b0383166000908152600c602052604081205460ff1615613413576040805162461bcd60e51b815260206004820152601060248201526f189bdc9c9bddc81a5cc81c185d5cd95960821b604482015290519081900360640190fd5b6001600160a01b03841660009081526009602052604090205460ff1661343a576009611f89565b6001600160a01b038085166000908152600960209081526040808320938716835260029093019052205460ff1661352a57336001600160a01b038516146134c0576040805162461bcd60e51b815260206004820152601560248201527439b2b73232b91036bab9ba1031329031aa37b5b2b760591b604482015290519081900360640190fd5b60006134cc3385615177565b905060008160118111156134dc57fe5b146134f5578060118111156134ed57fe5b915050611acb565b6001600160a01b038086166000908152600960209081526040808320938816835260029093019052205460ff1661352857fe5b505b600480546040805163fc57d4df60e01b81526001600160a01b03888116948201949094529051929091169163fc57d4df91602480820192602092909190829003018186803b15801561357b57600080fd5b505afa15801561358f573d6000803e3d6000fd5b505050506040513d60208110156135a557600080fd5b50516135b257600d611f89565b6001600160a01b038416600090815260166020526040902054801561369f576000856001600160a01b03166347bd37186040518163ffffffff1660e01b815260040160206040518083038186803b15801561360c57600080fd5b505afa158015613620573d6000803e3d6000fd5b505050506040513d602081101561363657600080fd5b5051905060006136468286614fb7565b905082811061369c576040805162461bcd60e51b815260206004820152601960248201527f6d61726b657420626f72726f7720636170207265616368656400000000000000604482015290519081900360640190fd5b50505b6000806136af86886000886146e8565b919350909150600090508260118111156136c557fe5b146136e0578160118111156136d657fe5b9350505050611acb565b80156136ed5760046136d6565b6136f5615b9f565b6040518060200160405280896001600160a01b031663aa5af0fd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561373957600080fd5b505afa15801561374d573d6000803e3d6000fd5b505050506040513d602081101561376357600080fd5b5051905290506137738882613d5b565b6137808888836000613fe3565b600098975050505050505050565b600860205281600052604060002081815481106137a757fe5b6000918252602090912001546001600160a01b03169150829050565b6003546001600160a01b031681565b600080546001600160a01b031633146137f8576137f160016006614e96565b9050611512565b6001600160a01b0383166000908152600960205260409020805460ff1661382d5761382560096007614e96565b915050611512565b613835615b9f565b50604080516020810190915283815261384c615b9f565b506040805160208101909152670c7d713b49da0000815261386d8183615603565b156138885761387e60066008614e96565b9350505050611512565b84158015906139115750600480546040805163fc57d4df60e01b81526001600160a01b038a8116948201949094529051929091169163fc57d4df91602480820192602092909190829003018186803b1580156138e357600080fd5b505afa1580156138f7573d6000803e3d6000fd5b505050506040513d602081101561390d57600080fd5b5051155b156139225761387e600d6009614e96565b60018301805490869055604080516001600160a01b03891681526020810183905280820188905290517f70483e6592cd5182d45ac970e05bc62cdcc90e9d8ef2c2dbe686cf383bcd7fc59181900360600190a16000979650505050505050565b600a54600160a81b900460ff1681565b60055481565b6116d681600d8054806020026020016040519081016040528092919081815260200182805480156139f257602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116139d4575b5050505050611518565b600080613a0a8585856150cb565b90508015613a19579050611acb565b613a2285614a20565b613a2e85856000614c9e565b600095945050505050565b6000808290506000806000836001600160a01b031663c37f68e2336040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060806040518083038186803b158015613a9a57600080fd5b505afa158015613aae573d6000803e3d6000fd5b505050506040513d6080811015613ac457600080fd5b508051602082015160409092015190945090925090508215613b175760405162461bcd60e51b8152600401808060200182810382526025815260200180615d3a6025913960400191505060405180910390fd5b8015613b3457613b29600c6002614e96565b945050505050611a20565b6000613b418733856150cb565b90508015613b6257613b56600e60038361560a565b95505050505050611a20565b6001600160a01b0385166000908152600960209081526040808320338452600281019092529091205460ff16613ba15760009650505050505050611a20565b3360009081526002820160209081526040808320805460ff191690556008825291829020805483518184028101840190945280845260609392830182828015613c1357602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311613bf5575b5050835193945083925060009150505b82811015613c6857896001600160a01b0316848281518110613c4157fe5b60200260200101516001600160a01b03161415613c6057809150613c68565b600101613c23565b50818110613c7257fe5b336000908152600860205260409020805481906000198101908110613c9357fe5b9060005260206000200160009054906101000a90046001600160a01b0316818381548110613cbd57fe5b600091825260209091200180546001600160a01b0319166001600160a01b03929092169190911790558054613cf6826000198301615bb2565b50604080516001600160a01b038c16815233602082015281517fe699a64c18b07ac5b7301aa273f36a2287239eb9501d81950672794afba29a0d929181900390910190a160009c9b505050505050505050505050565b6000546001600160a01b031681565b6001600160a01b0382166000908152601160209081526040808320600f9092528220549091613d88611e60565b8354909150600090613da8908390600160e01b900463ffffffff16614f3b565b9050600081118015613dba5750600083115b15613f89576000613e2f876001600160a01b03166347bd37186040518163ffffffff1660e01b815260040160206040518083038186803b158015613dfd57600080fd5b505afa158015613e11573d6000803e3d6000fd5b505050506040513d6020811015613e2757600080fd5b505187615670565b90506000613e3d8386614f75565b9050613e47615b9f565b60008311613e645760405180602001604052806000815250613e6e565b613e6e828461568e565b9050613e78615b9f565b604080516020810190915288546001600160e01b03168152613e9a90836156c3565b90506040518060400160405280613eea83600001516040518060400160405280601a81526020017f6e657720696e64657820657863656564732032323420626974730000000000008152506156e8565b6001600160e01b03168152602001613f25886040518060400160405280601c8152602001600080516020615d5f833981519152815250615782565b63ffffffff9081169091526001600160a01b038c166000908152601160209081526040909120835181549490920151909216600160e01b026001600160e01b039182166001600160e01b0319909416939093171691909117905550611e6592505050565b8015611e6557613fbc826040518060400160405280601c8152602001600080516020615d5f833981519152815250615782565b845463ffffffff91909116600160e01b026001600160e01b03909116178455505050505050565b6001600160a01b0384166000908152601160205260409020614003615b9f565b50604080516020810190915281546001600160e01b03168152614024615b9f565b5060408051602080820183526001600160a01b03808a16600090815260138352848120918a16808252828452948120805485528651959091529152919091558051156125b457614072615b9f565b61407c83836157d7565b9050600061410b896001600160a01b03166395dd91938a6040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b1580156140d957600080fd5b505afa1580156140ed573d6000803e3d6000fd5b505050506040513d602081101561410357600080fd5b505188615670565b9050600061411982846157fc565b6001600160a01b038a16600090815260146020526040812054919250906141409083614fb7565b90506141618a828a6141595766038d7ea4c6800061415c565b60005b61582b565b6001600160a01b03808c1660008181526014602090815260409182902094909455895181518781529485015280519193928f16927f1fc3ecc087d8d2d15e23d0032af5a47059c3892d003d8e139fdcb6bb327c99a6929081900390910190a35050505050505050505050565b600080546001600160a01b03163314806141f157506002546001600160a01b031633145b905090565b600080614201612b1f565b604080516370a0823160e01b815230600482015290519192506000916001600160a01b038416916370a08231916024808301926020929190829003018186803b15801561424d57600080fd5b505afa158015614261573d6000803e3d6000fd5b505050506040513d602081101561427757600080fd5b5051905080841161431a57816001600160a01b031663a9059cbb86866040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b1580156142e257600080fd5b505af11580156142f6573d6000803e3d6000fd5b505050506040513d602081101561430c57600080fd5b506000935061151292505050565b50919392505050565b6060600d80548060200260200160405190810160405280929190818152602001828054801561437b57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161435d575b50939450600093505050505b815181101561444157600082828151811061439e57fe5b602002602001015190506143b0615b9f565b6040518060200160405280836001600160a01b031663aa5af0fd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156143f457600080fd5b505afa158015614408573d6000803e3d6000fd5b505050506040513d602081101561441e57600080fd5b50519052905061442d82614a20565b6144378282613d5b565b5050600101614387565b5061444a615b9f565b6040518060200160405280600081525090506060825160405190808252806020026020018201604052801561449957816020015b614486615b9f565b81526020019060019003908161447e5790505b50905060005b835181101561461f5760008482815181106144b657fe5b6020908102919091018101516001600160a01b0381166000908152600990925260409091206003015490915060ff1615614616576144f2615b9f565b60408051602080820180845260045463fc57d4df60e01b9091526001600160a01b03868116602485015293519293849391169163fc57d4df916044808601929190818703018186803b15801561454757600080fd5b505afa15801561455b573d6000803e3d6000fd5b505050506040513d602081101561457157600080fd5b50519052905061457f615b9f565b6145ed82846001600160a01b03166347bd37186040518163ffffffff1660e01b815260040160206040518083038186803b1580156145bc57600080fd5b505afa1580156145d0573d6000803e3d6000fd5b505050506040513d60208110156145e657600080fd5b5051615970565b9050808585815181106145fc57fe5b602002602001018190525061461186826156c3565b955050505b5060010161449f565b5060005b8351811015611e5a576000600d828154811061463b57fe5b600091825260208220015485516001600160a01b039091169250614660576000614688565b614688600e5461468386868151811061467557fe5b6020026020010151886152ac565b615991565b6001600160a01b0383166000818152600f60209081526040918290208490558151848152915193945091927f2ab93f65628379309f36cb125e90d7c902454a545c4f8b8cb0794af75c24b807929181900390910190a25050600101614623565b60008060006146f5615bd6565b6001600160a01b0388166000908152600860209081526040808320805482518185028101850190935280835260609383018282801561475d57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161473f575b50939450600093505050505b81518110156149e157600082828151811061478057fe5b60200260200101519050806001600160a01b031663c37f68e28d6040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060806040518083038186803b1580156147e057600080fd5b505afa1580156147f4573d6000803e3d6000fd5b505050506040513d608081101561480a57600080fd5b508051602082015160408084015160609485015160808b015293890193909352918701919091529350831561484f5750600f965060009550859450611efd9350505050565b60408051602080820183526001600160a01b0380851660008181526009845285902060010154845260c08a01939093528351808301855260808a0151815260e08a015260048054855163fc57d4df60e01b815291820194909452935192169263fc57d4df9260248083019392829003018186803b1580156148cf57600080fd5b505afa1580156148e3573d6000803e3d6000fd5b505050506040513d60208110156148f957600080fd5b505160a0860181905261491c5750600d965060009550859450611efd9350505050565b604080516020810190915260a0860151815261010086015260c085015160e08601516149569161494b9161526d565b86610100015161526d565b6101208601819052604086015186516149709291906159aa565b85526101008501516060860151602087015161498d9291906159aa565b60208601526001600160a01b03818116908c1614156149d8576149ba8561012001518b87602001516159aa565b602086018190526101008601516149d2918b906159aa565b60208601525b50600101614769565b50602083015183511115614a075750506020810151905160009450039150829050611efd565b5050805160209091015160009450849350039050611efd565b6001600160a01b0381166000908152601060209081526040808320600f9092528220549091614a4d611e60565b8354909150600090614a6d908390600160e01b900463ffffffff16614f3b565b9050600081118015614a7f5750600083115b15614c45576000856001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015614abf57600080fd5b505afa158015614ad3573d6000803e3d6000fd5b505050506040513d6020811015614ae957600080fd5b505190506000614af98386614f75565b9050614b03615b9f565b60008311614b205760405180602001604052806000815250614b2a565b614b2a828461568e565b9050614b34615b9f565b604080516020810190915288546001600160e01b03168152614b5690836156c3565b90506040518060400160405280614ba683600001516040518060400160405280601a81526020017f6e657720696e64657820657863656564732032323420626974730000000000008152506156e8565b6001600160e01b03168152602001614be1886040518060400160405280601c8152602001600080516020615d5f833981519152815250615782565b63ffffffff9081169091526001600160a01b038b166000908152601060209081526040909120835181549490920151909216600160e01b026001600160e01b039182166001600160e01b03199094169390931716919091179055506116eb92505050565b80156116eb57614c78826040518060400160405280601c8152602001600080516020615d5f833981519152815250615782565b845463ffffffff91909116600160e01b026001600160e01b039091161784555050505050565b6001600160a01b0383166000908152601060205260409020614cbe615b9f565b50604080516020810190915281546001600160e01b03168152614cdf615b9f565b5060408051602080820183526001600160a01b03808916600090815260128352848120918916808252828452948120805485528651959091529152919091558051158015614d2d5750815115155b15614d45576ec097ce7bc90715b34b9f100000000081525b614d4d615b9f565b614d5783836157d7565b90506000876001600160a01b03166370a08231886040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015614db157600080fd5b505afa158015614dc5573d6000803e3d6000fd5b505050506040513d6020811015614ddb57600080fd5b505190506000614deb82846157fc565b6001600160a01b03891660009081526014602052604081205491925090614e129083614fb7565b9050614e2b89828a6141595766038d7ea4c6800061415c565b6001600160a01b03808b1660008181526014602090815260409182902094909455895181518781529485015280519193928e16927f2caecd17d02f56fa897705dcc740da2d237c373f70686f4e0d9bd3bf0400ea7a929081900390910190a350505050505050505050565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0836011811115614ec557fe5b836013811115614ed157fe5b604080519283526020830191909152600082820152519081900360600190a1826011811115611acb57fe5b6000806000614f0f8460008060006146e8565b9250925092509193909250565b6000614f26615b9f565b614f308484615970565b90506117c2816159d2565b6000611acb8383604051806040016040528060158152602001747375627472616374696f6e20756e646572666c6f7760581b8152506159e1565b6000611acb83836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f77000000000000000000815250615a3b565b6000611acb8383604051806040016040528060118152602001706164646974696f6e206f766572666c6f7760781b815250615aba565b60005b600d5481101561507857816001600160a01b0316600d828154811061501157fe5b6000918252602090912001546001600160a01b03161415615070576040805162461bcd60e51b81526020600482015260146024820152731b585c9ad95d08185b1c9958591e48185919195960621b604482015290519081900360640190fd5b600101614ff0565b50600d80546001810182556000919091527fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb50180546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b03831660009081526009602052604081205460ff166150f2576009611f89565b6001600160a01b038085166000908152600960209081526040808320938716835260029093019052205460ff1661512a576000611f89565b60008061513a85878660006146e8565b9193509091506000905082601181111561515057fe5b1461516a5781601181111561516157fe5b92505050611acb565b80156133a6576004615161565b6001600160a01b0382166000908152600960205260408120805460ff166151a2576009915050611512565b6001600160a01b038316600090815260028201602052604090205460ff161515600114156151d4576000915050611512565b6001600160a01b0380841660008181526002840160209081526040808320805460ff19166001908117909155600883528184208054918201815584529282902090920180549489166001600160a01b031990951685179055815193845283019190915280517f3ab23ab0d51cccc0c3085aec51f99228625aa1a922b3a8ca89a26b0f2027a1a59281900390910190a15060009392505050565b615275615b9f565b6040518060200160405280670de0b6b3a764000061529b86600001518660000151614f75565b816152a257fe5b0490529392505050565b6152b4615b9f565b60405180602001604052806152df6152d88660000151670de0b6b3a7640000614f75565b8551615b0f565b90529392505050565b6001600160a01b0381166000908152600960205260409020805460ff16151560011461535b576040805162461bcd60e51b815260206004820152601960248201527f636f6d70206d61726b6574206973206e6f74206c697374656400000000000000604482015290519081900360640190fd5b600381015460ff16156153b5576040805162461bcd60e51b815260206004820152601960248201527f636f6d70206d61726b657420616c726561647920616464656400000000000000604482015290519081900360640190fd5b60038101805460ff19166001908117909155604080516001600160a01b0385168152602081019290925280517f93c1f3e36ed71139f466a4ce8c9751790e2e33f5afb2df0dcfb3aeabe55d5aa29281900390910190a16001600160a01b0382166000908152601060205260409020546001600160e01b031615801561545d57506001600160a01b038216600090815260106020526040902054600160e01b900463ffffffff16155b1561551a5760405180604001604052806ec097ce7bc90715b34b9f10000000006001600160e01b031681526020016154bf615496611e60565b6040518060400160405280601c8152602001600080516020615d5f833981519152815250615782565b63ffffffff9081169091526001600160a01b0384166000908152601060209081526040909120835181549490920151909216600160e01b026001600160e01b039182166001600160e01b031990941693909317169190911790555b6001600160a01b0382166000908152601160205260409020546001600160e01b031615801561556c57506001600160a01b038216600090815260116020526040902054600160e01b900463ffffffff16155b15611cab5760405180604001604052806ec097ce7bc90715b34b9f10000000006001600160e01b031681526020016155a5615496611e60565b63ffffffff9081169091526001600160a01b0384166000908152601160209081526040909120835181549490920151909216600160e01b026001600160e01b039182166001600160e01b031990941693909317169190911790555050565b5190511090565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa084601181111561563957fe5b84601381111561564557fe5b604080519283526020830191909152818101859052519081900360600190a18360118111156117c257fe5b6000611acb61568784670de0b6b3a7640000614f75565b8351615b0f565b615696615b9f565b60405180602001604052806152df6156bd866ec097ce7bc90715b34b9f1000000000614f75565b85615b0f565b6156cb615b9f565b60405180602001604052806152df85600001518560000151614fb7565b600081600160e01b841061577a5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561573f578181015183820152602001615727565b50505050905090810190601f16801561576c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b509192915050565b600081600160201b841061577a5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561573f578181015183820152602001615727565b6157df615b9f565b60405180602001604052806152df85600001518560000151614f3b565b60006ec097ce7bc90715b34b9f100000000061581c848460000151614f75565b8161582357fe5b049392505050565b600081831015801561583d5750600083115b1561596857600061584c612b1f565b604080516370a0823160e01b815230600482015290519192506000916001600160a01b038416916370a08231916024808301926020929190829003018186803b15801561589857600080fd5b505afa1580156158ac573d6000803e3d6000fd5b505050506040513d60208110156158c257600080fd5b5051905080851161596557816001600160a01b031663a9059cbb87876040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561592d57600080fd5b505af1158015615941573d6000803e3d6000fd5b505050506040513d602081101561595757600080fd5b5060009350611acb92505050565b50505b509092915050565b615978615b9f565b60405180602001604052806152df856000015185614f75565b6000670de0b6b3a764000061581c848460000151614f75565b60006159b4615b9f565b6159be8585615970565b90506124246159cc826159d2565b84614fb7565b51670de0b6b3a7640000900490565b60008184841115615a335760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561573f578181015183820152602001615727565b505050900390565b6000831580615a48575082155b15615a5557506000611acb565b83830283858281615a6257fe5b04148390615ab15760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561573f578181015183820152602001615727565b50949350505050565b60008383018285821015615ab15760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561573f578181015183820152602001615727565b6000611acb83836040518060400160405280600e81526020016d646976696465206279207a65726f60901b81525060008183615b8c5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561573f578181015183820152602001615727565b50828481615b9657fe5b04949350505050565b6040518060200160405280600081525090565b81548183558181111561157557600083815260209020611575918101908301615c40565b604051806101400160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001615c14615b9f565b8152602001615c21615b9f565b8152602001615c2e615b9f565b8152602001615c3b615b9f565b905290565b611e6291905b80821115615c5a5760008155600101615c46565b509056fe63616e6e6f742070617573652061206d61726b65742074686174206973206e6f74206c69737465646f6e6c792065787465726e616c6c79206f776e6564206163636f756e7473206d61792072656672657368207370656564736f6e6c7920706175736520677561726469616e20616e642061646d696e2063616e2070617573656f6e6c792061646d696e2063616e2073657420626f72726f772063617020677561726469616e6f6e6c792061646d696e206f7220626f72726f772063617020677561726469616e2063616e2073657420626f72726f772063617073657869744d61726b65743a206765744163636f756e74536e617073686f74206661696c6564626c6f636b206e756d62657220657863656564732033322062697473000000006f6e6c7920756e6974726f6c6c65722061646d696e2063616e206368616e676520627261696e73a265627a7a723158201fcbfb50061d543a7cf2aaf83232afde0ab1f39e2fd66e342b3200e33a1f6d3a64736f6c63430005100032", + "metadata": "{\"compiler\":{\"version\":\"0.5.16+commit.9c3226ce\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"action\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"pauseState\",\"type\":\"bool\"}],\"name\":\"ActionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"action\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"pauseState\",\"type\":\"bool\"}],\"name\":\"ActionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"CompGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSpeed\",\"type\":\"uint256\"}],\"name\":\"CompSpeedUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"contributor\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSpeed\",\"type\":\"uint256\"}],\"name\":\"ContributorCompSpeedUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compBorrowIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedBorrowerComp\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"supplier\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compSupplyIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedSupplierComp\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isComped\",\"type\":\"bool\"}],\"name\":\"MarketComped\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketEntered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketExited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"MarketListed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newBorrowCap\",\"type\":\"uint256\"}],\"name\":\"NewBorrowCap\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldBorrowCapGuardian\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newBorrowCapGuardian\",\"type\":\"address\"}],\"name\":\"NewBorrowCapGuardian\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCloseFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCloseFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCollateralFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCollateralFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCompRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCompRate\",\"type\":\"uint256\"}],\"name\":\"NewCompRate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldLiquidationIncentiveMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"NewLiquidationIncentive\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldPauseGuardian\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"NewPauseGuardian\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"oldPriceOracle\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"newPriceOracle\",\"type\":\"address\"}],\"name\":\"NewPriceOracle\",\"type\":\"event\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"_addCompMarkets\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract Unitroller\",\"name\":\"unitroller\",\"type\":\"address\"}],\"name\":\"_become\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"_dropCompMarket\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"_grantComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"newBorrowCapGuardian\",\"type\":\"address\"}],\"name\":\"_setBorrowCapGuardian\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setBorrowPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCloseFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCollateralFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"compRate_\",\"type\":\"uint256\"}],\"name\":\"_setCompRate\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"contributor\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"compSpeed\",\"type\":\"uint256\"}],\"name\":\"_setContributorCompSpeed\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"_setLiquidationIncentive\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"cTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"newBorrowCaps\",\"type\":\"uint256[]\"}],\"name\":\"_setMarketBorrowCaps\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setMintPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"_setPauseGuardian\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"newOracle\",\"type\":\"address\"}],\"name\":\"_setPriceOracle\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setSeizePaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setTransferPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"_supportMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allMarkets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"borrowCapGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"checkMembership\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"},{\"internalType\":\"contract CToken[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"holders\",\"type\":\"address[]\"},{\"internalType\":\"contract CToken[]\",\"name\":\"cTokens\",\"type\":\"address[]\"},{\"internalType\":\"bool\",\"name\":\"borrowers\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"suppliers\",\"type\":\"bool\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compAccrued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compBorrowState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compBorrowerIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compClaimThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compContributorSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compInitialIndex\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSupplierIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSupplyState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"enterMarkets\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenAddress\",\"type\":\"address\"}],\"name\":\"exitMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getAllMarkets\",\"outputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAssetsIn\",\"outputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getCompAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenModify\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"getHypotheticalAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"isComptroller\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"lastContributorBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateCalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"liquidationIncentiveMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"markets\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isComped\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"mintAmount\",\"type\":\"uint256\"}],\"name\":\"mintAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualMintAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"mintTokens\",\"type\":\"uint256\"}],\"name\":\"mintVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"refreshCompSpeeds\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"repayBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowerIndex\",\"type\":\"uint256\"}],\"name\":\"repayBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"seizeGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"transferGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"contributor\",\"type\":\"address\"}],\"name\":\"updateContributorRewards\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Compound\",\"methods\":{\"_addCompMarkets(address[])\":{\"params\":{\"cTokens\":\"The addresses of the markets to add\"}},\"_dropCompMarket(address)\":{\"params\":{\"cToken\":\"The address of the market to drop\"}},\"_grantComp(address,uint256)\":{\"details\":\"Note: If there is not enough COMP, we do not perform the transfer all.\",\"params\":{\"amount\":\"The amount of COMP to (possibly) transfer\",\"recipient\":\"The address of the recipient to transfer COMP to\"}},\"_setBorrowCapGuardian(address)\":{\"params\":{\"newBorrowCapGuardian\":\"The address of the new Borrow Cap Guardian\"}},\"_setCloseFactor(uint256)\":{\"details\":\"Admin function to set closeFactor\",\"params\":{\"newCloseFactorMantissa\":\"New close factor, scaled by 1e18\"},\"return\":\"uint 0=success, otherwise a failure\"},\"_setCollateralFactor(address,uint256)\":{\"details\":\"Admin function to set per-market collateralFactor\",\"params\":{\"cToken\":\"The market to set the factor on\",\"newCollateralFactorMantissa\":\"The new collateral factor, scaled by 1e18\"},\"return\":\"uint 0=success, otherwise a failure. (See ErrorReporter for details)\"},\"_setCompRate(uint256)\":{\"params\":{\"compRate_\":\"The amount of COMP wei per block to distribute\"}},\"_setContributorCompSpeed(address,uint256)\":{\"params\":{\"compSpeed\":\"New COMP speed for contributor\",\"contributor\":\"The contributor whose COMP speed to update\"}},\"_setLiquidationIncentive(uint256)\":{\"details\":\"Admin function to set liquidationIncentive\",\"params\":{\"newLiquidationIncentiveMantissa\":\"New liquidationIncentive scaled by 1e18\"},\"return\":\"uint 0=success, otherwise a failure. (See ErrorReporter for details)\"},\"_setMarketBorrowCaps(address[],uint256[])\":{\"details\":\"Admin or borrowCapGuardian function to set the borrow caps. A borrow cap of 0 corresponds to unlimited borrowing.\",\"params\":{\"cTokens\":\"The addresses of the markets (tokens) to change the borrow caps for\",\"newBorrowCaps\":\"The new borrow cap values in underlying to be set. A value of 0 corresponds to unlimited borrowing.\"}},\"_setPauseGuardian(address)\":{\"params\":{\"newPauseGuardian\":\"The address of the new Pause Guardian\"},\"return\":\"uint 0=success, otherwise a failure. (See enum Error for details)\"},\"_setPriceOracle(address)\":{\"details\":\"Admin function to set a new price oracle\",\"return\":\"uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\"},\"_supportMarket(address)\":{\"details\":\"Admin function to set isListed and add support for the market\",\"params\":{\"cToken\":\"The address of the market (token) to list\"},\"return\":\"uint 0=success, otherwise a failure. (See enum Error for details)\"},\"borrowAllowed(address,address,uint256)\":{\"params\":{\"borrowAmount\":\"The amount of underlying the account would borrow\",\"borrower\":\"The account which would borrow the asset\",\"cToken\":\"The market to verify the borrow against\"},\"return\":\"0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"borrowVerify(address,address,uint256)\":{\"params\":{\"borrowAmount\":\"The amount of the underlying asset requested to borrow\",\"borrower\":\"The address borrowing the underlying\",\"cToken\":\"Asset whose underlying is being borrowed\"}},\"checkMembership(address,address)\":{\"params\":{\"account\":\"The address of the account to check\",\"cToken\":\"The cToken to check\"},\"return\":\"True if the account is in the asset, otherwise false.\"},\"claimComp(address)\":{\"params\":{\"holder\":\"The address to claim COMP for\"}},\"claimComp(address,address[])\":{\"params\":{\"cTokens\":\"The list of markets to claim COMP in\",\"holder\":\"The address to claim COMP for\"}},\"claimComp(address[],address[],bool,bool)\":{\"params\":{\"borrowers\":\"Whether or not to claim COMP earned by borrowing\",\"cTokens\":\"The list of markets to claim COMP in\",\"holders\":\"The addresses to claim COMP for\",\"suppliers\":\"Whether or not to claim COMP earned by supplying\"}},\"enterMarkets(address[])\":{\"params\":{\"cTokens\":\"The list of addresses of the cToken markets to be enabled\"},\"return\":\"Success indicator for whether each corresponding market was entered\"},\"exitMarket(address)\":{\"details\":\"Sender must not have an outstanding borrow balance in the asset, or be providing necessary collateral for an outstanding borrow.\",\"params\":{\"cTokenAddress\":\"The address of the asset to be removed\"},\"return\":\"Whether or not the account successfully exited the market\"},\"getAccountLiquidity(address)\":{\"return\":\"(possible error code (semi-opaque), account liquidity in excess of collateral requirements, account shortfall below collateral requirements)\"},\"getAllMarkets()\":{\"details\":\"The automatic getter may be used to access an individual market.\",\"return\":\"The list of market addresses\"},\"getAssetsIn(address)\":{\"params\":{\"account\":\"The address of the account to pull assets for\"},\"return\":\"A dynamic list with the assets the account has entered\"},\"getCompAddress()\":{\"return\":\"The address of COMP\"},\"getHypotheticalAccountLiquidity(address,address,uint256,uint256)\":{\"params\":{\"account\":\"The account to determine liquidity for\",\"borrowAmount\":\"The amount of underlying to hypothetically borrow\",\"cTokenModify\":\"The market to hypothetically redeem/borrow in\",\"redeemTokens\":\"The number of tokens to hypothetically redeem\"},\"return\":\"(possible error code (semi-opaque), hypothetical account liquidity in excess of collateral requirements, hypothetical account shortfall below collateral requirements)\"},\"liquidateBorrowAllowed(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"repayAmount\":\"The amount of underlying being repaid\"}},\"liquidateBorrowVerify(address,address,address,address,uint256,uint256)\":{\"params\":{\"actualRepayAmount\":\"The amount of underlying being repaid\",\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\"}},\"liquidateCalculateSeizeTokens(address,address,uint256)\":{\"details\":\"Used in liquidation (called in cToken.liquidateBorrowFresh)\",\"params\":{\"actualRepayAmount\":\"The amount of cTokenBorrowed underlying to convert into cTokenCollateral tokens\",\"cTokenBorrowed\":\"The address of the borrowed cToken\",\"cTokenCollateral\":\"The address of the collateral cToken\"},\"return\":\"(errorCode, number of cTokenCollateral tokens to be seized in a liquidation)\"},\"mintAllowed(address,address,uint256)\":{\"params\":{\"cToken\":\"The market to verify the mint against\",\"mintAmount\":\"The amount of underlying being supplied to the market in exchange for tokens\",\"minter\":\"The account which would get the minted tokens\"},\"return\":\"0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"mintVerify(address,address,uint256,uint256)\":{\"params\":{\"actualMintAmount\":\"The amount of the underlying asset being minted\",\"cToken\":\"Asset being minted\",\"mintTokens\":\"The number of tokens being minted\",\"minter\":\"The address minting the tokens\"}},\"redeemAllowed(address,address,uint256)\":{\"params\":{\"cToken\":\"The market to verify the redeem against\",\"redeemTokens\":\"The number of cTokens to exchange for the underlying asset in the market\",\"redeemer\":\"The account which would redeem the tokens\"},\"return\":\"0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"redeemVerify(address,address,uint256,uint256)\":{\"params\":{\"cToken\":\"Asset being redeemed\",\"redeemAmount\":\"The amount of the underlying asset being redeemed\",\"redeemTokens\":\"The number of tokens being redeemed\",\"redeemer\":\"The address redeeming the tokens\"}},\"repayBorrowAllowed(address,address,address,uint256)\":{\"params\":{\"borrower\":\"The account which would borrowed the asset\",\"cToken\":\"The market to verify the repay against\",\"payer\":\"The account which would repay the asset\",\"repayAmount\":\"The amount of the underlying asset the account would repay\"},\"return\":\"0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"repayBorrowVerify(address,address,address,uint256,uint256)\":{\"params\":{\"actualRepayAmount\":\"The amount of underlying being repaid\",\"borrower\":\"The address of the borrower\",\"cToken\":\"Asset being repaid\",\"payer\":\"The address repaying the borrow\"}},\"seizeAllowed(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"seizeTokens\":\"The number of collateral tokens to seize\"}},\"seizeVerify(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"seizeTokens\":\"The number of collateral tokens to seize\"}},\"transferAllowed(address,address,address,uint256)\":{\"params\":{\"cToken\":\"The market to verify the transfer against\",\"dst\":\"The account which receives the tokens\",\"src\":\"The account which sources the tokens\",\"transferTokens\":\"The number of cTokens to transfer\"},\"return\":\"0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"transferVerify(address,address,address,uint256)\":{\"params\":{\"cToken\":\"Asset being transferred\",\"dst\":\"The account which receives the tokens\",\"src\":\"The account which sources the tokens\",\"transferTokens\":\"The number of cTokens to transfer\"}},\"updateContributorRewards(address)\":{\"params\":{\"contributor\":\"The address to calculate contributor rewards for\"}}},\"title\":\"Compound's Comptroller Contract\"},\"userdoc\":{\"methods\":{\"_addCompMarkets(address[])\":{\"notice\":\"Add markets to compMarkets, allowing them to earn COMP in the flywheel\"},\"_dropCompMarket(address)\":{\"notice\":\"Remove a market from compMarkets, preventing it from earning COMP in the flywheel\"},\"_grantComp(address,uint256)\":{\"notice\":\"Transfer COMP to the recipient\"},\"_setBorrowCapGuardian(address)\":{\"notice\":\"Admin function to change the Borrow Cap Guardian\"},\"_setCloseFactor(uint256)\":{\"notice\":\"Sets the closeFactor used when liquidating borrows\"},\"_setCollateralFactor(address,uint256)\":{\"notice\":\"Sets the collateralFactor for a market\"},\"_setCompRate(uint256)\":{\"notice\":\"Set the amount of COMP distributed per block\"},\"_setContributorCompSpeed(address,uint256)\":{\"notice\":\"Set COMP speed for a single contributor\"},\"_setLiquidationIncentive(uint256)\":{\"notice\":\"Sets liquidationIncentive\"},\"_setMarketBorrowCaps(address[],uint256[])\":{\"notice\":\"Set the given borrow caps for the given cToken markets. Borrowing that brings total borrows to or above borrow cap will revert.\"},\"_setPauseGuardian(address)\":{\"notice\":\"Admin function to change the Pause Guardian\"},\"_setPriceOracle(address)\":{\"notice\":\"Sets a new price oracle for the comptroller\"},\"_supportMarket(address)\":{\"notice\":\"Add the market to the markets mapping and set it as listed\"},\"borrowAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to borrow the underlying asset of the given market\"},\"borrowVerify(address,address,uint256)\":{\"notice\":\"Validates borrow and reverts on rejection. May emit logs.\"},\"checkMembership(address,address)\":{\"notice\":\"Returns whether the given account is entered in the given asset\"},\"claimComp(address)\":{\"notice\":\"Claim all the comp accrued by holder in all markets\"},\"claimComp(address,address[])\":{\"notice\":\"Claim all the comp accrued by holder in the specified markets\"},\"claimComp(address[],address[],bool,bool)\":{\"notice\":\"Claim all comp accrued by the holders\"},\"enterMarkets(address[])\":{\"notice\":\"Add assets to be included in account liquidity calculation\"},\"exitMarket(address)\":{\"notice\":\"Removes asset from sender's account liquidity calculation\"},\"getAccountLiquidity(address)\":{\"notice\":\"Determine the current account liquidity wrt collateral requirements\"},\"getAllMarkets()\":{\"notice\":\"Return all of the markets\"},\"getAssetsIn(address)\":{\"notice\":\"Returns the assets an account has entered\"},\"getCompAddress()\":{\"notice\":\"Return the address of the COMP token\"},\"getHypotheticalAccountLiquidity(address,address,uint256,uint256)\":{\"notice\":\"Determine what the account liquidity would be if the given amounts were redeemed/borrowed\"},\"liquidateBorrowAllowed(address,address,address,address,uint256)\":{\"notice\":\"Checks if the liquidation should be allowed to occur\"},\"liquidateBorrowVerify(address,address,address,address,uint256,uint256)\":{\"notice\":\"Validates liquidateBorrow and reverts on rejection. May emit logs.\"},\"liquidateCalculateSeizeTokens(address,address,uint256)\":{\"notice\":\"Calculate number of tokens of collateral asset to seize given an underlying amount\"},\"mintAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to mint tokens in the given market\"},\"mintVerify(address,address,uint256,uint256)\":{\"notice\":\"Validates mint and reverts on rejection. May emit logs.\"},\"redeemAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to redeem tokens in the given market\"},\"redeemVerify(address,address,uint256,uint256)\":{\"notice\":\"Validates redeem and reverts on rejection. May emit logs.\"},\"refreshCompSpeeds()\":{\"notice\":\"Recalculate and update COMP speeds for all COMP markets\"},\"repayBorrowAllowed(address,address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to repay a borrow in the given market\"},\"repayBorrowVerify(address,address,address,uint256,uint256)\":{\"notice\":\"Validates repayBorrow and reverts on rejection. May emit logs.\"},\"seizeAllowed(address,address,address,address,uint256)\":{\"notice\":\"Checks if the seizing of assets should be allowed to occur\"},\"seizeVerify(address,address,address,address,uint256)\":{\"notice\":\"Validates seize and reverts on rejection. May emit logs.\"},\"transferAllowed(address,address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to transfer tokens in the given market\"},\"transferVerify(address,address,address,uint256)\":{\"notice\":\"Validates transfer and reverts on rejection. May emit logs.\"},\"updateContributorRewards(address)\":{\"notice\":\"Calculate additional accrued COMP for a contributor since last accrual\"}}}},\"settings\":{\"compilationTarget\":{\"contracts/ComptrollerG6.sol\":\"ComptrollerG6\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/CToken.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./CTokenInterfaces.sol\\\";\\nimport \\\"./ErrorReporter.sol\\\";\\nimport \\\"./Exponential.sol\\\";\\nimport \\\"./EIP20Interface.sol\\\";\\nimport \\\"./InterestRateModel.sol\\\";\\n\\n/**\\n * @title Compound's CToken Contract\\n * @notice Abstract base for CTokens\\n * @author Compound\\n */\\ncontract CToken is CTokenInterface, Exponential, TokenErrorReporter {\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_) public {\\n require(msg.sender == admin, \\\"only admin may initialize the market\\\");\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = getBlockNumber();\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Transfer `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = uint(-1);\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srcTokensNew;\\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, srcTokensNew) = 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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srcTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != uint(-1)) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n // unused function\\n // comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transfer(address dst, uint256 amount) external nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferFrom(address src, address dst, uint256 amount) external nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (-1 means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool) {\\n address src = msg.sender;\\n transferAllowances[src][spender] = amount;\\n emit Approval(src, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (-1 means infinite)\\n */\\n function allowance(address owner, address spender) external view returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external returns (uint) {\\n Exp memory exchangeRate = Exp({mantissa: exchangeRateCurrent()});\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n require(mErr == MathError.NO_ERROR, \\\"balance could not be calculated\\\");\\n return balance;\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view returns (uint, uint, uint, uint) {\\n uint cTokenBalance = accountTokens[account];\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), cTokenBalance, borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @dev Function to simply retrieve block number\\n * This exists mainly for inheriting test contracts to stub this result.\\n */\\n function getBlockNumber() internal view returns (uint) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this cToken\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view returns (uint) {\\n return interestRateModel.getBorrowRate(getCashPrior(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this cToken\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view returns (uint) {\\n return interestRateModel.getSupplyRate(getCashPrior(), totalBorrows, totalReserves, reserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n require(err == MathError.NO_ERROR, \\\"borrowBalanceStored: borrowBalanceStoredInternal failed\\\");\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return (error code, the calculated balance or 0 if error code is non-zero)\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the CToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n require(err == MathError.NO_ERROR, \\\"exchangeRateStored: exchangeRateStoredInternal failed\\\");\\n return result;\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the CToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return (error code, calculated exchange rate scaled by 1e18)\\n */\\n function exchangeRateStoredInternal() internal view returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows - totalReserves) / totalSupply\\n */\\n uint totalCash = getCashPrior();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Get cash balance of this cToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage.\\n */\\n function accrueInterest() public returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = getBlockNumber();\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = getCashPrior();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n require(mathErr == MathError.NO_ERROR, \\\"could not calculate block delta\\\");\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({mantissa: borrowRateMantissa}), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(Exp({mantissa: reserveFactorMantissa}), interestAccumulated, reservesPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives cTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n struct MintLocalVars {\\n Error err;\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives cTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, 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's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the cToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of cTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.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 cTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED\\\");\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\\");\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender redeems cTokens in exchange for the underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemTokens The number of cTokens to redeem into underlying\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemInternal(uint redeemTokens) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(msg.sender, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems cTokens in exchange for a specified amount of underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemAmount The amount of underlying to receive from redeeming cTokens\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemUnderlyingInternal(uint redeemAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(msg.sender, 0, redeemAmount);\\n }\\n\\n struct RedeemLocalVars {\\n Error err;\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n /**\\n * @notice User redeems cTokens in exchange for the underlying asset\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param redeemTokensIn The number of cTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming cTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemFresh(address payable redeemer, uint redeemTokensIn, uint redeemAmountIn) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr));\\n }\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(Exp({mantissa: vars.exchangeRateMantissa}), redeemTokensIn);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(redeemAmountIn, Exp({mantissa: vars.exchangeRateMantissa}));\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REDEEM_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDEEM_FRESHNESS_CHECK);\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDEEM_TRANSFER_OUT_NOT_POSSIBLE);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We invoke doTransferOut for the redeemer and the redeemAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(redeemer, vars.redeemAmount);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n /* We call the defense hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender borrows assets from the protocol to their own address\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function borrowInternal(uint borrowAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(msg.sender, borrowAmount);\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n /**\\n * @notice Users borrow assets from the protocol to their own address\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function borrowFresh(address payable borrower, uint borrowAmount) internal returns (uint) {\\n /* Fail if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.BORROW_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.BORROW_FRESHNESS_CHECK);\\n }\\n\\n /* Fail gracefully if protocol has insufficient underlying cash */\\n if (getCashPrior() < borrowAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.BORROW_CASH_NOT_AVAILABLE);\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We invoke doTransferOut for the borrower and the borrowAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(borrower, borrowAmount);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to borrower\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer the account paying off the borrow\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount the amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED\\\");\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED\\\");\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this cToken to be liquidated\\n * @param cTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) 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 = cTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, cTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this cToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param cTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowFresh(address liquidator, address borrower, uint repayAmount, CTokenInterface cTokenCollateral) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(address(this), address(cTokenCollateral), liquidator, borrower, repayAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify cTokenCollateral market's block number equals current block number */\\n if (cTokenCollateral.accrualBlockNumber() != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = -1 */\\n if (repayAmount == uint(-1)) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & 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(cTokenCollateral), actualRepayAmount);\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(cTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(cTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = cTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(cTokenCollateral), seizeTokens);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.liquidateBorrowVerify(address(this), address(cTokenCollateral), liquidator, borrower, actualRepayAmount, seizeTokens);\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another cToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed cToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of cTokens to seize\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function seize(address liquidator, address borrower, uint seizeTokens) external nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n struct SeizeInternalLocalVars {\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n uint liquidatorSeizeTokens;\\n uint protocolSeizeTokens;\\n uint protocolSeizeAmount;\\n uint exchangeRateMantissa;\\n uint totalReservesNew;\\n uint totalSupplyNew;\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another CToken.\\n * Its absolutely critical to use msg.sender as the seizer cToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed cToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of cTokens to seize\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function seizeInternal(address seizerToken, address liquidator, address borrower, uint seizeTokens) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n SeizeInternalLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (vars.mathErr, vars.borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(vars.mathErr));\\n }\\n\\n vars.protocolSeizeTokens = mul_(seizeTokens, Exp({mantissa: protocolSeizeShareMantissa}));\\n vars.liquidatorSeizeTokens = sub_(seizeTokens, vars.protocolSeizeTokens);\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n require(vars.mathErr == MathError.NO_ERROR, \\\"exchange rate math error\\\");\\n\\n vars.protocolSeizeAmount = mul_ScalarTruncate(Exp({mantissa: vars.exchangeRateMantissa}), vars.protocolSeizeTokens);\\n\\n vars.totalReservesNew = add_(totalReserves, vars.protocolSeizeAmount);\\n vars.totalSupplyNew = sub_(totalSupply, vars.protocolSeizeTokens);\\n\\n (vars.mathErr, vars.liquidatorTokensNew) = addUInt(accountTokens[liquidator], vars.liquidatorSeizeTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(vars.mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n totalReserves = vars.totalReservesNew;\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[borrower] = vars.borrowerTokensNew;\\n accountTokens[liquidator] = vars.liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, vars.liquidatorSeizeTokens);\\n emit Transfer(borrower, address(this), vars.protocolSeizeTokens);\\n emit ReservesAdded(address(this), vars.protocolSeizeAmount, vars.totalReservesNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n\\n /*** Admin Functions ***/\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPendingAdmin(address payable newPendingAdmin) external returns (uint) {\\n // Check caller = admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\\n }\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptAdmin() external returns (uint) {\\n // Check caller is pendingAdmin and pendingAdmin \\u2260 address(0)\\n if (msg.sender != pendingAdmin || msg.sender == address(0)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = address(0);\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setComptroller(ComptrollerInterface newComptroller) public returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_COMPTROLLER_OWNER_CHECK);\\n }\\n\\n ComptrollerInterface oldComptroller = comptroller;\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(oldComptroller, newComptroller);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh\\n * @dev Admin function to accrue interest and set a new reserve factor\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setReserveFactor(uint newReserveFactorMantissa) external nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\\n * @dev Admin function to set a new reserve factor\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_RESERVE_FACTOR_ADMIN_CHECK);\\n }\\n\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring from msg.sender\\n * @param addAmount Amount of addition to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to admin\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _reduceReserves(uint reduceAmount) external nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to admin\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _reduceReservesFresh(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's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n totalReservesNew = totalReserves - reduceAmount;\\n // We checked reduceAmount <= totalReserves above, so this should never revert.\\n require(totalReservesNew <= 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't be sure if side effects occurred.\\n doTransferOut(admin, reduceAmount);\\n\\n emit ReservesReduced(admin, reduceAmount, totalReservesNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Admin function to accrue interest and update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel);\\n }\\n\\n /**\\n * @notice updates the interest rate model (*requires fresh interest accrual)\\n * @dev Admin function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal returns (uint) {\\n\\n // Used to store old model for use in the event that is emitted on success\\n InterestRateModel oldInterestRateModel;\\n\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_INTEREST_RATE_MODEL_OWNER_CHECK);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Track the market's current interest rate model\\n oldInterestRateModel = interestRateModel;\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view returns (uint);\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure tather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal;\\n\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n}\\n\",\"keccak256\":\"0x436ec2e309682995f8a82dfdd9e8f75928599c10a9a680dddbee6c275014008d\"},\"contracts/CTokenInterfaces.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./InterestRateModel.sol\\\";\\nimport \\\"./EIP20NonStandardInterface.sol\\\";\\n\\ncontract CTokenStorage {\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-cToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModel public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first CTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping (address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping (address => mapping (address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Share of seized collateral that is added to reserves\\n */\\n uint public constant protocolSeizeShareMantissa = 2.8e16; //2.8%\\n\\n}\\n\\ncontract CTokenInterface is CTokenStorage {\\n /**\\n * @notice Indicator that this is a CToken contract (for inspection)\\n */\\n bool public constant isCToken = true;\\n\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(address liquidator, address borrower, uint repayAmount, address cTokenCollateral, uint seizeTokens);\\n\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin is updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(InterestRateModel oldInterestRateModel, InterestRateModel newInterestRateModel);\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address admin, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Failure event\\n */\\n event Failure(uint error, uint info, uint detail);\\n\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external returns (bool);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function approve(address spender, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function balanceOfUnderlying(address owner) external returns (uint);\\n function getAccountSnapshot(address account) external view returns (uint, uint, uint, uint);\\n function borrowRatePerBlock() external view returns (uint);\\n function supplyRatePerBlock() external view returns (uint);\\n function totalBorrowsCurrent() external returns (uint);\\n function borrowBalanceCurrent(address account) external returns (uint);\\n function borrowBalanceStored(address account) public view returns (uint);\\n function exchangeRateCurrent() public returns (uint);\\n function exchangeRateStored() public view returns (uint);\\n function getCash() external view returns (uint);\\n function accrueInterest() public returns (uint);\\n function seize(address liquidator, address borrower, uint seizeTokens) external returns (uint);\\n\\n\\n /*** Admin Functions ***/\\n\\n function _setPendingAdmin(address payable newPendingAdmin) external returns (uint);\\n function _acceptAdmin() external returns (uint);\\n function _setComptroller(ComptrollerInterface newComptroller) public returns (uint);\\n function _setReserveFactor(uint newReserveFactorMantissa) external returns (uint);\\n function _reduceReserves(uint reduceAmount) external returns (uint);\\n function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint);\\n}\\n\\ncontract CErc20Storage {\\n /**\\n * @notice Underlying asset for this CToken\\n */\\n address public underlying;\\n}\\n\\ncontract CErc20Interface is CErc20Storage {\\n\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n function redeem(uint redeemTokens) external returns (uint);\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n function borrow(uint borrowAmount) external returns (uint);\\n function repayBorrow(uint repayAmount) external returns (uint);\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n function liquidateBorrow(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) external returns (uint);\\n function sweepToken(EIP20NonStandardInterface token) external;\\n\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ncontract CDelegationStorage {\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n}\\n\\ncontract CDelegatorInterface is CDelegationStorage {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(address implementation_, bool allowResign, bytes memory becomeImplementationData) public;\\n}\\n\\ncontract CDelegateInterface is CDelegationStorage {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) public;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() public;\\n}\\n\",\"keccak256\":\"0x963bbf60b4c0b76900b3fcb2db8c8be634934b37b4113f1055e57a308197d21a\"},\"contracts/CarefulMath.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Careful Math\\n * @author Compound\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c = a * b;\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n return (MathError.NO_ERROR, a - b);\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c = a + b;\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\",\"keccak256\":\"0x0647348f27e41d22555d99eebd217dee02a4d737df6accd7cce5347a7487c7de\"},\"contracts/ComptrollerG6.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.sol\\\";\\nimport \\\"./ErrorReporter.sol\\\";\\nimport \\\"./PriceOracle.sol\\\";\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./ComptrollerStorage.sol\\\";\\nimport \\\"./Unitroller.sol\\\";\\nimport \\\"./Governance/Comp.sol\\\";\\n\\n/**\\n * @title Compound's Comptroller Contract\\n * @author Compound\\n */\\ncontract ComptrollerG6 is ComptrollerV5Storage, ComptrollerInterface, ComptrollerErrorReporter, ExponentialNoError {\\n /// @notice Emitted when an admin supports a market\\n event MarketListed(CToken cToken);\\n\\n /// @notice Emitted when an account enters a market\\n event MarketEntered(CToken cToken, address account);\\n\\n /// @notice Emitted when an account exits a market\\n event MarketExited(CToken cToken, 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(CToken cToken, uint oldCollateralFactorMantissa, uint newCollateralFactorMantissa);\\n\\n /// @notice Emitted when liquidation incentive is changed by admin\\n event NewLiquidationIncentive(uint oldLiquidationIncentiveMantissa, uint newLiquidationIncentiveMantissa);\\n\\n /// @notice Emitted when price oracle is changed\\n event NewPriceOracle(PriceOracle oldPriceOracle, PriceOracle newPriceOracle);\\n\\n /// @notice Emitted when pause guardian is changed\\n event NewPauseGuardian(address oldPauseGuardian, address newPauseGuardian);\\n\\n /// @notice Emitted when an action is paused globally\\n event ActionPaused(string action, bool pauseState);\\n\\n /// @notice Emitted when an action is paused on a market\\n event ActionPaused(CToken cToken, string action, bool pauseState);\\n\\n /// @notice Emitted when market comped status is changed\\n event MarketComped(CToken cToken, bool isComped);\\n\\n /// @notice Emitted when COMP rate is changed\\n event NewCompRate(uint oldCompRate, uint newCompRate);\\n\\n /// @notice Emitted when a new COMP speed is calculated for a market\\n event CompSpeedUpdated(CToken indexed cToken, uint newSpeed);\\n\\n /// @notice Emitted when a new COMP speed is set for a contributor\\n event ContributorCompSpeedUpdated(address indexed contributor, uint newSpeed);\\n\\n /// @notice Emitted when COMP is distributed to a supplier\\n event DistributedSupplierComp(CToken indexed cToken, address indexed supplier, uint compDelta, uint compSupplyIndex);\\n\\n /// @notice Emitted when COMP is distributed to a borrower\\n event DistributedBorrowerComp(CToken indexed cToken, address indexed borrower, uint compDelta, uint compBorrowIndex);\\n\\n /// @notice Emitted when borrow cap for a cToken is changed\\n event NewBorrowCap(CToken indexed cToken, uint newBorrowCap);\\n\\n /// @notice Emitted when borrow cap guardian is changed\\n event NewBorrowCapGuardian(address oldBorrowCapGuardian, address newBorrowCapGuardian);\\n\\n /// @notice Emitted when COMP is granted by admin\\n event CompGranted(address recipient, uint amount);\\n\\n /// @notice The threshold above which the flywheel transfers COMP, in wei\\n uint public constant compClaimThreshold = 0.001e18;\\n\\n /// @notice The initial COMP index for a market\\n uint224 public constant compInitialIndex = 1e36;\\n\\n // closeFactorMantissa must be strictly greater than this value\\n uint internal constant closeFactorMinMantissa = 0.05e18; // 0.05\\n\\n // closeFactorMantissa must not exceed this value\\n uint internal constant closeFactorMaxMantissa = 0.9e18; // 0.9\\n\\n // No collateralFactorMantissa may exceed this value\\n uint internal constant collateralFactorMaxMantissa = 0.9e18; // 0.9\\n\\n constructor() public {\\n admin = msg.sender;\\n }\\n\\n /*** Assets You Are In ***/\\n\\n /**\\n * @notice Returns the assets an account has entered\\n * @param account The address of the account to pull assets for\\n * @return A dynamic list with the assets the account has entered\\n */\\n function getAssetsIn(address account) external view returns (CToken[] memory) {\\n CToken[] memory assetsIn = accountAssets[account];\\n\\n return assetsIn;\\n }\\n\\n /**\\n * @notice Returns whether the given account is entered in the given asset\\n * @param account The address of the account to check\\n * @param cToken The cToken to check\\n * @return True if the account is in the asset, otherwise false.\\n */\\n function checkMembership(address account, CToken cToken) external view returns (bool) {\\n return markets[address(cToken)].accountMembership[account];\\n }\\n\\n /**\\n * @notice Add assets to be included in account liquidity calculation\\n * @param cTokens The list of addresses of the cToken markets to be enabled\\n * @return Success indicator for whether each corresponding market was entered\\n */\\n function enterMarkets(address[] memory cTokens) public returns (uint[] memory) {\\n uint len = cTokens.length;\\n\\n uint[] memory results = new uint[](len);\\n for (uint i = 0; i < len; i++) {\\n CToken cToken = CToken(cTokens[i]);\\n\\n results[i] = uint(addToMarketInternal(cToken, msg.sender));\\n }\\n\\n return results;\\n }\\n\\n /**\\n * @notice Add the market to the borrower's \\\"assets in\\\" for liquidity calculations\\n * @param cToken The market to enter\\n * @param borrower The address of the account to modify\\n * @return Success indicator for whether the market was entered\\n */\\n function addToMarketInternal(CToken cToken, address borrower) internal returns (Error) {\\n Market storage marketToJoin = markets[address(cToken)];\\n\\n if (!marketToJoin.isListed) {\\n // market is not listed, cannot join\\n return Error.MARKET_NOT_LISTED;\\n }\\n\\n if (marketToJoin.accountMembership[borrower] == true) {\\n // already joined\\n return Error.NO_ERROR;\\n }\\n\\n // survived the gauntlet, add to list\\n // NOTE: we store these somewhat redundantly as a significant optimization\\n // this avoids having to iterate through the list for the most common use cases\\n // that is, only when we need to perform liquidity checks\\n // and not whenever we want to check if an account is in a particular market\\n marketToJoin.accountMembership[borrower] = true;\\n accountAssets[borrower].push(cToken);\\n\\n emit MarketEntered(cToken, borrower);\\n\\n return Error.NO_ERROR;\\n }\\n\\n /**\\n * @notice Removes asset from sender's 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 cTokenAddress The address of the asset to be removed\\n * @return Whether or not the account successfully exited the market\\n */\\n function exitMarket(address cTokenAddress) external returns (uint) {\\n CToken cToken = CToken(cTokenAddress);\\n /* Get sender tokensHeld and amountOwed underlying from the cToken */\\n (uint oErr, uint tokensHeld, uint amountOwed, ) = cToken.getAccountSnapshot(msg.sender);\\n require(oErr == 0, \\\"exitMarket: getAccountSnapshot failed\\\"); // semi-opaque error code\\n\\n /* Fail if the sender has a borrow balance */\\n if (amountOwed != 0) {\\n return fail(Error.NONZERO_BORROW_BALANCE, FailureInfo.EXIT_MARKET_BALANCE_OWED);\\n }\\n\\n /* Fail if the sender is not permitted to redeem all of their tokens */\\n uint allowed = redeemAllowedInternal(cTokenAddress, msg.sender, tokensHeld);\\n if (allowed != 0) {\\n return failOpaque(Error.REJECTION, FailureInfo.EXIT_MARKET_REJECTION, allowed);\\n }\\n\\n Market storage marketToExit = markets[address(cToken)];\\n\\n /* Return true if the sender is not already \\u2018in\\u2019 the market */\\n if (!marketToExit.accountMembership[msg.sender]) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Set cToken account membership to false */\\n delete marketToExit.accountMembership[msg.sender];\\n\\n /* Delete cToken from the account\\u2019s list of assets */\\n // load into memory for faster iteration\\n CToken[] memory userAssetList = accountAssets[msg.sender];\\n uint len = userAssetList.length;\\n uint assetIndex = len;\\n for (uint i = 0; i < len; i++) {\\n if (userAssetList[i] == cToken) {\\n assetIndex = i;\\n break;\\n }\\n }\\n\\n // We *must* have found the asset in the list or our redundant data structure is broken\\n assert(assetIndex < len);\\n\\n // copy last item in list to location of item to be removed, reduce length by 1\\n CToken[] storage storedList = accountAssets[msg.sender];\\n storedList[assetIndex] = storedList[storedList.length - 1];\\n storedList.length--;\\n\\n emit MarketExited(cToken, 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 cToken The market to verify the mint against\\n * @param minter The account which would get the minted tokens\\n * @param mintAmount The amount of underlying being supplied to the market in exchange for tokens\\n * @return 0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function mintAllowed(address cToken, address minter, uint mintAmount) external returns (uint) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n require(!mintGuardianPaused[cToken], \\\"mint is paused\\\");\\n\\n // Shh - currently unused\\n minter;\\n mintAmount;\\n\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n // Keep the flywheel moving\\n updateCompSupplyIndex(cToken);\\n distributeSupplierComp(cToken, minter, false);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates mint and reverts on rejection. May emit logs.\\n * @param cToken Asset being minted\\n * @param minter The address minting the tokens\\n * @param actualMintAmount The amount of the underlying asset being minted\\n * @param mintTokens The number of tokens being minted\\n */\\n function mintVerify(address cToken, address minter, uint actualMintAmount, uint mintTokens) external {\\n // Shh - currently unused\\n cToken;\\n minter;\\n actualMintAmount;\\n mintTokens;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to redeem tokens in the given market\\n * @param cToken The market to verify the redeem against\\n * @param redeemer The account which would redeem the tokens\\n * @param redeemTokens The number of cTokens to exchange for the underlying asset in the market\\n * @return 0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function redeemAllowed(address cToken, address redeemer, uint redeemTokens) external returns (uint) {\\n uint allowed = redeemAllowedInternal(cToken, redeemer, redeemTokens);\\n if (allowed != uint(Error.NO_ERROR)) {\\n return allowed;\\n }\\n\\n // Keep the flywheel moving\\n updateCompSupplyIndex(cToken);\\n distributeSupplierComp(cToken, redeemer, false);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n function redeemAllowedInternal(address cToken, address redeemer, uint redeemTokens) internal view returns (uint) {\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!markets[cToken].accountMembership[redeemer]) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n (Error err, , uint shortfall) = getHypotheticalAccountLiquidityInternal(redeemer, CToken(cToken), redeemTokens, 0);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n if (shortfall > 0) {\\n return uint(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates redeem and reverts on rejection. May emit logs.\\n * @param cToken Asset being redeemed\\n * @param redeemer The address redeeming the tokens\\n * @param redeemAmount The amount of the underlying asset being redeemed\\n * @param redeemTokens The number of tokens being redeemed\\n */\\n function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) external {\\n // Shh - currently unused\\n cToken;\\n redeemer;\\n\\n // Require tokens is zero or amount is also zero\\n if (redeemTokens == 0 && redeemAmount > 0) {\\n revert(\\\"redeemTokens zero\\\");\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to borrow the underlying asset of the given market\\n * @param cToken The market to verify the borrow against\\n * @param borrower The account which would borrow the asset\\n * @param borrowAmount The amount of underlying the account would borrow\\n * @return 0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function borrowAllowed(address cToken, address borrower, uint borrowAmount) external returns (uint) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n require(!borrowGuardianPaused[cToken], \\\"borrow is paused\\\");\\n\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n if (!markets[cToken].accountMembership[borrower]) {\\n // only cTokens may call borrowAllowed if borrower not in market\\n require(msg.sender == cToken, \\\"sender must be cToken\\\");\\n\\n // attempt to add borrower to the market\\n Error err = addToMarketInternal(CToken(msg.sender), borrower);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n\\n // it should be impossible to break the important invariant\\n assert(markets[cToken].accountMembership[borrower]);\\n }\\n\\n if (oracle.getUnderlyingPrice(CToken(cToken)) == 0) {\\n return uint(Error.PRICE_ERROR);\\n }\\n\\n\\n uint borrowCap = borrowCaps[cToken];\\n // Borrow cap of 0 corresponds to unlimited borrowing\\n if (borrowCap != 0) {\\n uint totalBorrows = CToken(cToken).totalBorrows();\\n uint nextTotalBorrows = add_(totalBorrows, borrowAmount);\\n require(nextTotalBorrows < borrowCap, \\\"market borrow cap reached\\\");\\n }\\n\\n (Error err, , uint shortfall) = getHypotheticalAccountLiquidityInternal(borrower, CToken(cToken), 0, borrowAmount);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n if (shortfall > 0) {\\n return uint(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n\\n // Keep the flywheel moving\\n Exp memory borrowIndex = Exp({mantissa: CToken(cToken).borrowIndex()});\\n updateCompBorrowIndex(cToken, borrowIndex);\\n distributeBorrowerComp(cToken, borrower, borrowIndex, false);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates borrow and reverts on rejection. May emit logs.\\n * @param cToken Asset whose underlying is being borrowed\\n * @param borrower The address borrowing the underlying\\n * @param borrowAmount The amount of the underlying asset requested to borrow\\n */\\n function borrowVerify(address cToken, address borrower, uint borrowAmount) external {\\n // Shh - currently unused\\n cToken;\\n borrower;\\n borrowAmount;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to repay a borrow in the given market\\n * @param cToken The market to verify the repay against\\n * @param payer The account which would repay the asset\\n * @param borrower The account which would borrowed the asset\\n * @param repayAmount The amount of the underlying asset the account would repay\\n * @return 0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function repayBorrowAllowed(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount) external returns (uint) {\\n // Shh - currently unused\\n payer;\\n borrower;\\n repayAmount;\\n\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n // Keep the flywheel moving\\n Exp memory borrowIndex = Exp({mantissa: CToken(cToken).borrowIndex()});\\n updateCompBorrowIndex(cToken, borrowIndex);\\n distributeBorrowerComp(cToken, borrower, borrowIndex, false);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates repayBorrow and reverts on rejection. May emit logs.\\n * @param cToken Asset being repaid\\n * @param payer The address repaying the borrow\\n * @param borrower The address of the borrower\\n * @param actualRepayAmount The amount of underlying being repaid\\n */\\n function repayBorrowVerify(\\n address cToken,\\n address payer,\\n address borrower,\\n uint actualRepayAmount,\\n uint borrowerIndex) external {\\n // Shh - currently unused\\n cToken;\\n payer;\\n borrower;\\n actualRepayAmount;\\n borrowerIndex;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the liquidation should be allowed to occur\\n * @param cTokenBorrowed Asset which was borrowed by the borrower\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param repayAmount The amount of underlying being repaid\\n */\\n function liquidateBorrowAllowed(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount) external returns (uint) {\\n // Shh - currently unused\\n liquidator;\\n\\n if (!markets[cTokenBorrowed].isListed || !markets[cTokenCollateral].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n /* The borrower must have shortfall in order to be liquidatable */\\n (Error err, , uint shortfall) = getAccountLiquidityInternal(borrower);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n if (shortfall == 0) {\\n return uint(Error.INSUFFICIENT_SHORTFALL);\\n }\\n\\n /* The liquidator may not repay more than what is allowed by the closeFactor */\\n uint borrowBalance = CToken(cTokenBorrowed).borrowBalanceStored(borrower);\\n uint maxClose = mul_ScalarTruncate(Exp({mantissa: closeFactorMantissa}), borrowBalance);\\n if (repayAmount > 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 cTokenBorrowed Asset which was borrowed by the borrower\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param actualRepayAmount The amount of underlying being repaid\\n */\\n function liquidateBorrowVerify(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint actualRepayAmount,\\n uint seizeTokens) external {\\n // Shh - currently unused\\n cTokenBorrowed;\\n cTokenCollateral;\\n liquidator;\\n borrower;\\n actualRepayAmount;\\n seizeTokens;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the seizing of assets should be allowed to occur\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param cTokenBorrowed Asset which was borrowed by the borrower\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param seizeTokens The number of collateral tokens to seize\\n */\\n function seizeAllowed(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external returns (uint) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n require(!seizeGuardianPaused, \\\"seize is paused\\\");\\n\\n // Shh - currently unused\\n seizeTokens;\\n\\n if (!markets[cTokenCollateral].isListed || !markets[cTokenBorrowed].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n if (CToken(cTokenCollateral).comptroller() != CToken(cTokenBorrowed).comptroller()) {\\n return uint(Error.COMPTROLLER_MISMATCH);\\n }\\n\\n // Keep the flywheel moving\\n updateCompSupplyIndex(cTokenCollateral);\\n distributeSupplierComp(cTokenCollateral, borrower, false);\\n distributeSupplierComp(cTokenCollateral, liquidator, false);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates seize and reverts on rejection. May emit logs.\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param cTokenBorrowed Asset which was borrowed by the borrower\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param seizeTokens The number of collateral tokens to seize\\n */\\n function seizeVerify(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external {\\n // Shh - currently unused\\n cTokenCollateral;\\n cTokenBorrowed;\\n liquidator;\\n borrower;\\n seizeTokens;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to transfer tokens in the given market\\n * @param cToken The market to verify the transfer against\\n * @param src The account which sources the tokens\\n * @param dst The account which receives the tokens\\n * @param transferTokens The number of cTokens to transfer\\n * @return 0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function transferAllowed(address cToken, address src, address dst, uint transferTokens) external returns (uint) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n require(!transferGuardianPaused, \\\"transfer is paused\\\");\\n\\n // Currently the only consideration is whether or not\\n // the src is allowed to redeem this many tokens\\n uint allowed = redeemAllowedInternal(cToken, src, transferTokens);\\n if (allowed != uint(Error.NO_ERROR)) {\\n return allowed;\\n }\\n\\n // Keep the flywheel moving\\n updateCompSupplyIndex(cToken);\\n distributeSupplierComp(cToken, src, false);\\n distributeSupplierComp(cToken, dst, false);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates transfer and reverts on rejection. May emit logs.\\n * @param cToken Asset being transferred\\n * @param src The account which sources the tokens\\n * @param dst The account which receives the tokens\\n * @param transferTokens The number of cTokens to transfer\\n */\\n function transferVerify(address cToken, address src, address dst, uint transferTokens) external {\\n // Shh - currently unused\\n cToken;\\n src;\\n dst;\\n transferTokens;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n /**\\n * @dev Local vars for avoiding stack-depth limits in calculating account liquidity.\\n * Note that `cTokenBalance` is the number of cTokens the account owns in the market,\\n * whereas `borrowBalance` is the amount of underlying that the account has borrowed.\\n */\\n struct AccountLiquidityLocalVars {\\n uint sumCollateral;\\n uint sumBorrowPlusEffects;\\n uint cTokenBalance;\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n uint oraclePriceMantissa;\\n Exp collateralFactor;\\n Exp exchangeRate;\\n Exp oraclePrice;\\n Exp tokensToDenom;\\n }\\n\\n /**\\n * @notice Determine the current account liquidity wrt collateral requirements\\n * @return (possible error code (semi-opaque),\\n account liquidity in excess of collateral requirements,\\n * account shortfall below collateral requirements)\\n */\\n function getAccountLiquidity(address account) public view returns (uint, uint, uint) {\\n (Error err, uint liquidity, uint shortfall) = getHypotheticalAccountLiquidityInternal(account, CToken(0), 0, 0);\\n\\n return (uint(err), liquidity, shortfall);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity wrt collateral requirements\\n * @return (possible error code,\\n account liquidity in excess of collateral requirements,\\n * account shortfall below collateral requirements)\\n */\\n function getAccountLiquidityInternal(address account) internal view returns (Error, uint, uint) {\\n return getHypotheticalAccountLiquidityInternal(account, CToken(0), 0, 0);\\n }\\n\\n /**\\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\\n * @param cTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @return (possible error code (semi-opaque),\\n hypothetical account liquidity in excess of collateral requirements,\\n * hypothetical account shortfall below collateral requirements)\\n */\\n function getHypotheticalAccountLiquidity(\\n address account,\\n address cTokenModify,\\n uint redeemTokens,\\n uint borrowAmount) public view returns (uint, uint, uint) {\\n (Error err, uint liquidity, uint shortfall) = getHypotheticalAccountLiquidityInternal(account, CToken(cTokenModify), 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 cTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @dev Note that we calculate the exchangeRateStored for each collateral cToken using stored data,\\n * without calculating accumulated interest.\\n * @return (possible error code,\\n hypothetical account liquidity in excess of collateral requirements,\\n * hypothetical account shortfall below collateral requirements)\\n */\\n function getHypotheticalAccountLiquidityInternal(\\n address account,\\n CToken cTokenModify,\\n uint redeemTokens,\\n uint borrowAmount) internal view returns (Error, uint, uint) {\\n\\n AccountLiquidityLocalVars memory vars; // Holds all our calculation results\\n uint oErr;\\n\\n // For each asset the account is in\\n CToken[] memory assets = accountAssets[account];\\n for (uint i = 0; i < assets.length; i++) {\\n CToken asset = assets[i];\\n\\n // Read the balances and exchange rate from the cToken\\n (oErr, vars.cTokenBalance, vars.borrowBalance, vars.exchangeRateMantissa) = asset.getAccountSnapshot(account);\\n if (oErr != 0) { // semi-opaque error code, we assume NO_ERROR == 0 is invariant between upgrades\\n return (Error.SNAPSHOT_ERROR, 0, 0);\\n }\\n vars.collateralFactor = Exp({mantissa: markets[address(asset)].collateralFactorMantissa});\\n vars.exchangeRate = Exp({mantissa: vars.exchangeRateMantissa});\\n\\n // Get the normalized price of the asset\\n vars.oraclePriceMantissa = oracle.getUnderlyingPrice(asset);\\n if (vars.oraclePriceMantissa == 0) {\\n return (Error.PRICE_ERROR, 0, 0);\\n }\\n vars.oraclePrice = Exp({mantissa: vars.oraclePriceMantissa});\\n\\n // Pre-compute a conversion factor from tokens -> ether (normalized price value)\\n vars.tokensToDenom = mul_(mul_(vars.collateralFactor, vars.exchangeRate), vars.oraclePrice);\\n\\n // sumCollateral += tokensToDenom * cTokenBalance\\n vars.sumCollateral = mul_ScalarTruncateAddUInt(vars.tokensToDenom, vars.cTokenBalance, vars.sumCollateral);\\n\\n // sumBorrowPlusEffects += oraclePrice * borrowBalance\\n vars.sumBorrowPlusEffects = mul_ScalarTruncateAddUInt(vars.oraclePrice, vars.borrowBalance, vars.sumBorrowPlusEffects);\\n\\n // Calculate effects of interacting with cTokenModify\\n if (asset == cTokenModify) {\\n // redeem effect\\n // sumBorrowPlusEffects += tokensToDenom * redeemTokens\\n vars.sumBorrowPlusEffects = mul_ScalarTruncateAddUInt(vars.tokensToDenom, redeemTokens, vars.sumBorrowPlusEffects);\\n\\n // borrow effect\\n // sumBorrowPlusEffects += oraclePrice * borrowAmount\\n vars.sumBorrowPlusEffects = mul_ScalarTruncateAddUInt(vars.oraclePrice, borrowAmount, vars.sumBorrowPlusEffects);\\n }\\n }\\n\\n // These are safe, as the underflow condition is checked first\\n if (vars.sumCollateral > vars.sumBorrowPlusEffects) {\\n return (Error.NO_ERROR, vars.sumCollateral - vars.sumBorrowPlusEffects, 0);\\n } else {\\n return (Error.NO_ERROR, 0, vars.sumBorrowPlusEffects - vars.sumCollateral);\\n }\\n }\\n\\n /**\\n * @notice Calculate number of tokens of collateral asset to seize given an underlying amount\\n * @dev Used in liquidation (called in cToken.liquidateBorrowFresh)\\n * @param cTokenBorrowed The address of the borrowed cToken\\n * @param cTokenCollateral The address of the collateral cToken\\n * @param actualRepayAmount The amount of cTokenBorrowed underlying to convert into cTokenCollateral tokens\\n * @return (errorCode, number of cTokenCollateral tokens to be seized in a liquidation)\\n */\\n function liquidateCalculateSeizeTokens(address cTokenBorrowed, address cTokenCollateral, uint actualRepayAmount) external view returns (uint, uint) {\\n /* Read oracle prices for borrowed and collateral markets */\\n uint priceBorrowedMantissa = oracle.getUnderlyingPrice(CToken(cTokenBorrowed));\\n uint priceCollateralMantissa = oracle.getUnderlyingPrice(CToken(cTokenCollateral));\\n if (priceBorrowedMantissa == 0 || priceCollateralMantissa == 0) {\\n return (uint(Error.PRICE_ERROR), 0);\\n }\\n\\n /*\\n * Get the exchange rate and calculate the number of collateral tokens to seize:\\n * seizeAmount = actualRepayAmount * liquidationIncentive * priceBorrowed / priceCollateral\\n * seizeTokens = seizeAmount / exchangeRate\\n * = actualRepayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate)\\n */\\n uint exchangeRateMantissa = CToken(cTokenCollateral).exchangeRateStored(); // Note: reverts on error\\n uint seizeTokens;\\n Exp memory numerator;\\n Exp memory denominator;\\n Exp memory ratio;\\n\\n numerator = mul_(Exp({mantissa: liquidationIncentiveMantissa}), Exp({mantissa: priceBorrowedMantissa}));\\n denominator = mul_(Exp({mantissa: priceCollateralMantissa}), Exp({mantissa: exchangeRateMantissa}));\\n ratio = div_(numerator, denominator);\\n\\n seizeTokens = mul_ScalarTruncate(ratio, actualRepayAmount);\\n\\n return (uint(Error.NO_ERROR), seizeTokens);\\n }\\n\\n /*** Admin Functions ***/\\n\\n /**\\n * @notice Sets a new price oracle for the comptroller\\n * @dev Admin function to set a new price oracle\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPriceOracle(PriceOracle newOracle) public returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PRICE_ORACLE_OWNER_CHECK);\\n }\\n\\n // Track the old oracle for the comptroller\\n PriceOracle oldOracle = oracle;\\n\\n // Set comptroller's oracle to newOracle\\n oracle = newOracle;\\n\\n // Emit NewPriceOracle(oldOracle, newOracle)\\n emit NewPriceOracle(oldOracle, newOracle);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets the closeFactor used when liquidating borrows\\n * @dev Admin function to set closeFactor\\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\\n * @return uint 0=success, otherwise a failure\\n */\\n function _setCloseFactor(uint newCloseFactorMantissa) external returns (uint) {\\n // Check caller is admin\\n \\trequire(msg.sender == admin, \\\"only admin can set close factor\\\");\\n\\n uint oldCloseFactorMantissa = closeFactorMantissa;\\n closeFactorMantissa = newCloseFactorMantissa;\\n emit NewCloseFactor(oldCloseFactorMantissa, closeFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets the collateralFactor for a market\\n * @dev Admin function to set per-market collateralFactor\\n * @param cToken The market to set the factor on\\n * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18\\n * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function _setCollateralFactor(CToken cToken, 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(cToken)];\\n if (!market.isListed) {\\n return fail(Error.MARKET_NOT_LISTED, FailureInfo.SET_COLLATERAL_FACTOR_NO_EXISTS);\\n }\\n\\n Exp memory newCollateralFactorExp = Exp({mantissa: newCollateralFactorMantissa});\\n\\n // Check collateral factor <= 0.9\\n Exp memory highLimit = Exp({mantissa: collateralFactorMaxMantissa});\\n if (lessThanExp(highLimit, newCollateralFactorExp)) {\\n return fail(Error.INVALID_COLLATERAL_FACTOR, FailureInfo.SET_COLLATERAL_FACTOR_VALIDATION);\\n }\\n\\n // If collateral factor != 0, fail if price == 0\\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(cToken) == 0) {\\n return fail(Error.PRICE_ERROR, FailureInfo.SET_COLLATERAL_FACTOR_WITHOUT_PRICE);\\n }\\n\\n // Set market's collateral factor to new collateral factor, remember old value\\n uint oldCollateralFactorMantissa = market.collateralFactorMantissa;\\n market.collateralFactorMantissa = newCollateralFactorMantissa;\\n\\n // Emit event with asset, old collateral factor, and new collateral factor\\n emit NewCollateralFactor(cToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets liquidationIncentive\\n * @dev Admin function to set liquidationIncentive\\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\\n * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function _setLiquidationIncentive(uint newLiquidationIncentiveMantissa) external returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_LIQUIDATION_INCENTIVE_OWNER_CHECK);\\n }\\n\\n // Save current value for use in log\\n uint oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa;\\n\\n // Set liquidation incentive to new incentive\\n liquidationIncentiveMantissa = newLiquidationIncentiveMantissa;\\n\\n // Emit event with old incentive, new incentive\\n emit NewLiquidationIncentive(oldLiquidationIncentiveMantissa, newLiquidationIncentiveMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Add the market to the markets mapping and set it as listed\\n * @dev Admin function to set isListed and add support for the market\\n * @param cToken The address of the market (token) to list\\n * @return uint 0=success, otherwise a failure. (See enum Error for details)\\n */\\n function _supportMarket(CToken cToken) external returns (uint) {\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SUPPORT_MARKET_OWNER_CHECK);\\n }\\n\\n if (markets[address(cToken)].isListed) {\\n return fail(Error.MARKET_ALREADY_LISTED, FailureInfo.SUPPORT_MARKET_EXISTS);\\n }\\n\\n cToken.isCToken(); // Sanity check to make sure its really a CToken\\n\\n markets[address(cToken)] = Market({isListed: true, isComped: false, collateralFactorMantissa: 0});\\n\\n _addMarketInternal(address(cToken));\\n\\n emit MarketListed(cToken);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n function _addMarketInternal(address cToken) internal {\\n for (uint i = 0; i < allMarkets.length; i ++) {\\n require(allMarkets[i] != CToken(cToken), \\\"market already added\\\");\\n }\\n allMarkets.push(CToken(cToken));\\n }\\n\\n\\n /**\\n * @notice Set the given borrow caps for the given cToken markets. Borrowing that brings total borrows to or above borrow cap will revert.\\n * @dev Admin or borrowCapGuardian function to set the borrow caps. A borrow cap of 0 corresponds to unlimited borrowing.\\n * @param cTokens The addresses of the markets (tokens) to change the borrow caps for\\n * @param newBorrowCaps The new borrow cap values in underlying to be set. A value of 0 corresponds to unlimited borrowing.\\n */\\n function _setMarketBorrowCaps(CToken[] calldata cTokens, uint[] calldata newBorrowCaps) external {\\n \\trequire(msg.sender == admin || msg.sender == borrowCapGuardian, \\\"only admin or borrow cap guardian can set borrow caps\\\"); \\n\\n uint numMarkets = cTokens.length;\\n uint numBorrowCaps = newBorrowCaps.length;\\n\\n require(numMarkets != 0 && numMarkets == numBorrowCaps, \\\"invalid input\\\");\\n\\n for(uint i = 0; i < numMarkets; i++) {\\n borrowCaps[address(cTokens[i])] = newBorrowCaps[i];\\n emit NewBorrowCap(cTokens[i], newBorrowCaps[i]);\\n }\\n }\\n\\n /**\\n * @notice Admin function to change the Borrow Cap Guardian\\n * @param newBorrowCapGuardian The address of the new Borrow Cap Guardian\\n */\\n function _setBorrowCapGuardian(address newBorrowCapGuardian) external {\\n require(msg.sender == admin, \\\"only admin can set borrow cap guardian\\\");\\n\\n // Save current value for inclusion in log\\n address oldBorrowCapGuardian = borrowCapGuardian;\\n\\n // Store borrowCapGuardian with value newBorrowCapGuardian\\n borrowCapGuardian = newBorrowCapGuardian;\\n\\n // Emit NewBorrowCapGuardian(OldBorrowCapGuardian, NewBorrowCapGuardian)\\n emit NewBorrowCapGuardian(oldBorrowCapGuardian, newBorrowCapGuardian);\\n }\\n\\n /**\\n * @notice Admin function to change the Pause Guardian\\n * @param newPauseGuardian The address of the new Pause Guardian\\n * @return uint 0=success, otherwise a failure. (See enum Error for details)\\n */\\n function _setPauseGuardian(address newPauseGuardian) public returns (uint) {\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PAUSE_GUARDIAN_OWNER_CHECK);\\n }\\n\\n // Save current value for inclusion in log\\n address oldPauseGuardian = pauseGuardian;\\n\\n // Store pauseGuardian with value newPauseGuardian\\n pauseGuardian = newPauseGuardian;\\n\\n // Emit NewPauseGuardian(OldPauseGuardian, NewPauseGuardian)\\n emit NewPauseGuardian(oldPauseGuardian, pauseGuardian);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n function _setMintPaused(CToken cToken, bool state) public returns (bool) {\\n require(markets[address(cToken)].isListed, \\\"cannot pause a market that is not listed\\\");\\n require(msg.sender == pauseGuardian || msg.sender == admin, \\\"only pause guardian and admin can pause\\\");\\n require(msg.sender == admin || state == true, \\\"only admin can unpause\\\");\\n\\n mintGuardianPaused[address(cToken)] = state;\\n emit ActionPaused(cToken, \\\"Mint\\\", state);\\n return state;\\n }\\n\\n function _setBorrowPaused(CToken cToken, bool state) public returns (bool) {\\n require(markets[address(cToken)].isListed, \\\"cannot pause a market that is not listed\\\");\\n require(msg.sender == pauseGuardian || msg.sender == admin, \\\"only pause guardian and admin can pause\\\");\\n require(msg.sender == admin || state == true, \\\"only admin can unpause\\\");\\n\\n borrowGuardianPaused[address(cToken)] = state;\\n emit ActionPaused(cToken, \\\"Borrow\\\", state);\\n return state;\\n }\\n\\n function _setTransferPaused(bool state) public returns (bool) {\\n require(msg.sender == pauseGuardian || msg.sender == admin, \\\"only pause guardian and admin can pause\\\");\\n require(msg.sender == admin || state == true, \\\"only admin can unpause\\\");\\n\\n transferGuardianPaused = state;\\n emit ActionPaused(\\\"Transfer\\\", state);\\n return state;\\n }\\n\\n function _setSeizePaused(bool state) public returns (bool) {\\n require(msg.sender == pauseGuardian || msg.sender == admin, \\\"only pause guardian and admin can pause\\\");\\n require(msg.sender == admin || state == true, \\\"only admin can unpause\\\");\\n\\n seizeGuardianPaused = state;\\n emit ActionPaused(\\\"Seize\\\", state);\\n return state;\\n }\\n\\n function _become(Unitroller unitroller) public {\\n require(msg.sender == unitroller.admin(), \\\"only unitroller admin can change brains\\\");\\n require(unitroller._acceptImplementation() == 0, \\\"change not authorized\\\");\\n }\\n\\n /**\\n * @notice Checks caller is admin, or this contract is becoming the new implementation\\n */\\n function adminOrInitializing() internal view returns (bool) {\\n return msg.sender == admin || msg.sender == comptrollerImplementation;\\n }\\n\\n /*** Comp Distribution ***/\\n\\n /**\\n * @notice Recalculate and update COMP speeds for all COMP markets\\n */\\n function refreshCompSpeeds() public {\\n require(msg.sender == tx.origin, \\\"only externally owned accounts may refresh speeds\\\");\\n refreshCompSpeedsInternal();\\n }\\n\\n function refreshCompSpeedsInternal() internal {\\n CToken[] memory allMarkets_ = allMarkets;\\n\\n for (uint i = 0; i < allMarkets_.length; i++) {\\n CToken cToken = allMarkets_[i];\\n Exp memory borrowIndex = Exp({mantissa: cToken.borrowIndex()});\\n updateCompSupplyIndex(address(cToken));\\n updateCompBorrowIndex(address(cToken), borrowIndex);\\n }\\n\\n Exp memory totalUtility = Exp({mantissa: 0});\\n Exp[] memory utilities = new Exp[](allMarkets_.length);\\n for (uint i = 0; i < allMarkets_.length; i++) {\\n CToken cToken = allMarkets_[i];\\n if (markets[address(cToken)].isComped) {\\n Exp memory assetPrice = Exp({mantissa: oracle.getUnderlyingPrice(cToken)});\\n Exp memory utility = mul_(assetPrice, cToken.totalBorrows());\\n utilities[i] = utility;\\n totalUtility = add_(totalUtility, utility);\\n }\\n }\\n\\n for (uint i = 0; i < allMarkets_.length; i++) {\\n CToken cToken = allMarkets[i];\\n uint newSpeed = totalUtility.mantissa > 0 ? mul_(compRate, div_(utilities[i], totalUtility)) : 0;\\n compSpeeds[address(cToken)] = newSpeed;\\n emit CompSpeedUpdated(cToken, newSpeed);\\n }\\n }\\n\\n /**\\n * @notice Accrue COMP to the market by updating the supply index\\n * @param cToken The market whose supply index to update\\n */\\n function updateCompSupplyIndex(address cToken) internal {\\n CompMarketState storage supplyState = compSupplyState[cToken];\\n uint supplySpeed = compSpeeds[cToken];\\n uint blockNumber = getBlockNumber();\\n uint deltaBlocks = sub_(blockNumber, uint(supplyState.block));\\n if (deltaBlocks > 0 && supplySpeed > 0) {\\n uint supplyTokens = CToken(cToken).totalSupply();\\n uint compAccrued = mul_(deltaBlocks, supplySpeed);\\n Double memory ratio = supplyTokens > 0 ? fraction(compAccrued, supplyTokens) : Double({mantissa: 0});\\n Double memory index = add_(Double({mantissa: supplyState.index}), ratio);\\n compSupplyState[cToken] = CompMarketState({\\n index: safe224(index.mantissa, \\\"new index exceeds 224 bits\\\"),\\n block: safe32(blockNumber, \\\"block number exceeds 32 bits\\\")\\n });\\n } else if (deltaBlocks > 0) {\\n supplyState.block = safe32(blockNumber, \\\"block number exceeds 32 bits\\\");\\n }\\n }\\n\\n /**\\n * @notice Accrue COMP to the market by updating the borrow index\\n * @param cToken The market whose borrow index to update\\n */\\n function updateCompBorrowIndex(address cToken, Exp memory marketBorrowIndex) internal {\\n CompMarketState storage borrowState = compBorrowState[cToken];\\n uint borrowSpeed = compSpeeds[cToken];\\n uint blockNumber = getBlockNumber();\\n uint deltaBlocks = sub_(blockNumber, uint(borrowState.block));\\n if (deltaBlocks > 0 && borrowSpeed > 0) {\\n uint borrowAmount = div_(CToken(cToken).totalBorrows(), marketBorrowIndex);\\n uint compAccrued = mul_(deltaBlocks, borrowSpeed);\\n Double memory ratio = borrowAmount > 0 ? fraction(compAccrued, borrowAmount) : Double({mantissa: 0});\\n Double memory index = add_(Double({mantissa: borrowState.index}), ratio);\\n compBorrowState[cToken] = CompMarketState({\\n index: safe224(index.mantissa, \\\"new index exceeds 224 bits\\\"),\\n block: safe32(blockNumber, \\\"block number exceeds 32 bits\\\")\\n });\\n } else if (deltaBlocks > 0) {\\n borrowState.block = safe32(blockNumber, \\\"block number exceeds 32 bits\\\");\\n }\\n }\\n\\n /**\\n * @notice Calculate COMP accrued by a supplier and possibly transfer it to them\\n * @param cToken The market in which the supplier is interacting\\n * @param supplier The address of the supplier to distribute COMP to\\n */\\n function distributeSupplierComp(address cToken, address supplier, bool distributeAll) internal {\\n CompMarketState storage supplyState = compSupplyState[cToken];\\n Double memory supplyIndex = Double({mantissa: supplyState.index});\\n Double memory supplierIndex = Double({mantissa: compSupplierIndex[cToken][supplier]});\\n compSupplierIndex[cToken][supplier] = supplyIndex.mantissa;\\n\\n if (supplierIndex.mantissa == 0 && supplyIndex.mantissa > 0) {\\n supplierIndex.mantissa = compInitialIndex;\\n }\\n\\n Double memory deltaIndex = sub_(supplyIndex, supplierIndex);\\n uint supplierTokens = CToken(cToken).balanceOf(supplier);\\n uint supplierDelta = mul_(supplierTokens, deltaIndex);\\n uint supplierAccrued = add_(compAccrued[supplier], supplierDelta);\\n compAccrued[supplier] = transferComp(supplier, supplierAccrued, distributeAll ? 0 : compClaimThreshold);\\n emit DistributedSupplierComp(CToken(cToken), supplier, supplierDelta, supplyIndex.mantissa);\\n }\\n\\n /**\\n * @notice Calculate COMP accrued by a borrower and possibly transfer it to them\\n * @dev Borrowers will not begin to accrue until after the first interaction with the protocol.\\n * @param cToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute COMP to\\n */\\n function distributeBorrowerComp(address cToken, address borrower, Exp memory marketBorrowIndex, bool distributeAll) internal {\\n CompMarketState storage borrowState = compBorrowState[cToken];\\n Double memory borrowIndex = Double({mantissa: borrowState.index});\\n Double memory borrowerIndex = Double({mantissa: compBorrowerIndex[cToken][borrower]});\\n compBorrowerIndex[cToken][borrower] = borrowIndex.mantissa;\\n\\n if (borrowerIndex.mantissa > 0) {\\n Double memory deltaIndex = sub_(borrowIndex, borrowerIndex);\\n uint borrowerAmount = div_(CToken(cToken).borrowBalanceStored(borrower), marketBorrowIndex);\\n uint borrowerDelta = mul_(borrowerAmount, deltaIndex);\\n uint borrowerAccrued = add_(compAccrued[borrower], borrowerDelta);\\n compAccrued[borrower] = transferComp(borrower, borrowerAccrued, distributeAll ? 0 : compClaimThreshold);\\n emit DistributedBorrowerComp(CToken(cToken), borrower, borrowerDelta, borrowIndex.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Transfer COMP to the user, if they are above the threshold\\n * @dev Note: If there is not enough COMP, we do not perform the transfer all.\\n * @param user The address of the user to transfer COMP to\\n * @param userAccrued The amount of COMP to (possibly) transfer\\n * @return The amount of COMP which was NOT transferred to the user\\n */\\n function transferComp(address user, uint userAccrued, uint threshold) internal returns (uint) {\\n if (userAccrued >= threshold && userAccrued > 0) {\\n Comp comp = Comp(getCompAddress());\\n uint compRemaining = comp.balanceOf(address(this));\\n if (userAccrued <= compRemaining) {\\n comp.transfer(user, userAccrued);\\n return 0;\\n }\\n }\\n return userAccrued;\\n }\\n\\n /**\\n * @notice Calculate additional accrued COMP for a contributor since last accrual\\n * @param contributor The address to calculate contributor rewards for\\n */\\n function updateContributorRewards(address contributor) public {\\n uint compSpeed = compContributorSpeeds[contributor];\\n uint blockNumber = getBlockNumber();\\n uint deltaBlocks = sub_(blockNumber, lastContributorBlock[contributor]);\\n if (deltaBlocks > 0 && compSpeed > 0) {\\n uint newAccrued = mul_(deltaBlocks, compSpeed);\\n uint contributorAccrued = add_(compAccrued[contributor], newAccrued);\\n\\n compAccrued[contributor] = contributorAccrued;\\n lastContributorBlock[contributor] = blockNumber;\\n }\\n }\\n\\n /**\\n * @notice Claim all the comp accrued by holder in all markets\\n * @param holder The address to claim COMP for\\n */\\n function claimComp(address holder) public {\\n return claimComp(holder, allMarkets);\\n }\\n\\n /**\\n * @notice Claim all the comp accrued by holder in the specified markets\\n * @param holder The address to claim COMP for\\n * @param cTokens The list of markets to claim COMP in\\n */\\n function claimComp(address holder, CToken[] memory cTokens) public {\\n address[] memory holders = new address[](1);\\n holders[0] = holder;\\n claimComp(holders, cTokens, true, true);\\n }\\n\\n /**\\n * @notice Claim all comp accrued by the holders\\n * @param holders The addresses to claim COMP for\\n * @param cTokens The list of markets to claim COMP in\\n * @param borrowers Whether or not to claim COMP earned by borrowing\\n * @param suppliers Whether or not to claim COMP earned by supplying\\n */\\n function claimComp(address[] memory holders, CToken[] memory cTokens, bool borrowers, bool suppliers) public {\\n for (uint i = 0; i < cTokens.length; i++) {\\n CToken cToken = cTokens[i];\\n require(markets[address(cToken)].isListed, \\\"market must be listed\\\");\\n if (borrowers == true) {\\n Exp memory borrowIndex = Exp({mantissa: cToken.borrowIndex()});\\n updateCompBorrowIndex(address(cToken), borrowIndex);\\n for (uint j = 0; j < holders.length; j++) {\\n distributeBorrowerComp(address(cToken), holders[j], borrowIndex, true);\\n }\\n }\\n if (suppliers == true) {\\n updateCompSupplyIndex(address(cToken));\\n for (uint j = 0; j < holders.length; j++) {\\n distributeSupplierComp(address(cToken), holders[j], true);\\n }\\n }\\n }\\n }\\n\\n /**\\n * @notice Transfer COMP to the user\\n * @dev Note: If there is not enough COMP, we do not perform the transfer all.\\n * @param user The address of the user to transfer COMP to\\n * @param amount The amount of COMP to (possibly) transfer\\n * @return The amount of COMP which was NOT transferred to the user\\n */\\n function grantCompInternal(address user, uint amount) internal returns (uint) {\\n Comp comp = Comp(getCompAddress());\\n uint compRemaining = comp.balanceOf(address(this));\\n if (amount <= compRemaining) {\\n comp.transfer(user, amount);\\n return 0;\\n }\\n return amount;\\n }\\n\\n /*** Comp Distribution Admin ***/\\n\\n /**\\n * @notice Transfer COMP to the recipient\\n * @dev Note: If there is not enough COMP, we do not perform the transfer all.\\n * @param recipient The address of the recipient to transfer COMP to\\n * @param amount The amount of COMP to (possibly) transfer\\n */\\n function _grantComp(address recipient, uint amount) public {\\n require(adminOrInitializing(), \\\"only admin can grant comp\\\");\\n uint amountLeft = grantCompInternal(recipient, amount);\\n require(amountLeft == 0, \\\"insufficient comp for grant\\\");\\n emit CompGranted(recipient, amount);\\n }\\n\\n /**\\n * @notice Set COMP speed for a single contributor\\n * @param contributor The contributor whose COMP speed to update\\n * @param compSpeed New COMP speed for contributor\\n */\\n function _setContributorCompSpeed(address contributor, uint compSpeed) public {\\n require(adminOrInitializing(), \\\"only admin can set comp speed\\\");\\n\\n // note that COMP speed could be set to 0 to halt liquidity rewards for a contributor\\n updateContributorRewards(contributor);\\n if (compSpeed == 0) {\\n // release storage\\n delete lastContributorBlock[contributor];\\n }\\n lastContributorBlock[contributor] = getBlockNumber();\\n compContributorSpeeds[contributor] = compSpeed;\\n\\n emit ContributorCompSpeedUpdated(contributor, compSpeed);\\n }\\n\\n /**\\n * @notice Set the amount of COMP distributed per block\\n * @param compRate_ The amount of COMP wei per block to distribute\\n */\\n function _setCompRate(uint compRate_) public {\\n require(adminOrInitializing(), \\\"only admin can change comp rate\\\");\\n\\n uint oldRate = compRate;\\n compRate = compRate_;\\n emit NewCompRate(oldRate, compRate_);\\n\\n refreshCompSpeedsInternal();\\n }\\n\\n /**\\n * @notice Add markets to compMarkets, allowing them to earn COMP in the flywheel\\n * @param cTokens The addresses of the markets to add\\n */\\n function _addCompMarkets(address[] memory cTokens) public {\\n require(adminOrInitializing(), \\\"only admin can add comp market\\\");\\n\\n for (uint i = 0; i < cTokens.length; i++) {\\n _addCompMarketInternal(cTokens[i]);\\n }\\n\\n refreshCompSpeedsInternal();\\n }\\n\\n function _addCompMarketInternal(address cToken) internal {\\n Market storage market = markets[cToken];\\n require(market.isListed == true, \\\"comp market is not listed\\\");\\n require(market.isComped == false, \\\"comp market already added\\\");\\n\\n market.isComped = true;\\n emit MarketComped(CToken(cToken), true);\\n\\n if (compSupplyState[cToken].index == 0 && compSupplyState[cToken].block == 0) {\\n compSupplyState[cToken] = CompMarketState({\\n index: compInitialIndex,\\n block: safe32(getBlockNumber(), \\\"block number exceeds 32 bits\\\")\\n });\\n }\\n\\n if (compBorrowState[cToken].index == 0 && compBorrowState[cToken].block == 0) {\\n compBorrowState[cToken] = CompMarketState({\\n index: compInitialIndex,\\n block: safe32(getBlockNumber(), \\\"block number exceeds 32 bits\\\")\\n });\\n }\\n }\\n\\n /**\\n * @notice Remove a market from compMarkets, preventing it from earning COMP in the flywheel\\n * @param cToken The address of the market to drop\\n */\\n function _dropCompMarket(address cToken) public {\\n require(msg.sender == admin, \\\"only admin can drop comp market\\\");\\n\\n Market storage market = markets[cToken];\\n require(market.isComped == true, \\\"market is not a comp market\\\");\\n\\n market.isComped = false;\\n emit MarketComped(CToken(cToken), false);\\n\\n refreshCompSpeedsInternal();\\n }\\n\\n /**\\n * @notice Return all of the markets\\n * @dev The automatic getter may be used to access an individual market.\\n * @return The list of market addresses\\n */\\n function getAllMarkets() public view returns (CToken[] memory) {\\n return allMarkets;\\n }\\n\\n function getBlockNumber() public view returns (uint) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Return the address of the COMP token\\n * @return The address of COMP\\n */\\n function getCompAddress() public view returns (address) {\\n return 0xc00e94Cb662C3520282E6f5717214004A7f26888;\\n }\\n}\\n\",\"keccak256\":\"0xb304abff1f7e652d176e42f867e5ca9bf6b44025c1cc3b142e1a3a0433ee7d82\"},\"contracts/ComptrollerInterface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\ncontract ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n bool public constant isComptroller = true;\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata cTokens) external returns (uint[] memory);\\n function exitMarket(address cToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address cToken, address minter, uint mintAmount) external returns (uint);\\n function mintVerify(address cToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address cToken, address redeemer, uint redeemTokens) external returns (uint);\\n function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address cToken, address borrower, uint borrowAmount) external returns (uint);\\n function borrowVerify(address cToken, address borrower, uint borrowAmount) external;\\n\\n function repayBorrowAllowed(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount) external returns (uint);\\n function repayBorrowVerify(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex) external;\\n\\n function liquidateBorrowAllowed(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount) external returns (uint);\\n function liquidateBorrowVerify(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens) external;\\n\\n function seizeAllowed(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external returns (uint);\\n function seizeVerify(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external;\\n\\n function transferAllowed(address cToken, address src, address dst, uint transferTokens) external returns (uint);\\n function transferVerify(address cToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n uint repayAmount) external view returns (uint, uint);\\n}\\n\",\"keccak256\":\"0xede7670d2dd7b25d0187aecd2c28b7b5ca7d7c1bdac144fbedecf5d4bdd92a6b\"},\"contracts/ComptrollerStorage.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.sol\\\";\\nimport \\\"./PriceOracle.sol\\\";\\n\\ncontract UnitrollerAdminStorage {\\n /**\\n * @notice Administrator for this contract\\n */\\n address public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address public pendingAdmin;\\n\\n /**\\n * @notice Active brains of Unitroller\\n */\\n address public comptrollerImplementation;\\n\\n /**\\n * @notice Pending brains of Unitroller\\n */\\n address public pendingComptrollerImplementation;\\n}\\n\\ncontract ComptrollerV1Storage is UnitrollerAdminStorage {\\n\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n PriceOracle public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives\\n */\\n uint public liquidationIncentiveMantissa;\\n\\n /**\\n * @notice Max number of assets a single account can participate in (borrow or use as collateral)\\n */\\n uint public maxAssets;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\\n */\\n mapping(address => CToken[]) public accountAssets;\\n\\n}\\n\\ncontract ComptrollerV2Storage is ComptrollerV1Storage {\\n struct Market {\\n /// @notice Whether or not this market is listed\\n bool isListed;\\n\\n /**\\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\\n * For instance, 0.9 to allow borrowing 90% of collateral value.\\n * Must be between 0 and 1, and stored as a mantissa.\\n */\\n uint collateralFactorMantissa;\\n\\n /// @notice Per-market mapping of \\\"accounts in this asset\\\"\\n mapping(address => bool) accountMembership;\\n\\n /// @notice Whether or not this market receives COMP\\n bool isComped;\\n }\\n\\n /**\\n * @notice Official mapping of cTokens -> Market metadata\\n * @dev Used e.g. to determine if a market is supported\\n */\\n mapping(address => Market) public markets;\\n\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n * Actions which allow users to remove their own assets cannot be paused.\\n * Liquidation / seizing / transfer can only be paused globally, not by market.\\n */\\n address public pauseGuardian;\\n bool public _mintGuardianPaused;\\n bool public _borrowGuardianPaused;\\n bool public transferGuardianPaused;\\n bool public seizeGuardianPaused;\\n mapping(address => bool) public mintGuardianPaused;\\n mapping(address => bool) public borrowGuardianPaused;\\n}\\n\\ncontract ComptrollerV3Storage is ComptrollerV2Storage {\\n struct CompMarketState {\\n /// @notice The market's last updated compBorrowIndex or compSupplyIndex\\n uint224 index;\\n\\n /// @notice The block number the index was last updated at\\n uint32 block;\\n }\\n\\n /// @notice A list of all markets\\n CToken[] public allMarkets;\\n\\n /// @notice The rate at which the flywheel distributes COMP, per block\\n uint public compRate;\\n\\n /// @notice The portion of compRate that each market currently receives\\n mapping(address => uint) public compSpeeds;\\n\\n /// @notice The COMP market supply state for each market\\n mapping(address => CompMarketState) public compSupplyState;\\n\\n /// @notice The COMP market borrow state for each market\\n mapping(address => CompMarketState) public compBorrowState;\\n\\n /// @notice The COMP borrow index for each market for each supplier as of the last time they accrued COMP\\n mapping(address => mapping(address => uint)) public compSupplierIndex;\\n\\n /// @notice The COMP borrow index for each market for each borrower as of the last time they accrued COMP\\n mapping(address => mapping(address => uint)) public compBorrowerIndex;\\n\\n /// @notice The COMP accrued but not yet transferred to each user\\n mapping(address => uint) public compAccrued;\\n}\\n\\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\\n // @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\\n address public borrowCapGuardian;\\n\\n // @notice Borrow caps enforced by borrowAllowed for each cToken address. Defaults to zero which corresponds to unlimited borrowing.\\n mapping(address => uint) public borrowCaps;\\n}\\n\\ncontract ComptrollerV5Storage is ComptrollerV4Storage {\\n /// @notice The portion of COMP that each contributor receives per block\\n mapping(address => uint) public compContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's COMP rewards have been allocated\\n mapping(address => uint) public lastContributorBlock;\\n}\\n\",\"keccak256\":\"0x5db970485549f493618b5e36bfd4d799d4f8701a136bf71ed6e0117e1ed8c254\"},\"contracts/EIP20Interface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title ERC 20 Token Standard Interface\\n * https://eips.ethereum.org/EIPS/eip-20\\n */\\ninterface EIP20Interface {\\n function name() external view returns (string memory);\\n function symbol() external view returns (string memory);\\n function decimals() external view returns (uint8);\\n\\n /**\\n * @notice Get the total number of tokens in circulation\\n * @return The supply of tokens\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @notice Gets the balance of the specified address\\n * @param owner The address from which the balance will be retrieved\\n * @return The balance\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transfer(address dst, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferFrom(address src, address dst, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (-1 means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (-1 means infinite)\\n */\\n function allowance(address owner, address spender) external view returns (uint256 remaining);\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n}\\n\",\"keccak256\":\"0xfd8ed2eac6d0b4d9ee6b32628ba68bae17544b66f190a5f7ce0c6ad024579dc8\"},\"contracts/EIP20NonStandardInterface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title EIP20NonStandardInterface\\n * @dev Version of ERC20 with no return values for `transfer` and `transferFrom`\\n * See https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\\n */\\ninterface EIP20NonStandardInterface {\\n\\n /**\\n * @notice Get the total number of tokens in circulation\\n * @return The supply of tokens\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @notice Gets the balance of the specified address\\n * @param owner The address from which the balance will be retrieved\\n * @return The balance\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n ///\\n /// !!!!!!!!!!!!!!\\n /// !!! NOTICE !!! `transfer` does not return a value, in violation of the ERC-20 specification\\n /// !!!!!!!!!!!!!!\\n ///\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n */\\n function transfer(address dst, uint256 amount) external;\\n\\n ///\\n /// !!!!!!!!!!!!!!\\n /// !!! NOTICE !!! `transferFrom` does not return a value, in violation of the ERC-20 specification\\n /// !!!!!!!!!!!!!!\\n ///\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n */\\n function transferFrom(address src, address dst, uint256 amount) external;\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent\\n */\\n function allowance(address owner, address spender) external view returns (uint256 remaining);\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n}\\n\",\"keccak256\":\"0x9719f12e4b80b51147ac195553a198cf8b0c516e7e4d04fc324a23ed15cbafb2\"},\"contracts/ErrorReporter.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\ncontract ComptrollerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\",\"keccak256\":\"0x5179afb1071c0fd555e5c1f1d2565f72dbe1740cc3dd02f6e52037f150afc5c9\"},\"contracts/Exponential.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CarefulMath.sol\\\";\\nimport \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @dev Legacy contract for compatibility reasons with existing contracts that still use MathError\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: rational}));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({mantissa: result}));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({mantissa: result}));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: scaledMantissa}));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: descaledMantissa}));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) pure internal returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({mantissa: 0}));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({mantissa: product}));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) pure internal returns (MathError, Exp memory) {\\n return mulExp(Exp({mantissa: a}), Exp({mantissa: b}));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) pure internal returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6ff054d65a0289dbb43c9f437d6909f9cf1207c9b8f984b3cb8e97a9de76a434\"},\"contracts/ExponentialNoError.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\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 Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) pure internal returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) pure internal returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) pure internal returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) pure internal returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) pure internal returns (uint224) {\\n require(n < 2**224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) pure internal returns (uint32) {\\n require(n < 2**32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: add_(a.mantissa, b.mantissa)});\\n }\\n\\n function add_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: add_(a.mantissa, b.mantissa)});\\n }\\n\\n function add_(uint a, uint b) pure internal returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: sub_(a.mantissa, b.mantissa)});\\n }\\n\\n function sub_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: sub_(a.mantissa, b.mantissa)});\\n }\\n\\n function sub_(uint a, uint b) pure internal returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: mul_(a.mantissa, b.mantissa) / expScale});\\n }\\n\\n function mul_(Exp memory a, uint b) pure internal returns (Exp memory) {\\n return Exp({mantissa: mul_(a.mantissa, b)});\\n }\\n\\n function mul_(uint a, Exp memory b) pure internal returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: mul_(a.mantissa, b.mantissa) / doubleScale});\\n }\\n\\n function mul_(Double memory a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: mul_(a.mantissa, b)});\\n }\\n\\n function mul_(uint a, Double memory b) pure internal returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) pure internal returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) pure internal 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) pure internal returns (Exp memory) {\\n return Exp({mantissa: div_(mul_(a.mantissa, expScale), b.mantissa)});\\n }\\n\\n function div_(Exp memory a, uint b) pure internal returns (Exp memory) {\\n return Exp({mantissa: div_(a.mantissa, b)});\\n }\\n\\n function div_(uint a, Exp memory b) pure internal returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa)});\\n }\\n\\n function div_(Double memory a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(a.mantissa, b)});\\n }\\n\\n function div_(uint a, Double memory b) pure internal returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) pure internal returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(mul_(a, doubleScale), b)});\\n }\\n}\\n\",\"keccak256\":\"0x7cb184b7cee71a5e707053dfba7eebbd46f11974004028100510ccce19b6694d\"},\"contracts/Governance/Comp.sol\":{\"content\":\"pragma solidity ^0.5.16;\\npragma experimental ABIEncoderV2;\\n\\ncontract Comp {\\n /// @notice EIP-20 token name for this token\\n string public constant name = \\\"Compound\\\";\\n\\n /// @notice EIP-20 token symbol for this token\\n string public constant symbol = \\\"COMP\\\";\\n\\n /// @notice EIP-20 token decimals for this token\\n uint8 public constant decimals = 18;\\n\\n /// @notice Total number of tokens in circulation\\n uint public constant totalSupply = 10000000e18; // 10 million Comp\\n\\n /// @notice Allowance amounts on behalf of others\\n mapping (address => mapping (address => uint96)) internal allowances;\\n\\n /// @notice Official record of token balances for each account\\n mapping (address => uint96) internal balances;\\n\\n /// @notice A record of each accounts delegate\\n mapping (address => address) public delegates;\\n\\n /// @notice A checkpoint for marking number of votes from a given block\\n struct Checkpoint {\\n uint32 fromBlock;\\n uint96 votes;\\n }\\n\\n /// @notice A record of votes checkpoints for each account, by index\\n mapping (address => mapping (uint32 => Checkpoint)) public checkpoints;\\n\\n /// @notice The number of checkpoints for each account\\n mapping (address => uint32) public numCheckpoints;\\n\\n /// @notice The EIP-712 typehash for the contract's domain\\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\\\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\\\");\\n\\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\\\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\\\");\\n\\n /// @notice A record of states for signing / validating signatures\\n mapping (address => uint) public nonces;\\n\\n /// @notice An event thats emitted when an account changes its delegate\\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\\n\\n /// @notice An event thats emitted when a delegate account's vote balance changes\\n event DelegateVotesChanged(address indexed delegate, uint previousBalance, uint newBalance);\\n\\n /// @notice The standard EIP-20 transfer event\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n\\n /// @notice The standard EIP-20 approval event\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n\\n /**\\n * @notice Construct a new Comp token\\n * @param account The initial account to grant all the tokens\\n */\\n constructor(address account) public {\\n balances[account] = uint96(totalSupply);\\n emit Transfer(address(0), account, totalSupply);\\n }\\n\\n /**\\n * @notice Get the number of tokens `spender` is approved to spend on behalf of `account`\\n * @param account The address of the account holding the funds\\n * @param spender The address of the account spending the funds\\n * @return The number of tokens approved\\n */\\n function allowance(address account, address spender) external view returns (uint) {\\n return allowances[account][spender];\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param rawAmount The number of tokens that are approved (2^256-1 means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint rawAmount) external returns (bool) {\\n uint96 amount;\\n if (rawAmount == uint(-1)) {\\n amount = uint96(-1);\\n } else {\\n amount = safe96(rawAmount, \\\"Comp::approve: amount exceeds 96 bits\\\");\\n }\\n\\n allowances[msg.sender][spender] = amount;\\n\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the number of tokens held by the `account`\\n * @param account The address of the account to get the balance of\\n * @return The number of tokens held\\n */\\n function balanceOf(address account) external view returns (uint) {\\n return balances[account];\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param rawAmount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transfer(address dst, uint rawAmount) external returns (bool) {\\n uint96 amount = safe96(rawAmount, \\\"Comp::transfer: amount exceeds 96 bits\\\");\\n _transferTokens(msg.sender, dst, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param rawAmount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferFrom(address src, address dst, uint rawAmount) external returns (bool) {\\n address spender = msg.sender;\\n uint96 spenderAllowance = allowances[src][spender];\\n uint96 amount = safe96(rawAmount, \\\"Comp::approve: amount exceeds 96 bits\\\");\\n\\n if (spender != src && spenderAllowance != uint96(-1)) {\\n uint96 newAllowance = sub96(spenderAllowance, amount, \\\"Comp::transferFrom: transfer amount exceeds spender allowance\\\");\\n allowances[src][spender] = newAllowance;\\n\\n emit Approval(src, spender, newAllowance);\\n }\\n\\n _transferTokens(src, dst, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Delegate votes from `msg.sender` to `delegatee`\\n * @param delegatee The address to delegate votes to\\n */\\n function delegate(address delegatee) public {\\n return _delegate(msg.sender, delegatee);\\n }\\n\\n /**\\n * @notice Delegates votes from signatory to `delegatee`\\n * @param delegatee The address to delegate votes to\\n * @param nonce The contract state required to match the signature\\n * @param expiry The time at which to expire the signature\\n * @param v The recovery byte of the signature\\n * @param r Half of the ECDSA signature pair\\n * @param s Half of the ECDSA signature pair\\n */\\n function delegateBySig(address delegatee, uint nonce, uint expiry, uint8 v, bytes32 r, bytes32 s) public {\\n bytes32 domainSeparator = keccak256(abi.encode(DOMAIN_TYPEHASH, keccak256(bytes(name)), getChainId(), address(this)));\\n bytes32 structHash = keccak256(abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry));\\n bytes32 digest = keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash));\\n address signatory = ecrecover(digest, v, r, s);\\n require(signatory != address(0), \\\"Comp::delegateBySig: invalid signature\\\");\\n require(nonce == nonces[signatory]++, \\\"Comp::delegateBySig: invalid nonce\\\");\\n require(now <= expiry, \\\"Comp::delegateBySig: signature expired\\\");\\n return _delegate(signatory, delegatee);\\n }\\n\\n /**\\n * @notice Gets the current votes balance for `account`\\n * @param account The address to get votes balance\\n * @return The number of current votes for `account`\\n */\\n function getCurrentVotes(address account) external view returns (uint96) {\\n uint32 nCheckpoints = numCheckpoints[account];\\n return nCheckpoints > 0 ? checkpoints[account][nCheckpoints - 1].votes : 0;\\n }\\n\\n /**\\n * @notice Determine the prior number of votes for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param account The address of the account to check\\n * @param blockNumber The block number to get the vote balance at\\n * @return The number of votes the account had as of the given block\\n */\\n function getPriorVotes(address account, uint blockNumber) public view returns (uint96) {\\n require(blockNumber < block.number, \\\"Comp::getPriorVotes: not yet determined\\\");\\n\\n uint32 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (checkpoints[account][nCheckpoints - 1].fromBlock <= blockNumber) {\\n return checkpoints[account][nCheckpoints - 1].votes;\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[account][0].fromBlock > blockNumber) {\\n return 0;\\n }\\n\\n uint32 lower = 0;\\n uint32 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[account][center];\\n if (cp.fromBlock == blockNumber) {\\n return cp.votes;\\n } else if (cp.fromBlock < blockNumber) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return checkpoints[account][lower].votes;\\n }\\n\\n function _delegate(address delegator, address delegatee) internal {\\n address currentDelegate = delegates[delegator];\\n uint96 delegatorBalance = balances[delegator];\\n delegates[delegator] = delegatee;\\n\\n emit DelegateChanged(delegator, currentDelegate, delegatee);\\n\\n _moveDelegates(currentDelegate, delegatee, delegatorBalance);\\n }\\n\\n function _transferTokens(address src, address dst, uint96 amount) internal {\\n require(src != address(0), \\\"Comp::_transferTokens: cannot transfer from the zero address\\\");\\n require(dst != address(0), \\\"Comp::_transferTokens: cannot transfer to the zero address\\\");\\n\\n balances[src] = sub96(balances[src], amount, \\\"Comp::_transferTokens: transfer amount exceeds balance\\\");\\n balances[dst] = add96(balances[dst], amount, \\\"Comp::_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 && amount > 0) {\\n if (srcRep != address(0)) {\\n uint32 srcRepNum = numCheckpoints[srcRep];\\n uint96 srcRepOld = srcRepNum > 0 ? checkpoints[srcRep][srcRepNum - 1].votes : 0;\\n uint96 srcRepNew = sub96(srcRepOld, amount, \\\"Comp::_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 > 0 ? checkpoints[dstRep][dstRepNum - 1].votes : 0;\\n uint96 dstRepNew = add96(dstRepOld, amount, \\\"Comp::_moveVotes: vote amount overflows\\\");\\n _writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew);\\n }\\n }\\n }\\n\\n function _writeCheckpoint(address delegatee, uint32 nCheckpoints, uint96 oldVotes, uint96 newVotes) internal {\\n uint32 blockNumber = safe32(block.number, \\\"Comp::_writeCheckpoint: block number exceeds 32 bits\\\");\\n\\n if (nCheckpoints > 0 && checkpoints[delegatee][nCheckpoints - 1].fromBlock == blockNumber) {\\n checkpoints[delegatee][nCheckpoints - 1].votes = newVotes;\\n } else {\\n checkpoints[delegatee][nCheckpoints] = Checkpoint(blockNumber, newVotes);\\n numCheckpoints[delegatee] = nCheckpoints + 1;\\n }\\n\\n emit DelegateVotesChanged(delegatee, oldVotes, newVotes);\\n }\\n\\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\\n require(n < 2**32, errorMessage);\\n return uint32(n);\\n }\\n\\n function safe96(uint n, string memory errorMessage) internal pure returns (uint96) {\\n require(n < 2**96, errorMessage);\\n return uint96(n);\\n }\\n\\n function add96(uint96 a, uint96 b, string memory errorMessage) internal pure returns (uint96) {\\n uint96 c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub96(uint96 a, uint96 b, string memory errorMessage) internal pure returns (uint96) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function getChainId() internal pure returns (uint) {\\n uint256 chainId;\\n assembly { chainId := chainid() }\\n return chainId;\\n }\\n}\\n\",\"keccak256\":\"0x539f7158013dd91efd3ad42dc6a56e0f7aebdca06063d40ce7b6e9a981b726a3\"},\"contracts/InterestRateModel.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Compound's InterestRateModel Interface\\n * @author Compound\\n */\\ncontract InterestRateModel {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint cash, uint borrows, uint reserves) external view returns (uint);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) external view returns (uint);\\n\\n}\\n\",\"keccak256\":\"0x929282d73c79e6d700ebe79f9fafc1e414b3848acff5a56d6740afd1dc908678\"},\"contracts/PriceOracle.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.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 cToken asset\\n * @param cToken The cToken to get the underlying price of\\n * @return The underlying asset price mantissa (scaled by 1e18).\\n * Zero means the price is unavailable.\\n */\\n function getUnderlyingPrice(CToken cToken) external view returns (uint);\\n}\\n\",\"keccak256\":\"0xe79ebc23bba508eb2479e7b3340abf566da1ab62131f106aee1aac3dc53816ef\"},\"contracts/Unitroller.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ErrorReporter.sol\\\";\\nimport \\\"./ComptrollerStorage.sol\\\";\\n/**\\n * @title ComptrollerCore\\n * @dev Storage for the comptroller is at this address, while execution is delegated to the `comptrollerImplementation`.\\n * CTokens should reference this contract as their comptroller.\\n */\\ncontract Unitroller is UnitrollerAdminStorage, ComptrollerErrorReporter {\\n\\n /**\\n * @notice Emitted when pendingComptrollerImplementation is changed\\n */\\n event NewPendingImplementation(address oldPendingImplementation, address newPendingImplementation);\\n\\n /**\\n * @notice Emitted when pendingComptrollerImplementation is accepted, which means comptroller implementation is updated\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Emitted when pendingAdmin is accepted, which means admin is updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n constructor() public {\\n // Set admin to caller\\n admin = msg.sender;\\n }\\n\\n /*** Admin Functions ***/\\n function _setPendingImplementation(address newPendingImplementation) public returns (uint) {\\n\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_IMPLEMENTATION_OWNER_CHECK);\\n }\\n\\n address oldPendingImplementation = pendingComptrollerImplementation;\\n\\n pendingComptrollerImplementation = newPendingImplementation;\\n\\n emit NewPendingImplementation(oldPendingImplementation, pendingComptrollerImplementation);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts new implementation of comptroller. msg.sender must be pendingImplementation\\n * @dev Admin function for new implementation to accept it's role as implementation\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptImplementation() public returns (uint) {\\n // Check caller is pendingImplementation and pendingImplementation \\u2260 address(0)\\n if (msg.sender != pendingComptrollerImplementation || pendingComptrollerImplementation == address(0)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldImplementation = comptrollerImplementation;\\n address oldPendingImplementation = pendingComptrollerImplementation;\\n\\n comptrollerImplementation = pendingComptrollerImplementation;\\n\\n pendingComptrollerImplementation = address(0);\\n\\n emit NewImplementation(oldImplementation, comptrollerImplementation);\\n emit NewPendingImplementation(oldPendingImplementation, pendingComptrollerImplementation);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPendingAdmin(address newPendingAdmin) public returns (uint) {\\n // Check caller = admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\\n }\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptAdmin() public returns (uint) {\\n // Check caller is pendingAdmin and pendingAdmin \\u2260 address(0)\\n if (msg.sender != pendingAdmin || msg.sender == address(0)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = address(0);\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return 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 () payable external {\\n // delegate all other functions to current implementation\\n (bool success, ) = comptrollerImplementation.delegatecall(msg.data);\\n\\n assembly {\\n let free_mem_ptr := mload(0x40)\\n returndatacopy(free_mem_ptr, 0, returndatasize)\\n\\n switch success\\n case 0 { revert(free_mem_ptr, returndatasize) }\\n default { return(free_mem_ptr, returndatasize) }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x51f81451eab9d5c4849507e724f2b2c53e41f54e5359fdbeae89432a727c16df\"}},\"version\":1}" + }, + "contracts/ComptrollerG7.sol:ComptrollerG7": { + "abi": "[{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"action\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"pauseState\",\"type\":\"bool\"}],\"name\":\"ActionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"action\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"pauseState\",\"type\":\"bool\"}],\"name\":\"ActionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"CompGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSpeed\",\"type\":\"uint256\"}],\"name\":\"CompSpeedUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"contributor\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSpeed\",\"type\":\"uint256\"}],\"name\":\"ContributorCompSpeedUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compBorrowIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedBorrowerComp\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"supplier\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compSupplyIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedSupplierComp\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketEntered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketExited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"MarketListed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newBorrowCap\",\"type\":\"uint256\"}],\"name\":\"NewBorrowCap\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldBorrowCapGuardian\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newBorrowCapGuardian\",\"type\":\"address\"}],\"name\":\"NewBorrowCapGuardian\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCloseFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCloseFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCollateralFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCollateralFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldLiquidationIncentiveMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"NewLiquidationIncentive\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldPauseGuardian\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"NewPauseGuardian\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"oldPriceOracle\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"newPriceOracle\",\"type\":\"address\"}],\"name\":\"NewPriceOracle\",\"type\":\"event\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract Unitroller\",\"name\":\"unitroller\",\"type\":\"address\"}],\"name\":\"_become\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"_grantComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"newBorrowCapGuardian\",\"type\":\"address\"}],\"name\":\"_setBorrowCapGuardian\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setBorrowPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCloseFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCollateralFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"compSpeed\",\"type\":\"uint256\"}],\"name\":\"_setCompSpeed\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"contributor\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"compSpeed\",\"type\":\"uint256\"}],\"name\":\"_setContributorCompSpeed\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"_setLiquidationIncentive\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"cTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"newBorrowCaps\",\"type\":\"uint256[]\"}],\"name\":\"_setMarketBorrowCaps\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setMintPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"_setPauseGuardian\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"newOracle\",\"type\":\"address\"}],\"name\":\"_setPriceOracle\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setSeizePaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setTransferPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"_supportMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allMarkets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"borrowCapGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"checkMembership\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"},{\"internalType\":\"contract CToken[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"holders\",\"type\":\"address[]\"},{\"internalType\":\"contract CToken[]\",\"name\":\"cTokens\",\"type\":\"address[]\"},{\"internalType\":\"bool\",\"name\":\"borrowers\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"suppliers\",\"type\":\"bool\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compAccrued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compBorrowState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compBorrowerIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compContributorSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compInitialIndex\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSupplierIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSupplyState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"enterMarkets\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenAddress\",\"type\":\"address\"}],\"name\":\"exitMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getAllMarkets\",\"outputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAssetsIn\",\"outputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getCompAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenModify\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"getHypotheticalAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"isComptroller\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"lastContributorBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateCalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"liquidationIncentiveMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"markets\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isComped\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"mintAmount\",\"type\":\"uint256\"}],\"name\":\"mintAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualMintAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"mintTokens\",\"type\":\"uint256\"}],\"name\":\"mintVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"repayBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowerIndex\",\"type\":\"uint256\"}],\"name\":\"repayBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"seizeGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"transferGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"contributor\",\"type\":\"address\"}],\"name\":\"updateContributorRewards\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + "bin": "608060405234801561001057600080fd5b50600080546001600160a01b0319163317905561562580620000336000396000f3fe608060405234801561001057600080fd5b50600436106104485760003560e01c80636d154ea511610241578063b21be7fd1161013b578063da3d454c116100c3578063e875544611610087578063e8755446146111ed578063e9af0292146111f5578063eabe7d911461121b578063ede4edd014611251578063f851a4401461127757610448565b8063da3d454c1461114f578063dce1544914611185578063dcfbc0c7146111b1578063e4028eee146111b9578063e6653f3d146111e557610448565b8063c29982381161010a578063c299823814610fc5578063c488847b14611066578063ca0af043146110b5578063cc7ebdc4146110e3578063d02f73511461110957610448565b8063b21be7fd14610f2d578063bb82aa5e14610f5b578063bdcdc25814610f63578063bea6b8b814610f9f57610448565b8063929fe9a1116101c9578063a7f0e2311161018d578063a7f0e23114610e7b578063aa90075414610e9f578063abfceffc14610ea7578063ac0b0bb714610f1d578063b0772d0b14610f2557610448565b8063929fe9a114610df157806394b2294b14610e1f578063986ab83814610e275780639d1b5a0a14610e4d578063a76b3fda14610e5557610448565b80637dc0d1d0116102105780637dc0d1d014610d5457806387f7630314610d5c5780638c57804e14610d645780638e8f294b14610d8a5780638ebf636414610dd257610448565b80636d154ea514610c9c5780636d35bf9114610cc2578063731f0c2b14610d08578063741b252514610d2e57610448565b8063434caf251161035257806355ee1fe1116102da5780635fc7e71e1161029e5780635fc7e71e146109e2578063607ef6c114610a285780636810dfa614610ae65780636a56947e14610c125780636b79c38d14610c4e57610448565b806355ee1fe11461090e578063598ee1cb146109345780635c778605146109605780635ec88c79146109965780635f5af1aa146109bc57610448565b80634e79238f116103215780634e79238f146108085780634ef4c3e1146108625780634fd42e171461089857806351dff989146108b557806352d84d1e146108f157610448565b8063434caf251461076257806347ef3b3b1461078e5780634a584432146107da5780634ada90af1461080057610448565b806326782247116103d5578063391957d7116103a4578063391957d7146106c25780633bcf7ec1146106e85780633c94786f1461071657806341c728b91461071e57806342cbb15c1461075a57610448565b8063267822471461065257806327efe3cb1461065a5780632d70db7814610686578063317b0b77146106a557610448565b80631d7b33d71161041c5780631d7b33d7146105705780631ededc91146105a857806321af4569146105ea57806324008a621461060e57806324a3d6221461064a57610448565b80627e3dd21461044d57806318c882a5146104695780631c3db2e0146104975780631d504dc61461054a575b600080fd5b61045561127f565b604080519115158252519081900360200190f35b6104556004803603604081101561047f57600080fd5b506001600160a01b0381351690602001351515611284565b610548600480360360408110156104ad57600080fd5b6001600160a01b038235169190810190604081016020820135600160201b8111156104d757600080fd5b8201836020820111156104e957600080fd5b803590602001918460208302840111600160201b8311171561050a57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550611424945050505050565b005b6105486004803603602081101561056057600080fd5b50356001600160a01b0316611486565b6105966004803603602081101561058657600080fd5b50356001600160a01b03166115e5565b60408051918252519081900360200190f35b610548600480360360a08110156105be57600080fd5b506001600160a01b038135811691602081013582169160408201351690606081013590608001356115f7565b6105f26115fe565b604080516001600160a01b039092168252519081900360200190f35b6105966004803603608081101561062457600080fd5b506001600160a01b0381358116916020810135821691604082013516906060013561160d565b6105f26116d4565b6105f26116e3565b6105486004803603604081101561067057600080fd5b506001600160a01b0381351690602001356116f2565b6104556004803603602081101561069c57600080fd5b503515156117f5565b610596600480360360208110156106bb57600080fd5b503561192f565b610548600480360360208110156106d857600080fd5b50356001600160a01b03166119dc565b610455600480360360408110156106fe57600080fd5b506001600160a01b0381351690602001351515611a88565b610455611c23565b6105486004803603608081101561073457600080fd5b506001600160a01b03813581169160208101359091169060408101359060600135611c33565b610596611c39565b6105486004803603604081101561077857600080fd5b506001600160a01b038135169060200135611c3e565b610548600480360360c08110156107a457600080fd5b506001600160a01b0381358116916020810135821691604082013581169160608101359091169060808101359060a00135611ca5565b610596600480360360208110156107f057600080fd5b50356001600160a01b0316611cad565b610596611cbf565b6108446004803603608081101561081e57600080fd5b506001600160a01b03813581169160208101359091169060408101359060600135611cc5565b60408051938452602084019290925282820152519081900360600190f35b6105966004803603606081101561087857600080fd5b506001600160a01b03813581169160208101359091169060400135611cff565b610596600480360360208110156108ae57600080fd5b5035611da5565b610548600480360360808110156108cb57600080fd5b506001600160a01b03813581169160208101359091169060408101359060600135611e15565b6105f26004803603602081101561090757600080fd5b5035611e69565b6105966004803603602081101561092457600080fd5b50356001600160a01b0316611e90565b6105486004803603604081101561094a57600080fd5b506001600160a01b038135169060200135611f15565b6105486004803603606081101561097657600080fd5b506001600160a01b03813581169160208101359091169060400135612010565b610844600480360360208110156109ac57600080fd5b50356001600160a01b0316612015565b610596600480360360208110156109d257600080fd5b50356001600160a01b031661204a565b610596600480360360a08110156109f857600080fd5b506001600160a01b03813581169160208101358216916040820135811691606081013590911690608001356120ce565b61054860048036036040811015610a3e57600080fd5b810190602081018135600160201b811115610a5857600080fd5b820183602082011115610a6a57600080fd5b803590602001918460208302840111600160201b83111715610a8b57600080fd5b919390929091602081019035600160201b811115610aa857600080fd5b820183602082011115610aba57600080fd5b803590602001918460208302840111600160201b83111715610adb57600080fd5b509092509050612233565b61054860048036036080811015610afc57600080fd5b810190602081018135600160201b811115610b1657600080fd5b820183602082011115610b2857600080fd5b803590602001918460208302840111600160201b83111715610b4957600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b811115610b9857600080fd5b820183602082011115610baa57600080fd5b803590602001918460208302840111600160201b83111715610bcb57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295505050508035151591506020013515156123c3565b61054860048036036080811015610c2857600080fd5b506001600160a01b03813581169160208101358216916040820135169060600135611c33565b610c7460048036036020811015610c6457600080fd5b50356001600160a01b031661264c565b604080516001600160e01b03909316835263ffffffff90911660208301528051918290030190f35b61045560048036036020811015610cb257600080fd5b50356001600160a01b0316612676565b610548600480360360a0811015610cd857600080fd5b506001600160a01b03813581169160208101358216916040820135811691606081013590911690608001356115f7565b61045560048036036020811015610d1e57600080fd5b50356001600160a01b031661268b565b61054860048036036020811015610d4457600080fd5b50356001600160a01b03166126a0565b6105f2612763565b610455612772565b610c7460048036036020811015610d7a57600080fd5b50356001600160a01b0316612782565b610db060048036036020811015610da057600080fd5b50356001600160a01b03166127ac565b6040805193151584526020840192909252151582820152519081900360600190f35b61045560048036036020811015610de857600080fd5b503515156127d2565b61045560048036036040811015610e0757600080fd5b506001600160a01b038135811691602001351661290b565b61059661293e565b61059660048036036020811015610e3d57600080fd5b50356001600160a01b0316612944565b6105f2612956565b61059660048036036020811015610e6b57600080fd5b50356001600160a01b031661296e565b610e83612acb565b604080516001600160e01b039092168252519081900360200190f35b610596612ade565b610ecd60048036036020811015610ebd57600080fd5b50356001600160a01b0316612ae4565b60408051602080825283518183015283519192839290830191858101910280838360005b83811015610f09578181015183820152602001610ef1565b505050509050019250505060405180910390f35b610455612b6d565b610ecd612b7d565b61059660048036036040811015610f4357600080fd5b506001600160a01b0381358116916020013516612bdf565b6105f2612bfc565b61059660048036036080811015610f7957600080fd5b506001600160a01b03813581169160208101358216916040820135169060600135612c0b565b61059660048036036020811015610fb557600080fd5b50356001600160a01b0316612c9b565b610ecd60048036036020811015610fdb57600080fd5b810190602081018135600160201b811115610ff557600080fd5b82018360208201111561100757600080fd5b803590602001918460208302840111600160201b8311171561102857600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550612cad945050505050565b61109c6004803603606081101561107c57600080fd5b506001600160a01b03813581169160208101359091169060400135612d44565b6040805192835260208301919091528051918290030190f35b610596600480360360408110156110cb57600080fd5b506001600160a01b0381358116916020013516612f6c565b610596600480360360208110156110f957600080fd5b50356001600160a01b0316612f89565b610596600480360360a081101561111f57600080fd5b506001600160a01b0381358116916020810135821691604082013581169160608101359091169060800135612f9b565b6105966004803603606081101561116557600080fd5b506001600160a01b0381358116916020810135909116906040013561314f565b6105f26004803603604081101561119b57600080fd5b506001600160a01b038135169060200135613529565b6105f261355e565b610596600480360360408110156111cf57600080fd5b506001600160a01b03813516906020013561356d565b61045561371d565b61059661372d565b6105486004803603602081101561120b57600080fd5b50356001600160a01b0316613733565b6105966004803603606081101561123157600080fd5b506001600160a01b03813581169160208101359091169060400135613797565b6105966004803603602081101561126757600080fd5b50356001600160a01b03166137d2565b6105f2613ae5565b600181565b6001600160a01b03821660009081526009602052604081205460ff166112db5760405162461bcd60e51b81526004018080602001828103825260288152602001806154db6028913960400191505060405180910390fd5b600a546001600160a01b03163314806112fe57506000546001600160a01b031633145b6113395760405162461bcd60e51b81526004018080602001828103825260278152602001806155036027913960400191505060405180910390fd5b6000546001600160a01b031633148061135457506001821515145b61139e576040805162461bcd60e51b81526020600482015260166024820152756f6e6c792061646d696e2063616e20756e706175736560501b604482015290519081900360640190fd5b6001600160a01b0383166000818152600c6020908152604091829020805486151560ff199091168117909155825193845283830152606090830181905260069083015265426f72726f7760d01b6080830152517f71aec636243f9709bb0007ae15e9afb8150ab01716d75fd7573be5cc096e03b09181900360a00190a150805b92915050565b60408051600180825281830190925260609160208083019080388339019050509050828160008151811061145457fe5b60200260200101906001600160a01b031690816001600160a01b03168152505061148181836001806123c3565b505050565b806001600160a01b031663f851a4406040518163ffffffff1660e01b815260040160206040518083038186803b1580156114bf57600080fd5b505afa1580156114d3573d6000803e3d6000fd5b505050506040513d60208110156114e957600080fd5b50516001600160a01b031633146115315760405162461bcd60e51b81526004018080602001828103825260278152602001806155ca6027913960400191505060405180910390fd5b806001600160a01b031663c1e803346040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561156c57600080fd5b505af1158015611580573d6000803e3d6000fd5b505050506040513d602081101561159657600080fd5b5051156115e2576040805162461bcd60e51b815260206004820152601560248201527418da185b99d9481b9bdd08185d5d1a1bdc9a5e9959605a1b604482015290519081900360640190fd5b50565b600f6020526000908152604090205481565b5050505050565b6015546001600160a01b031681565b6001600160a01b03841660009081526009602052604081205460ff16611635575060096116cc565b61163d61541b565b6040518060200160405280876001600160a01b031663aa5af0fd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561168157600080fd5b505afa158015611695573d6000803e3d6000fd5b505050506040513d60208110156116ab57600080fd5b5051905290506116bb8682613af4565b6116c6868583613d7c565b60009150505b949350505050565b600a546001600160a01b031681565b6001546001600160a01b031681565b6116fa613f13565b61174b576040805162461bcd60e51b815260206004820152601960248201527f6f6e6c792061646d696e2063616e206772616e7420636f6d7000000000000000604482015290519081900360640190fd5b60006117578383613f3c565b905080156117ac576040805162461bcd60e51b815260206004820152601b60248201527f696e73756666696369656e7420636f6d7020666f72206772616e740000000000604482015290519081900360640190fd5b604080516001600160a01b03851681526020810184905281517f98b2f82a3a07f223a0be64b3d0f47711c64dccd1feafb94aa28156b38cd9695c929181900390910190a1505050565b600a546000906001600160a01b031633148061181b57506000546001600160a01b031633145b6118565760405162461bcd60e51b81526004018080602001828103825260278152602001806155036027913960400191505060405180910390fd5b6000546001600160a01b031633148061187157506001821515145b6118bb576040805162461bcd60e51b81526020600482015260166024820152756f6e6c792061646d696e2063616e20756e706175736560501b604482015290519081900360640190fd5b600a8054831515600160b81b810260ff60b81b1990921691909117909155604080516020810192909252808252600582820152645365697a6560d81b6060830152517fef159d9a32b2472e32b098f954f3ce62d232939f1c207070b584df1814de2de09181900360800190a150805b919050565b600080546001600160a01b0316331461198f576040805162461bcd60e51b815260206004820152601f60248201527f6f6e6c792061646d696e2063616e2073657420636c6f736520666163746f7200604482015290519081900360640190fd5b6005805490839055604080518281526020810185905281517f3b9670cf975d26958e754b57098eaa2ac914d8d2a31b83257997b9f346110fd9929181900390910190a160005b9392505050565b6000546001600160a01b03163314611a255760405162461bcd60e51b815260040180806020018281038252602681526020018061552a6026913960400191505060405180910390fd5b601580546001600160a01b038381166001600160a01b0319831681179093556040805191909216808252602082019390935281517feda98690e518e9a05f8ec6837663e188211b2da8f4906648b323f2c1d4434e29929181900390910190a15050565b6001600160a01b03821660009081526009602052604081205460ff16611adf5760405162461bcd60e51b81526004018080602001828103825260288152602001806154db6028913960400191505060405180910390fd5b600a546001600160a01b0316331480611b0257506000546001600160a01b031633145b611b3d5760405162461bcd60e51b81526004018080602001828103825260278152602001806155036027913960400191505060405180910390fd5b6000546001600160a01b0316331480611b5857506001821515145b611ba2576040805162461bcd60e51b81526020600482015260166024820152756f6e6c792061646d696e2063616e20756e706175736560501b604482015290519081900360640190fd5b6001600160a01b0383166000818152600b6020908152604091829020805486151560ff199091168117909155825193845283830152606090830181905260049083015263135a5b9d60e21b6080830152517f71aec636243f9709bb0007ae15e9afb8150ab01716d75fd7573be5cc096e03b09181900360a00190a150919050565b600a54600160a01b900460ff1681565b50505050565b435b90565b611c46613f13565b611c97576040805162461bcd60e51b815260206004820152601d60248201527f6f6e6c792061646d696e2063616e2073657420636f6d70207370656564000000604482015290519081900360640190fd5b611ca18282614076565b5050565b505050505050565b60166020526000908152604090205481565b60065481565b600080600080600080611cda8a8a8a8a6143f6565b925092509250826011811115611cec57fe5b95509093509150505b9450945094915050565b6001600160a01b0383166000908152600b602052604081205460ff1615611d5e576040805162461bcd60e51b815260206004820152600e60248201526d1b5a5b9d081a5cc81c185d5cd95960921b604482015290519081900360640190fd5b6001600160a01b03841660009081526009602052604090205460ff16611d885760095b90506119d5565b611d918461472e565b611d9b84846149ac565b6000949350505050565b600080546001600160a01b03163314611dcb57611dc46001600b614b8b565b905061192a565b6006805490839055604080518281526020810185905281517faeba5a6c40a8ac138134bff1aaa65debf25971188a58804bad717f82f0ec1316929181900390910190a160006119d5565b80158015611e235750600082115b15611c33576040805162461bcd60e51b815260206004820152601160248201527072656465656d546f6b656e73207a65726f60781b604482015290519081900360640190fd5b600d8181548110611e7657fe5b6000918252602090912001546001600160a01b0316905081565b600080546001600160a01b03163314611eaf57611dc460016010614b8b565b600480546001600160a01b038481166001600160a01b0319831681179093556040805191909216808252602082019390935281517fd52b2b9b7e9ee655fcb95d2e5b9e0c9f69e7ef2b8e9d2d0ea78402d576d22e22929181900390910190a160006119d5565b611f1d613f13565b611f6e576040805162461bcd60e51b815260206004820152601d60248201527f6f6e6c792061646d696e2063616e2073657420636f6d70207370656564000000604482015290519081900360640190fd5b611f77826126a0565b80611f9a576001600160a01b038216600090815260186020526040812055611fbc565b611fa2611c39565b6001600160a01b0383166000908152601860205260409020555b6001600160a01b038216600081815260176020908152604091829020849055815184815291517f386537fa92edc3319af95f1f904dcf1900021e4f3f4e08169a577a09076e66b39281900390910190a25050565b611481565b60008060008060008061202c8760008060006143f6565b92509250925082601181111561203e57fe5b97919650945092505050565b600080546001600160a01b0316331461206957611dc460016013614b8b565b600a80546001600160a01b038481166001600160a01b0319831617928390556040805192821680845293909116602083015280517f0613b6ee6a04f0d09f390e4d9318894b9f6ac7fd83897cd8d18896ba579c401e9281900390910190a160006119d5565b6001600160a01b03851660009081526009602052604081205460ff16158061210f57506001600160a01b03851660009081526009602052604090205460ff16155b1561211e5760095b905061222a565b60008061212a85614bf1565b9193509091506000905082601181111561214057fe5b1461215a5781601181111561215157fe5b9250505061222a565b80612166576003612151565b6000886001600160a01b03166395dd9193876040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b1580156121be57600080fd5b505afa1580156121d2573d6000803e3d6000fd5b505050506040513d60208110156121e857600080fd5b50516040805160208101909152600554815290915060009061220a9083614c11565b90508086111561222157601194505050505061222a565b60009450505050505b95945050505050565b6000546001600160a01b031633148061225657506015546001600160a01b031633145b6122915760405162461bcd60e51b81526004018080602001828103825260358152602001806155506035913960400191505060405180910390fd5b828181158015906122a157508082145b6122e2576040805162461bcd60e51b815260206004820152600d60248201526c1a5b9d985b1a59081a5b9c1d5d609a1b604482015290519081900360640190fd5b60005b828110156123ba578484828181106122f957fe5b905060200201356016600089898581811061231057fe5b905060200201356001600160a01b03166001600160a01b03166001600160a01b031681526020019081526020016000208190555086868281811061235057fe5b905060200201356001600160a01b03166001600160a01b03167f6f1951b2aad10f3fc81b86d91105b413a5b3f847a34bbc5ce1904201b14438f686868481811061239657fe5b905060200201356040518082815260200191505060405180910390a26001016122e5565b50505050505050565b60005b83518110156115f75760008482815181106123dd57fe5b6020908102919091018101516001600160a01b0381166000908152600990925260409091205490915060ff16612452576040805162461bcd60e51b81526020600482015260156024820152741b585c9ad95d081b5d5cdd081899481b1a5cdd1959605a1b604482015290519081900360640190fd5b600184151514156125a15761246561541b565b6040518060200160405280836001600160a01b031663aa5af0fd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156124a957600080fd5b505afa1580156124bd573d6000803e3d6000fd5b505050506040513d60208110156124d357600080fd5b5051905290506124e38282613af4565b60005b875181101561259e5761250d838983815181106124ff57fe5b602002602001015184613d7c565b61256288828151811061251c57fe5b6020026020010151601460008b858151811061253457fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054613f3c565b601460008a848151811061257257fe5b6020908102919091018101516001600160a01b03168252810191909152604001600020556001016124e6565b50505b60018315151415612643576125b58161472e565b60005b8651811015612641576125de828883815181106125d157fe5b60200260200101516149ac565b6126058782815181106125ed57fe5b6020026020010151601460008a858151811061253457fe5b6014600089848151811061261557fe5b6020908102919091018101516001600160a01b03168252810191909152604001600020556001016125b8565b505b506001016123c6565b6010602052600090815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b600c6020526000908152604090205460ff1681565b600b6020526000908152604090205460ff1681565b6001600160a01b038116600090815260176020526040812054906126c2611c39565b6001600160a01b038416600090815260186020526040812054919250906126ea908390614c30565b90506000811180156126fc5750600083115b15611c3357600061270d8285614c6a565b6001600160a01b038616600090815260146020526040812054919250906127349083614cac565b6001600160a01b0387166000908152601460209081526040808320939093556018905220849055505050505050565b6004546001600160a01b031681565b600a54600160b01b900460ff1681565b6011602052600090815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b60096020526000908152604090208054600182015460039092015460ff91821692911683565b600a546000906001600160a01b03163314806127f857506000546001600160a01b031633145b6128335760405162461bcd60e51b81526004018080602001828103825260278152602001806155036027913960400191505060405180910390fd5b6000546001600160a01b031633148061284e57506001821515145b612898576040805162461bcd60e51b81526020600482015260166024820152756f6e6c792061646d696e2063616e20756e706175736560501b604482015290519081900360640190fd5b600a8054831515600160b01b810260ff60b01b1990921691909117909155604080516020810192909252808252600882820152672a3930b739b332b960c11b6060830152517fef159d9a32b2472e32b098f954f3ce62d232939f1c207070b584df1814de2de09181900360800190a15090565b6001600160a01b038082166000908152600960209081526040808320938616835260029093019052205460ff1692915050565b60075481565b60176020526000908152604090205481565b73c00e94cb662c3520282e6f5717214004a7f2688890565b600080546001600160a01b0316331461298d57611dc460016012614b8b565b6001600160a01b03821660009081526009602052604090205460ff16156129ba57611dc4600a6011614b8b565b816001600160a01b031663fe9c44ae6040518163ffffffff1660e01b815260040160206040518083038186803b1580156129f357600080fd5b505afa158015612a07573d6000803e3d6000fd5b505050506040513d6020811015612a1d57600080fd5b5050604080516060810182526001808252600060208381018281528486018381526001600160a01b03891684526009909252949091209251835490151560ff19918216178455935191830191909155516003909101805491151591909216179055612a8782614ce2565b604080516001600160a01b038416815290517fcf583bb0c569eb967f806b11601c4cb93c10310485c67add5f8362c2f212321f9181900360200190a1600092915050565b6ec097ce7bc90715b34b9f100000000081565b600e5481565b60608060086000846001600160a01b03166001600160a01b03168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015612b6057602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612b42575b5093979650505050505050565b600a54600160b81b900460ff1681565b6060600d805480602002602001604051908101604052809291908181526020018280548015612bd557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612bb7575b5050505050905090565b601260209081526000928352604080842090915290825290205481565b6002546001600160a01b031681565b600a54600090600160b01b900460ff1615612c62576040805162461bcd60e51b81526020600482015260126024820152711d1c985b9cd9995c881a5cc81c185d5cd95960721b604482015290519081900360640190fd5b6000612c6f868685614dc0565b90508015612c7e5790506116cc565b612c878661472e565b612c9186866149ac565b6116c686856149ac565b60186020526000908152604090205481565b6060600082519050606081604051908082528060200260200182016040528015612ce1578160200160208202803883390190505b50905060005b82811015612d3c576000858281518110612cfd57fe5b60200260200101519050612d118133614e6c565b6011811115612d1c57fe5b838381518110612d2857fe5b602090810291909101015250600101612ce7565b509392505050565b600480546040805163fc57d4df60e01b81526001600160a01b038781169482019490945290516000938493849391169163fc57d4df91602480820192602092909190829003018186803b158015612d9a57600080fd5b505afa158015612dae573d6000803e3d6000fd5b505050506040513d6020811015612dc457600080fd5b5051600480546040805163fc57d4df60e01b81526001600160a01b038a8116948201949094529051939450600093929091169163fc57d4df91602480820192602092909190829003018186803b158015612e1d57600080fd5b505afa158015612e31573d6000803e3d6000fd5b505050506040513d6020811015612e4757600080fd5b50519050811580612e56575080155b15612e6b57600d935060009250612f64915050565b6000866001600160a01b031663182df0f56040518163ffffffff1660e01b815260040160206040518083038186803b158015612ea657600080fd5b505afa158015612eba573d6000803e3d6000fd5b505050506040513d6020811015612ed057600080fd5b505190506000612ede61541b565b612ee661541b565b612eee61541b565b612f16604051806020016040528060065481525060405180602001604052808a815250614f62565b9250612f3e604051806020016040528088815250604051806020016040528088815250614f62565b9150612f4a8383614fa1565b9050612f56818b614c11565b600099509750505050505050505b935093915050565b601360209081526000928352604080842090915290825290205481565b60146020526000908152604090205481565b600a54600090600160b81b900460ff1615612fef576040805162461bcd60e51b815260206004820152600f60248201526e1cd95a5e99481a5cc81c185d5cd959608a1b604482015290519081900360640190fd5b6001600160a01b03861660009081526009602052604090205460ff16158061303057506001600160a01b03851660009081526009602052604090205460ff16155b1561303c576009612117565b846001600160a01b0316635fe3b5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561307557600080fd5b505afa158015613089573d6000803e3d6000fd5b505050506040513d602081101561309f57600080fd5b505160408051635fe3b56760e01b815290516001600160a01b0392831692891691635fe3b567916004808301926020929190829003018186803b1580156130e557600080fd5b505afa1580156130f9573d6000803e3d6000fd5b505050506040513d602081101561310f57600080fd5b50516001600160a01b031614613126576002612117565b61312f8661472e565b61313986846149ac565b61314386856149ac565b60009695505050505050565b6001600160a01b0383166000908152600c602052604081205460ff16156131b0576040805162461bcd60e51b815260206004820152601060248201526f189bdc9c9bddc81a5cc81c185d5cd95960821b604482015290519081900360640190fd5b6001600160a01b03841660009081526009602052604090205460ff166131d7576009611d81565b6001600160a01b038085166000908152600960209081526040808320938716835260029093019052205460ff166132c757336001600160a01b0385161461325d576040805162461bcd60e51b815260206004820152601560248201527439b2b73232b91036bab9ba1031329031aa37b5b2b760591b604482015290519081900360640190fd5b60006132693385614e6c565b9050600081601181111561327957fe5b146132925780601181111561328a57fe5b9150506119d5565b6001600160a01b038086166000908152600960209081526040808320938816835260029093019052205460ff166132c557fe5b505b600480546040805163fc57d4df60e01b81526001600160a01b03888116948201949094529051929091169163fc57d4df91602480820192602092909190829003018186803b15801561331857600080fd5b505afa15801561332c573d6000803e3d6000fd5b505050506040513d602081101561334257600080fd5b505161334f57600d611d81565b6001600160a01b038416600090815260166020526040902054801561343c576000856001600160a01b03166347bd37186040518163ffffffff1660e01b815260040160206040518083038186803b1580156133a957600080fd5b505afa1580156133bd573d6000803e3d6000fd5b505050506040513d60208110156133d357600080fd5b5051905060006133e38286614cac565b9050828110613439576040805162461bcd60e51b815260206004820152601960248201527f6d61726b657420626f72726f7720636170207265616368656400000000000000604482015290519081900360640190fd5b50505b60008061344c86886000886143f6565b9193509091506000905082601181111561346257fe5b1461347d5781601181111561347357fe5b93505050506119d5565b801561348a576004613473565b61349261541b565b6040518060200160405280896001600160a01b031663aa5af0fd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156134d657600080fd5b505afa1580156134ea573d6000803e3d6000fd5b505050506040513d602081101561350057600080fd5b5051905290506135108882613af4565b61351b888883613d7c565b600098975050505050505050565b6008602052816000526040600020818154811061354257fe5b6000918252602090912001546001600160a01b03169150829050565b6003546001600160a01b031681565b600080546001600160a01b031633146135935761358c60016006614b8b565b905061141e565b6001600160a01b0383166000908152600960205260409020805460ff166135c8576135c060096007614b8b565b91505061141e565b6135d061541b565b5060408051602081019091528381526135e761541b565b506040805160208101909152670c7d713b49da000081526136088183614fdd565b156136235761361960066008614b8b565b935050505061141e565b84158015906136ac5750600480546040805163fc57d4df60e01b81526001600160a01b038a8116948201949094529051929091169163fc57d4df91602480820192602092909190829003018186803b15801561367e57600080fd5b505afa158015613692573d6000803e3d6000fd5b505050506040513d60208110156136a857600080fd5b5051155b156136bd57613619600d6009614b8b565b60018301805490869055604080516001600160a01b03891681526020810183905280820188905290517f70483e6592cd5182d45ac970e05bc62cdcc90e9d8ef2c2dbe686cf383bcd7fc59181900360600190a16000979650505050505050565b600a54600160a81b900460ff1681565b60055481565b6115e281600d80548060200260200160405190810160405280929190818152602001828054801561378d57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161376f575b5050505050611424565b6000806137a5858585614dc0565b905080156137b45790506119d5565b6137bd8561472e565b6137c785856149ac565b600095945050505050565b6000808290506000806000836001600160a01b031663c37f68e2336040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060806040518083038186803b15801561383357600080fd5b505afa158015613847573d6000803e3d6000fd5b505050506040513d608081101561385d57600080fd5b5080516020820151604090920151909450909250905082156138b05760405162461bcd60e51b81526004018080602001828103825260258152602001806155856025913960400191505060405180910390fd5b80156138cd576138c2600c6002614b8b565b94505050505061192a565b60006138da873385614dc0565b905080156138fb576138ef600e600383614fe4565b9550505050505061192a565b6001600160a01b0385166000908152600960209081526040808320338452600281019092529091205460ff1661393a576000965050505050505061192a565b3360009081526002820160209081526040808320805460ff1916905560088252918290208054835181840281018401909452808452606093928301828280156139ac57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161398e575b5050835193945083925060009150505b82811015613a0157896001600160a01b03168482815181106139da57fe5b60200260200101516001600160a01b031614156139f957809150613a01565b6001016139bc565b50818110613a0b57fe5b336000908152600860205260409020805481906000198101908110613a2c57fe5b9060005260206000200160009054906101000a90046001600160a01b0316818381548110613a5657fe5b600091825260209091200180546001600160a01b0319166001600160a01b03929092169190911790558054613a8f82600019830161542e565b50604080516001600160a01b038c16815233602082015281517fe699a64c18b07ac5b7301aa273f36a2287239eb9501d81950672794afba29a0d929181900390910190a160009c9b505050505050505050505050565b6000546001600160a01b031681565b6001600160a01b0382166000908152601160209081526040808320600f9092528220549091613b21611c39565b8354909150600090613b41908390600160e01b900463ffffffff16614c30565b9050600081118015613b535750600083115b15613d22576000613bc8876001600160a01b03166347bd37186040518163ffffffff1660e01b815260040160206040518083038186803b158015613b9657600080fd5b505afa158015613baa573d6000803e3d6000fd5b505050506040513d6020811015613bc057600080fd5b50518761504a565b90506000613bd68386614c6a565b9050613be061541b565b60008311613bfd5760405180602001604052806000815250613c07565b613c078284615068565b9050613c1161541b565b604080516020810190915288546001600160e01b03168152613c33908361509d565b90506040518060400160405280613c8383600001516040518060400160405280601a81526020017f6e657720696e64657820657863656564732032323420626974730000000000008152506150c2565b6001600160e01b03168152602001613cbe886040518060400160405280601c81526020016000805160206155aa83398151915281525061515c565b63ffffffff9081169091526001600160a01b038c166000908152601160209081526040909120835181549490920151909216600160e01b026001600160e01b039182166001600160e01b0319909416939093171691909117905550611ca592505050565b8015611ca557613d55826040518060400160405280601c81526020016000805160206155aa83398151915281525061515c565b845463ffffffff91909116600160e01b026001600160e01b03909116178455505050505050565b6001600160a01b0383166000908152601160205260409020613d9c61541b565b50604080516020810190915281546001600160e01b03168152613dbd61541b565b5060408051602080820183526001600160a01b0380891660009081526013835284812091891680825282845294812080548552865195909152915291909155805115611ca557613e0b61541b565b613e1583836151b1565b90506000613e72886001600160a01b03166395dd9193896040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015613b9657600080fd5b90506000613e8082846151d6565b6001600160a01b03891660009081526014602052604081205491925090613ea79083614cac565b6001600160a01b03808b166000818152601460209081526040918290208590558a5182518881529182015281519495509193928e16927f1fc3ecc087d8d2d15e23d0032af5a47059c3892d003d8e139fdcb6bb327c99a69281900390910190a350505050505050505050565b600080546001600160a01b0316331480613f3757506002546001600160a01b031633145b905090565b600080613f47612956565b604080516370a0823160e01b815230600482015290519192506000916001600160a01b038416916370a08231916024808301926020929190829003018186803b158015613f9357600080fd5b505afa158015613fa7573d6000803e3d6000fd5b505050506040513d6020811015613fbd57600080fd5b505190508315801590613fd05750808411155b1561406d57816001600160a01b031663a9059cbb86866040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561403557600080fd5b505af1158015614049573d6000803e3d6000fd5b505050506040513d602081101561405f57600080fd5b506000935061141e92505050565b50919392505050565b6001600160a01b0382166000908152600f6020526040902054801561412a5761409d61541b565b6040518060200160405280856001600160a01b031663aa5af0fd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156140e157600080fd5b505afa1580156140f5573d6000803e3d6000fd5b505050506040513d602081101561410b57600080fd5b50519052905061411a8461472e565b6141248482613af4565b5061439a565b811561439a576001600160a01b0383166000908152600960205260409020805460ff1615156001146141a3576040805162461bcd60e51b815260206004820152601960248201527f636f6d70206d61726b6574206973206e6f74206c697374656400000000000000604482015290519081900360640190fd5b6001600160a01b0384166000908152601060205260409020546001600160e01b03161580156141f557506001600160a01b038416600090815260106020526040902054600160e01b900463ffffffff16155b156142b25760405180604001604052806ec097ce7bc90715b34b9f10000000006001600160e01b0316815260200161425761422e611c39565b6040518060400160405280601c81526020016000805160206155aa83398151915281525061515c565b63ffffffff9081169091526001600160a01b0386166000908152601060209081526040909120835181549490920151909216600160e01b026001600160e01b039182166001600160e01b031990941693909317169190911790555b6001600160a01b0384166000908152601160205260409020546001600160e01b031615801561430457506001600160a01b038416600090815260116020526040902054600160e01b900463ffffffff16155b156143985760405180604001604052806ec097ce7bc90715b34b9f10000000006001600160e01b0316815260200161433d61422e611c39565b63ffffffff9081169091526001600160a01b0386166000908152601160209081526040909120835181549490920151909216600160e01b026001600160e01b039182166001600160e01b031990941693909317169190911790555b505b818114611481576001600160a01b0383166000818152600f6020908152604091829020859055815185815291517f2ab93f65628379309f36cb125e90d7c902454a545c4f8b8cb0794af75c24b8079281900390910190a2505050565b6000806000614403615452565b6001600160a01b0388166000908152600860209081526040808320805482518185028101850190935280835260609383018282801561446b57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161444d575b50939450600093505050505b81518110156146ef57600082828151811061448e57fe5b60200260200101519050806001600160a01b031663c37f68e28d6040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060806040518083038186803b1580156144ee57600080fd5b505afa158015614502573d6000803e3d6000fd5b505050506040513d608081101561451857600080fd5b508051602082015160408084015160609485015160808b015293890193909352918701919091529350831561455d5750600f965060009550859450611cf59350505050565b60408051602080820183526001600160a01b0380851660008181526009845285902060010154845260c08a01939093528351808301855260808a0151815260e08a015260048054855163fc57d4df60e01b815291820194909452935192169263fc57d4df9260248083019392829003018186803b1580156145dd57600080fd5b505afa1580156145f1573d6000803e3d6000fd5b505050506040513d602081101561460757600080fd5b505160a0860181905261462a5750600d965060009550859450611cf59350505050565b604080516020810190915260a0860151815261010086015260c085015160e08601516146649161465991614f62565b866101000151614f62565b61012086018190526040860151865161467e929190615205565b85526101008501516060860151602087015161469b929190615205565b60208601526001600160a01b03818116908c1614156146e6576146c88561012001518b8760200151615205565b602086018190526101008601516146e0918b90615205565b60208601525b50600101614477565b506020830151835111156147155750506020810151905160009450039150829050611cf5565b5050805160209091015160009450849350039050611cf5565b6001600160a01b0381166000908152601060209081526040808320600f909252822054909161475b611c39565b835490915060009061477b908390600160e01b900463ffffffff16614c30565b905060008111801561478d5750600083115b15614953576000856001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156147cd57600080fd5b505afa1580156147e1573d6000803e3d6000fd5b505050506040513d60208110156147f757600080fd5b5051905060006148078386614c6a565b905061481161541b565b6000831161482e5760405180602001604052806000815250614838565b6148388284615068565b905061484261541b565b604080516020810190915288546001600160e01b03168152614864908361509d565b905060405180604001604052806148b483600001516040518060400160405280601a81526020017f6e657720696e64657820657863656564732032323420626974730000000000008152506150c2565b6001600160e01b031681526020016148ef886040518060400160405280601c81526020016000805160206155aa83398151915281525061515c565b63ffffffff9081169091526001600160a01b038b166000908152601060209081526040909120835181549490920151909216600160e01b026001600160e01b039182166001600160e01b03199094169390931716919091179055506115f792505050565b80156115f757614986826040518060400160405280601c81526020016000805160206155aa83398151915281525061515c565b845463ffffffff91909116600160e01b026001600160e01b039091161784555050505050565b6001600160a01b03821660009081526010602052604090206149cc61541b565b50604080516020810190915281546001600160e01b031681526149ed61541b565b5060408051602080820183526001600160a01b03808816600090815260128352848120918816808252828452948120805485528651959091529152919091558051158015614a3b5750815115155b15614a53576ec097ce7bc90715b34b9f100000000081525b614a5b61541b565b614a6583836151b1565b90506000866001600160a01b03166370a08231876040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015614abf57600080fd5b505afa158015614ad3573d6000803e3d6000fd5b505050506040513d6020811015614ae957600080fd5b505190506000614af982846151d6565b6001600160a01b03881660009081526014602052604081205491925090614b209083614cac565b6001600160a01b03808a166000818152601460209081526040918290208590558a5182518881529182015281519495509193928d16927f2caecd17d02f56fa897705dcc740da2d237c373f70686f4e0d9bd3bf0400ea7a9281900390910190a3505050505050505050565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0836011811115614bba57fe5b836013811115614bc657fe5b604080519283526020830191909152600082820152519081900360600190a18260118111156119d557fe5b6000806000614c048460008060006143f6565b9250925092509193909250565b6000614c1b61541b565b614c25848461522d565b90506116cc8161524e565b60006119d58383604051806040016040528060158152602001747375627472616374696f6e20756e646572666c6f7760581b81525061525d565b60006119d583836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f770000000000000000008152506152b7565b60006119d58383604051806040016040528060118152602001706164646974696f6e206f766572666c6f7760781b815250615336565b60005b600d54811015614d6d57816001600160a01b0316600d8281548110614d0657fe5b6000918252602090912001546001600160a01b03161415614d65576040805162461bcd60e51b81526020600482015260146024820152731b585c9ad95d08185b1c9958591e48185919195960621b604482015290519081900360640190fd5b600101614ce5565b50600d80546001810182556000919091527fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb50180546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b03831660009081526009602052604081205460ff16614de7576009611d81565b6001600160a01b038085166000908152600960209081526040808320938716835260029093019052205460ff16614e1f576000611d81565b600080614e2f85878660006143f6565b91935090915060009050826011811115614e4557fe5b14614e5f57816011811115614e5657fe5b925050506119d5565b8015613143576004614e56565b6001600160a01b0382166000908152600960205260408120805460ff16614e9757600991505061141e565b6001600160a01b038316600090815260028201602052604090205460ff16151560011415614ec957600091505061141e565b6001600160a01b0380841660008181526002840160209081526040808320805460ff19166001908117909155600883528184208054918201815584529282902090920180549489166001600160a01b031990951685179055815193845283019190915280517f3ab23ab0d51cccc0c3085aec51f99228625aa1a922b3a8ca89a26b0f2027a1a59281900390910190a15060009392505050565b614f6a61541b565b6040518060200160405280670de0b6b3a7640000614f9086600001518660000151614c6a565b81614f9757fe5b0490529392505050565b614fa961541b565b6040518060200160405280614fd4614fcd8660000151670de0b6b3a7640000614c6a565b855161538b565b90529392505050565b5190511090565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa084601181111561501357fe5b84601381111561501f57fe5b604080519283526020830191909152818101859052519081900360600190a18360118111156116cc57fe5b60006119d561506184670de0b6b3a7640000614c6a565b835161538b565b61507061541b565b6040518060200160405280614fd4615097866ec097ce7bc90715b34b9f1000000000614c6a565b8561538b565b6150a561541b565b6040518060200160405280614fd485600001518560000151614cac565b600081600160e01b84106151545760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015615119578181015183820152602001615101565b50505050905090810190601f1680156151465780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b509192915050565b600081600160201b84106151545760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315615119578181015183820152602001615101565b6151b961541b565b6040518060200160405280614fd485600001518560000151614c30565b60006ec097ce7bc90715b34b9f10000000006151f6848460000151614c6a565b816151fd57fe5b049392505050565b600061520f61541b565b615219858561522d565b905061222a6152278261524e565b84614cac565b61523561541b565b6040518060200160405280614fd4856000015185614c6a565b51670de0b6b3a7640000900490565b600081848411156152af5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315615119578181015183820152602001615101565b505050900390565b60008315806152c4575082155b156152d1575060006119d5565b838302838582816152de57fe5b0414839061532d5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315615119578181015183820152602001615101565b50949350505050565b6000838301828582101561532d5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315615119578181015183820152602001615101565b60006119d583836040518060400160405280600e81526020016d646976696465206279207a65726f60901b815250600081836154085760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315615119578181015183820152602001615101565b5082848161541257fe5b04949350505050565b6040518060200160405280600081525090565b815481835581811115611481576000838152602090206114819181019083016154bc565b60405180610140016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200161549061541b565b815260200161549d61541b565b81526020016154aa61541b565b81526020016154b761541b565b905290565b611c3b91905b808211156154d657600081556001016154c2565b509056fe63616e6e6f742070617573652061206d61726b65742074686174206973206e6f74206c69737465646f6e6c7920706175736520677561726469616e20616e642061646d696e2063616e2070617573656f6e6c792061646d696e2063616e2073657420626f72726f772063617020677561726469616e6f6e6c792061646d696e206f7220626f72726f772063617020677561726469616e2063616e2073657420626f72726f772063617073657869744d61726b65743a206765744163636f756e74536e617073686f74206661696c6564626c6f636b206e756d62657220657863656564732033322062697473000000006f6e6c7920756e6974726f6c6c65722061646d696e2063616e206368616e676520627261696e73a265627a7a72315820a76e0a895acb7d6b5d8e1af20e5d1723e554bbf91a903317ed8ff00216920b3764736f6c63430005100032", + "metadata": "{\"compiler\":{\"version\":\"0.5.16+commit.9c3226ce\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"action\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"pauseState\",\"type\":\"bool\"}],\"name\":\"ActionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"action\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"pauseState\",\"type\":\"bool\"}],\"name\":\"ActionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"CompGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSpeed\",\"type\":\"uint256\"}],\"name\":\"CompSpeedUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"contributor\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSpeed\",\"type\":\"uint256\"}],\"name\":\"ContributorCompSpeedUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compBorrowIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedBorrowerComp\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"supplier\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compSupplyIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedSupplierComp\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketEntered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketExited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"MarketListed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newBorrowCap\",\"type\":\"uint256\"}],\"name\":\"NewBorrowCap\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldBorrowCapGuardian\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newBorrowCapGuardian\",\"type\":\"address\"}],\"name\":\"NewBorrowCapGuardian\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCloseFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCloseFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCollateralFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCollateralFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldLiquidationIncentiveMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"NewLiquidationIncentive\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldPauseGuardian\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"NewPauseGuardian\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"oldPriceOracle\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"newPriceOracle\",\"type\":\"address\"}],\"name\":\"NewPriceOracle\",\"type\":\"event\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract Unitroller\",\"name\":\"unitroller\",\"type\":\"address\"}],\"name\":\"_become\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"_grantComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"newBorrowCapGuardian\",\"type\":\"address\"}],\"name\":\"_setBorrowCapGuardian\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setBorrowPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCloseFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCollateralFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"compSpeed\",\"type\":\"uint256\"}],\"name\":\"_setCompSpeed\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"contributor\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"compSpeed\",\"type\":\"uint256\"}],\"name\":\"_setContributorCompSpeed\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"_setLiquidationIncentive\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"cTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"newBorrowCaps\",\"type\":\"uint256[]\"}],\"name\":\"_setMarketBorrowCaps\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setMintPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"_setPauseGuardian\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"newOracle\",\"type\":\"address\"}],\"name\":\"_setPriceOracle\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setSeizePaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setTransferPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"_supportMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allMarkets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"borrowCapGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"checkMembership\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"},{\"internalType\":\"contract CToken[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"holders\",\"type\":\"address[]\"},{\"internalType\":\"contract CToken[]\",\"name\":\"cTokens\",\"type\":\"address[]\"},{\"internalType\":\"bool\",\"name\":\"borrowers\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"suppliers\",\"type\":\"bool\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compAccrued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compBorrowState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compBorrowerIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compContributorSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compInitialIndex\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSupplierIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSupplyState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"enterMarkets\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenAddress\",\"type\":\"address\"}],\"name\":\"exitMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getAllMarkets\",\"outputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAssetsIn\",\"outputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getCompAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenModify\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"getHypotheticalAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"isComptroller\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"lastContributorBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateCalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"liquidationIncentiveMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"markets\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isComped\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"mintAmount\",\"type\":\"uint256\"}],\"name\":\"mintAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualMintAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"mintTokens\",\"type\":\"uint256\"}],\"name\":\"mintVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"repayBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowerIndex\",\"type\":\"uint256\"}],\"name\":\"repayBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"seizeGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"transferGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"contributor\",\"type\":\"address\"}],\"name\":\"updateContributorRewards\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Compound\",\"methods\":{\"_grantComp(address,uint256)\":{\"details\":\"Note: If there is not enough COMP, we do not perform the transfer all.\",\"params\":{\"amount\":\"The amount of COMP to (possibly) transfer\",\"recipient\":\"The address of the recipient to transfer COMP to\"}},\"_setBorrowCapGuardian(address)\":{\"params\":{\"newBorrowCapGuardian\":\"The address of the new Borrow Cap Guardian\"}},\"_setCloseFactor(uint256)\":{\"details\":\"Admin function to set closeFactor\",\"params\":{\"newCloseFactorMantissa\":\"New close factor, scaled by 1e18\"},\"return\":\"uint 0=success, otherwise a failure\"},\"_setCollateralFactor(address,uint256)\":{\"details\":\"Admin function to set per-market collateralFactor\",\"params\":{\"cToken\":\"The market to set the factor on\",\"newCollateralFactorMantissa\":\"The new collateral factor, scaled by 1e18\"},\"return\":\"uint 0=success, otherwise a failure. (See ErrorReporter for details)\"},\"_setCompSpeed(address,uint256)\":{\"params\":{\"cToken\":\"The market whose COMP speed to update\",\"compSpeed\":\"New COMP speed for market\"}},\"_setContributorCompSpeed(address,uint256)\":{\"params\":{\"compSpeed\":\"New COMP speed for contributor\",\"contributor\":\"The contributor whose COMP speed to update\"}},\"_setLiquidationIncentive(uint256)\":{\"details\":\"Admin function to set liquidationIncentive\",\"params\":{\"newLiquidationIncentiveMantissa\":\"New liquidationIncentive scaled by 1e18\"},\"return\":\"uint 0=success, otherwise a failure. (See ErrorReporter for details)\"},\"_setMarketBorrowCaps(address[],uint256[])\":{\"details\":\"Admin or borrowCapGuardian function to set the borrow caps. A borrow cap of 0 corresponds to unlimited borrowing.\",\"params\":{\"cTokens\":\"The addresses of the markets (tokens) to change the borrow caps for\",\"newBorrowCaps\":\"The new borrow cap values in underlying to be set. A value of 0 corresponds to unlimited borrowing.\"}},\"_setPauseGuardian(address)\":{\"params\":{\"newPauseGuardian\":\"The address of the new Pause Guardian\"},\"return\":\"uint 0=success, otherwise a failure. (See enum Error for details)\"},\"_setPriceOracle(address)\":{\"details\":\"Admin function to set a new price oracle\",\"return\":\"uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\"},\"_supportMarket(address)\":{\"details\":\"Admin function to set isListed and add support for the market\",\"params\":{\"cToken\":\"The address of the market (token) to list\"},\"return\":\"uint 0=success, otherwise a failure. (See enum Error for details)\"},\"borrowAllowed(address,address,uint256)\":{\"params\":{\"borrowAmount\":\"The amount of underlying the account would borrow\",\"borrower\":\"The account which would borrow the asset\",\"cToken\":\"The market to verify the borrow against\"},\"return\":\"0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"borrowVerify(address,address,uint256)\":{\"params\":{\"borrowAmount\":\"The amount of the underlying asset requested to borrow\",\"borrower\":\"The address borrowing the underlying\",\"cToken\":\"Asset whose underlying is being borrowed\"}},\"checkMembership(address,address)\":{\"params\":{\"account\":\"The address of the account to check\",\"cToken\":\"The cToken to check\"},\"return\":\"True if the account is in the asset, otherwise false.\"},\"claimComp(address)\":{\"params\":{\"holder\":\"The address to claim COMP for\"}},\"claimComp(address,address[])\":{\"params\":{\"cTokens\":\"The list of markets to claim COMP in\",\"holder\":\"The address to claim COMP for\"}},\"claimComp(address[],address[],bool,bool)\":{\"params\":{\"borrowers\":\"Whether or not to claim COMP earned by borrowing\",\"cTokens\":\"The list of markets to claim COMP in\",\"holders\":\"The addresses to claim COMP for\",\"suppliers\":\"Whether or not to claim COMP earned by supplying\"}},\"enterMarkets(address[])\":{\"params\":{\"cTokens\":\"The list of addresses of the cToken markets to be enabled\"},\"return\":\"Success indicator for whether each corresponding market was entered\"},\"exitMarket(address)\":{\"details\":\"Sender must not have an outstanding borrow balance in the asset, or be providing necessary collateral for an outstanding borrow.\",\"params\":{\"cTokenAddress\":\"The address of the asset to be removed\"},\"return\":\"Whether or not the account successfully exited the market\"},\"getAccountLiquidity(address)\":{\"return\":\"(possible error code (semi-opaque), account liquidity in excess of collateral requirements, account shortfall below collateral requirements)\"},\"getAllMarkets()\":{\"details\":\"The automatic getter may be used to access an individual market.\",\"return\":\"The list of market addresses\"},\"getAssetsIn(address)\":{\"params\":{\"account\":\"The address of the account to pull assets for\"},\"return\":\"A dynamic list with the assets the account has entered\"},\"getCompAddress()\":{\"return\":\"The address of COMP\"},\"getHypotheticalAccountLiquidity(address,address,uint256,uint256)\":{\"params\":{\"account\":\"The account to determine liquidity for\",\"borrowAmount\":\"The amount of underlying to hypothetically borrow\",\"cTokenModify\":\"The market to hypothetically redeem/borrow in\",\"redeemTokens\":\"The number of tokens to hypothetically redeem\"},\"return\":\"(possible error code (semi-opaque), hypothetical account liquidity in excess of collateral requirements, hypothetical account shortfall below collateral requirements)\"},\"liquidateBorrowAllowed(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"repayAmount\":\"The amount of underlying being repaid\"}},\"liquidateBorrowVerify(address,address,address,address,uint256,uint256)\":{\"params\":{\"actualRepayAmount\":\"The amount of underlying being repaid\",\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\"}},\"liquidateCalculateSeizeTokens(address,address,uint256)\":{\"details\":\"Used in liquidation (called in cToken.liquidateBorrowFresh)\",\"params\":{\"actualRepayAmount\":\"The amount of cTokenBorrowed underlying to convert into cTokenCollateral tokens\",\"cTokenBorrowed\":\"The address of the borrowed cToken\",\"cTokenCollateral\":\"The address of the collateral cToken\"},\"return\":\"(errorCode, number of cTokenCollateral tokens to be seized in a liquidation)\"},\"mintAllowed(address,address,uint256)\":{\"params\":{\"cToken\":\"The market to verify the mint against\",\"mintAmount\":\"The amount of underlying being supplied to the market in exchange for tokens\",\"minter\":\"The account which would get the minted tokens\"},\"return\":\"0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"mintVerify(address,address,uint256,uint256)\":{\"params\":{\"actualMintAmount\":\"The amount of the underlying asset being minted\",\"cToken\":\"Asset being minted\",\"mintTokens\":\"The number of tokens being minted\",\"minter\":\"The address minting the tokens\"}},\"redeemAllowed(address,address,uint256)\":{\"params\":{\"cToken\":\"The market to verify the redeem against\",\"redeemTokens\":\"The number of cTokens to exchange for the underlying asset in the market\",\"redeemer\":\"The account which would redeem the tokens\"},\"return\":\"0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"redeemVerify(address,address,uint256,uint256)\":{\"params\":{\"cToken\":\"Asset being redeemed\",\"redeemAmount\":\"The amount of the underlying asset being redeemed\",\"redeemTokens\":\"The number of tokens being redeemed\",\"redeemer\":\"The address redeeming the tokens\"}},\"repayBorrowAllowed(address,address,address,uint256)\":{\"params\":{\"borrower\":\"The account which would borrowed the asset\",\"cToken\":\"The market to verify the repay against\",\"payer\":\"The account which would repay the asset\",\"repayAmount\":\"The amount of the underlying asset the account would repay\"},\"return\":\"0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"repayBorrowVerify(address,address,address,uint256,uint256)\":{\"params\":{\"actualRepayAmount\":\"The amount of underlying being repaid\",\"borrower\":\"The address of the borrower\",\"cToken\":\"Asset being repaid\",\"payer\":\"The address repaying the borrow\"}},\"seizeAllowed(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"seizeTokens\":\"The number of collateral tokens to seize\"}},\"seizeVerify(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"seizeTokens\":\"The number of collateral tokens to seize\"}},\"transferAllowed(address,address,address,uint256)\":{\"params\":{\"cToken\":\"The market to verify the transfer against\",\"dst\":\"The account which receives the tokens\",\"src\":\"The account which sources the tokens\",\"transferTokens\":\"The number of cTokens to transfer\"},\"return\":\"0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"transferVerify(address,address,address,uint256)\":{\"params\":{\"cToken\":\"Asset being transferred\",\"dst\":\"The account which receives the tokens\",\"src\":\"The account which sources the tokens\",\"transferTokens\":\"The number of cTokens to transfer\"}},\"updateContributorRewards(address)\":{\"params\":{\"contributor\":\"The address to calculate contributor rewards for\"}}},\"title\":\"Compound's Comptroller Contract\"},\"userdoc\":{\"methods\":{\"_grantComp(address,uint256)\":{\"notice\":\"Transfer COMP to the recipient\"},\"_setBorrowCapGuardian(address)\":{\"notice\":\"Admin function to change the Borrow Cap Guardian\"},\"_setCloseFactor(uint256)\":{\"notice\":\"Sets the closeFactor used when liquidating borrows\"},\"_setCollateralFactor(address,uint256)\":{\"notice\":\"Sets the collateralFactor for a market\"},\"_setCompSpeed(address,uint256)\":{\"notice\":\"Set COMP speed for a single market\"},\"_setContributorCompSpeed(address,uint256)\":{\"notice\":\"Set COMP speed for a single contributor\"},\"_setLiquidationIncentive(uint256)\":{\"notice\":\"Sets liquidationIncentive\"},\"_setMarketBorrowCaps(address[],uint256[])\":{\"notice\":\"Set the given borrow caps for the given cToken markets. Borrowing that brings total borrows to or above borrow cap will revert.\"},\"_setPauseGuardian(address)\":{\"notice\":\"Admin function to change the Pause Guardian\"},\"_setPriceOracle(address)\":{\"notice\":\"Sets a new price oracle for the comptroller\"},\"_supportMarket(address)\":{\"notice\":\"Add the market to the markets mapping and set it as listed\"},\"borrowAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to borrow the underlying asset of the given market\"},\"borrowVerify(address,address,uint256)\":{\"notice\":\"Validates borrow and reverts on rejection. May emit logs.\"},\"checkMembership(address,address)\":{\"notice\":\"Returns whether the given account is entered in the given asset\"},\"claimComp(address)\":{\"notice\":\"Claim all the comp accrued by holder in all markets\"},\"claimComp(address,address[])\":{\"notice\":\"Claim all the comp accrued by holder in the specified markets\"},\"claimComp(address[],address[],bool,bool)\":{\"notice\":\"Claim all comp accrued by the holders\"},\"enterMarkets(address[])\":{\"notice\":\"Add assets to be included in account liquidity calculation\"},\"exitMarket(address)\":{\"notice\":\"Removes asset from sender's account liquidity calculation\"},\"getAccountLiquidity(address)\":{\"notice\":\"Determine the current account liquidity wrt collateral requirements\"},\"getAllMarkets()\":{\"notice\":\"Return all of the markets\"},\"getAssetsIn(address)\":{\"notice\":\"Returns the assets an account has entered\"},\"getCompAddress()\":{\"notice\":\"Return the address of the COMP token\"},\"getHypotheticalAccountLiquidity(address,address,uint256,uint256)\":{\"notice\":\"Determine what the account liquidity would be if the given amounts were redeemed/borrowed\"},\"liquidateBorrowAllowed(address,address,address,address,uint256)\":{\"notice\":\"Checks if the liquidation should be allowed to occur\"},\"liquidateBorrowVerify(address,address,address,address,uint256,uint256)\":{\"notice\":\"Validates liquidateBorrow and reverts on rejection. May emit logs.\"},\"liquidateCalculateSeizeTokens(address,address,uint256)\":{\"notice\":\"Calculate number of tokens of collateral asset to seize given an underlying amount\"},\"mintAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to mint tokens in the given market\"},\"mintVerify(address,address,uint256,uint256)\":{\"notice\":\"Validates mint and reverts on rejection. May emit logs.\"},\"redeemAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to redeem tokens in the given market\"},\"redeemVerify(address,address,uint256,uint256)\":{\"notice\":\"Validates redeem and reverts on rejection. May emit logs.\"},\"repayBorrowAllowed(address,address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to repay a borrow in the given market\"},\"repayBorrowVerify(address,address,address,uint256,uint256)\":{\"notice\":\"Validates repayBorrow and reverts on rejection. May emit logs.\"},\"seizeAllowed(address,address,address,address,uint256)\":{\"notice\":\"Checks if the seizing of assets should be allowed to occur\"},\"seizeVerify(address,address,address,address,uint256)\":{\"notice\":\"Validates seize and reverts on rejection. May emit logs.\"},\"transferAllowed(address,address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to transfer tokens in the given market\"},\"transferVerify(address,address,address,uint256)\":{\"notice\":\"Validates transfer and reverts on rejection. May emit logs.\"},\"updateContributorRewards(address)\":{\"notice\":\"Calculate additional accrued COMP for a contributor since last accrual\"}}}},\"settings\":{\"compilationTarget\":{\"contracts/ComptrollerG7.sol\":\"ComptrollerG7\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/CToken.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./CTokenInterfaces.sol\\\";\\nimport \\\"./ErrorReporter.sol\\\";\\nimport \\\"./Exponential.sol\\\";\\nimport \\\"./EIP20Interface.sol\\\";\\nimport \\\"./InterestRateModel.sol\\\";\\n\\n/**\\n * @title Compound's CToken Contract\\n * @notice Abstract base for CTokens\\n * @author Compound\\n */\\ncontract CToken is CTokenInterface, Exponential, TokenErrorReporter {\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_) public {\\n require(msg.sender == admin, \\\"only admin may initialize the market\\\");\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = getBlockNumber();\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Transfer `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = uint(-1);\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srcTokensNew;\\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, srcTokensNew) = 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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srcTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != uint(-1)) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n // unused function\\n // comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transfer(address dst, uint256 amount) external nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferFrom(address src, address dst, uint256 amount) external nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (-1 means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool) {\\n address src = msg.sender;\\n transferAllowances[src][spender] = amount;\\n emit Approval(src, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (-1 means infinite)\\n */\\n function allowance(address owner, address spender) external view returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external returns (uint) {\\n Exp memory exchangeRate = Exp({mantissa: exchangeRateCurrent()});\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n require(mErr == MathError.NO_ERROR, \\\"balance could not be calculated\\\");\\n return balance;\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view returns (uint, uint, uint, uint) {\\n uint cTokenBalance = accountTokens[account];\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), cTokenBalance, borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @dev Function to simply retrieve block number\\n * This exists mainly for inheriting test contracts to stub this result.\\n */\\n function getBlockNumber() internal view returns (uint) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this cToken\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view returns (uint) {\\n return interestRateModel.getBorrowRate(getCashPrior(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this cToken\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view returns (uint) {\\n return interestRateModel.getSupplyRate(getCashPrior(), totalBorrows, totalReserves, reserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n require(err == MathError.NO_ERROR, \\\"borrowBalanceStored: borrowBalanceStoredInternal failed\\\");\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return (error code, the calculated balance or 0 if error code is non-zero)\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the CToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n require(err == MathError.NO_ERROR, \\\"exchangeRateStored: exchangeRateStoredInternal failed\\\");\\n return result;\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the CToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return (error code, calculated exchange rate scaled by 1e18)\\n */\\n function exchangeRateStoredInternal() internal view returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows - totalReserves) / totalSupply\\n */\\n uint totalCash = getCashPrior();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Get cash balance of this cToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage.\\n */\\n function accrueInterest() public returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = getBlockNumber();\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = getCashPrior();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n require(mathErr == MathError.NO_ERROR, \\\"could not calculate block delta\\\");\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({mantissa: borrowRateMantissa}), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(Exp({mantissa: reserveFactorMantissa}), interestAccumulated, reservesPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives cTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n struct MintLocalVars {\\n Error err;\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives cTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, 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's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the cToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of cTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.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 cTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED\\\");\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\\");\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender redeems cTokens in exchange for the underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemTokens The number of cTokens to redeem into underlying\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemInternal(uint redeemTokens) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(msg.sender, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems cTokens in exchange for a specified amount of underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemAmount The amount of underlying to receive from redeeming cTokens\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemUnderlyingInternal(uint redeemAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(msg.sender, 0, redeemAmount);\\n }\\n\\n struct RedeemLocalVars {\\n Error err;\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n /**\\n * @notice User redeems cTokens in exchange for the underlying asset\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param redeemTokensIn The number of cTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming cTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemFresh(address payable redeemer, uint redeemTokensIn, uint redeemAmountIn) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr));\\n }\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(Exp({mantissa: vars.exchangeRateMantissa}), redeemTokensIn);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(redeemAmountIn, Exp({mantissa: vars.exchangeRateMantissa}));\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REDEEM_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDEEM_FRESHNESS_CHECK);\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDEEM_TRANSFER_OUT_NOT_POSSIBLE);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We invoke doTransferOut for the redeemer and the redeemAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(redeemer, vars.redeemAmount);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n /* We call the defense hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender borrows assets from the protocol to their own address\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function borrowInternal(uint borrowAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(msg.sender, borrowAmount);\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n /**\\n * @notice Users borrow assets from the protocol to their own address\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function borrowFresh(address payable borrower, uint borrowAmount) internal returns (uint) {\\n /* Fail if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.BORROW_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.BORROW_FRESHNESS_CHECK);\\n }\\n\\n /* Fail gracefully if protocol has insufficient underlying cash */\\n if (getCashPrior() < borrowAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.BORROW_CASH_NOT_AVAILABLE);\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We invoke doTransferOut for the borrower and the borrowAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(borrower, borrowAmount);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to borrower\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer the account paying off the borrow\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount the amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED\\\");\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED\\\");\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this cToken to be liquidated\\n * @param cTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) 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 = cTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, cTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this cToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param cTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowFresh(address liquidator, address borrower, uint repayAmount, CTokenInterface cTokenCollateral) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(address(this), address(cTokenCollateral), liquidator, borrower, repayAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify cTokenCollateral market's block number equals current block number */\\n if (cTokenCollateral.accrualBlockNumber() != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = -1 */\\n if (repayAmount == uint(-1)) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & 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(cTokenCollateral), actualRepayAmount);\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(cTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(cTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = cTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(cTokenCollateral), seizeTokens);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.liquidateBorrowVerify(address(this), address(cTokenCollateral), liquidator, borrower, actualRepayAmount, seizeTokens);\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another cToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed cToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of cTokens to seize\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function seize(address liquidator, address borrower, uint seizeTokens) external nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n struct SeizeInternalLocalVars {\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n uint liquidatorSeizeTokens;\\n uint protocolSeizeTokens;\\n uint protocolSeizeAmount;\\n uint exchangeRateMantissa;\\n uint totalReservesNew;\\n uint totalSupplyNew;\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another CToken.\\n * Its absolutely critical to use msg.sender as the seizer cToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed cToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of cTokens to seize\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function seizeInternal(address seizerToken, address liquidator, address borrower, uint seizeTokens) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n SeizeInternalLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (vars.mathErr, vars.borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(vars.mathErr));\\n }\\n\\n vars.protocolSeizeTokens = mul_(seizeTokens, Exp({mantissa: protocolSeizeShareMantissa}));\\n vars.liquidatorSeizeTokens = sub_(seizeTokens, vars.protocolSeizeTokens);\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n require(vars.mathErr == MathError.NO_ERROR, \\\"exchange rate math error\\\");\\n\\n vars.protocolSeizeAmount = mul_ScalarTruncate(Exp({mantissa: vars.exchangeRateMantissa}), vars.protocolSeizeTokens);\\n\\n vars.totalReservesNew = add_(totalReserves, vars.protocolSeizeAmount);\\n vars.totalSupplyNew = sub_(totalSupply, vars.protocolSeizeTokens);\\n\\n (vars.mathErr, vars.liquidatorTokensNew) = addUInt(accountTokens[liquidator], vars.liquidatorSeizeTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(vars.mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n totalReserves = vars.totalReservesNew;\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[borrower] = vars.borrowerTokensNew;\\n accountTokens[liquidator] = vars.liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, vars.liquidatorSeizeTokens);\\n emit Transfer(borrower, address(this), vars.protocolSeizeTokens);\\n emit ReservesAdded(address(this), vars.protocolSeizeAmount, vars.totalReservesNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n\\n /*** Admin Functions ***/\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPendingAdmin(address payable newPendingAdmin) external returns (uint) {\\n // Check caller = admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\\n }\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptAdmin() external returns (uint) {\\n // Check caller is pendingAdmin and pendingAdmin \\u2260 address(0)\\n if (msg.sender != pendingAdmin || msg.sender == address(0)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = address(0);\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setComptroller(ComptrollerInterface newComptroller) public returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_COMPTROLLER_OWNER_CHECK);\\n }\\n\\n ComptrollerInterface oldComptroller = comptroller;\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(oldComptroller, newComptroller);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh\\n * @dev Admin function to accrue interest and set a new reserve factor\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setReserveFactor(uint newReserveFactorMantissa) external nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\\n * @dev Admin function to set a new reserve factor\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_RESERVE_FACTOR_ADMIN_CHECK);\\n }\\n\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring from msg.sender\\n * @param addAmount Amount of addition to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to admin\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _reduceReserves(uint reduceAmount) external nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to admin\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _reduceReservesFresh(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's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n totalReservesNew = totalReserves - reduceAmount;\\n // We checked reduceAmount <= totalReserves above, so this should never revert.\\n require(totalReservesNew <= 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't be sure if side effects occurred.\\n doTransferOut(admin, reduceAmount);\\n\\n emit ReservesReduced(admin, reduceAmount, totalReservesNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Admin function to accrue interest and update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel);\\n }\\n\\n /**\\n * @notice updates the interest rate model (*requires fresh interest accrual)\\n * @dev Admin function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal returns (uint) {\\n\\n // Used to store old model for use in the event that is emitted on success\\n InterestRateModel oldInterestRateModel;\\n\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_INTEREST_RATE_MODEL_OWNER_CHECK);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Track the market's current interest rate model\\n oldInterestRateModel = interestRateModel;\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view returns (uint);\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure tather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal;\\n\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n}\\n\",\"keccak256\":\"0x436ec2e309682995f8a82dfdd9e8f75928599c10a9a680dddbee6c275014008d\"},\"contracts/CTokenInterfaces.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./InterestRateModel.sol\\\";\\nimport \\\"./EIP20NonStandardInterface.sol\\\";\\n\\ncontract CTokenStorage {\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-cToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModel public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first CTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping (address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping (address => mapping (address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Share of seized collateral that is added to reserves\\n */\\n uint public constant protocolSeizeShareMantissa = 2.8e16; //2.8%\\n\\n}\\n\\ncontract CTokenInterface is CTokenStorage {\\n /**\\n * @notice Indicator that this is a CToken contract (for inspection)\\n */\\n bool public constant isCToken = true;\\n\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(address liquidator, address borrower, uint repayAmount, address cTokenCollateral, uint seizeTokens);\\n\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin is updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(InterestRateModel oldInterestRateModel, InterestRateModel newInterestRateModel);\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address admin, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Failure event\\n */\\n event Failure(uint error, uint info, uint detail);\\n\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external returns (bool);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function approve(address spender, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function balanceOfUnderlying(address owner) external returns (uint);\\n function getAccountSnapshot(address account) external view returns (uint, uint, uint, uint);\\n function borrowRatePerBlock() external view returns (uint);\\n function supplyRatePerBlock() external view returns (uint);\\n function totalBorrowsCurrent() external returns (uint);\\n function borrowBalanceCurrent(address account) external returns (uint);\\n function borrowBalanceStored(address account) public view returns (uint);\\n function exchangeRateCurrent() public returns (uint);\\n function exchangeRateStored() public view returns (uint);\\n function getCash() external view returns (uint);\\n function accrueInterest() public returns (uint);\\n function seize(address liquidator, address borrower, uint seizeTokens) external returns (uint);\\n\\n\\n /*** Admin Functions ***/\\n\\n function _setPendingAdmin(address payable newPendingAdmin) external returns (uint);\\n function _acceptAdmin() external returns (uint);\\n function _setComptroller(ComptrollerInterface newComptroller) public returns (uint);\\n function _setReserveFactor(uint newReserveFactorMantissa) external returns (uint);\\n function _reduceReserves(uint reduceAmount) external returns (uint);\\n function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint);\\n}\\n\\ncontract CErc20Storage {\\n /**\\n * @notice Underlying asset for this CToken\\n */\\n address public underlying;\\n}\\n\\ncontract CErc20Interface is CErc20Storage {\\n\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n function redeem(uint redeemTokens) external returns (uint);\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n function borrow(uint borrowAmount) external returns (uint);\\n function repayBorrow(uint repayAmount) external returns (uint);\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n function liquidateBorrow(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) external returns (uint);\\n function sweepToken(EIP20NonStandardInterface token) external;\\n\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ncontract CDelegationStorage {\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n}\\n\\ncontract CDelegatorInterface is CDelegationStorage {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(address implementation_, bool allowResign, bytes memory becomeImplementationData) public;\\n}\\n\\ncontract CDelegateInterface is CDelegationStorage {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) public;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() public;\\n}\\n\",\"keccak256\":\"0x963bbf60b4c0b76900b3fcb2db8c8be634934b37b4113f1055e57a308197d21a\"},\"contracts/CarefulMath.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Careful Math\\n * @author Compound\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c = a * b;\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n return (MathError.NO_ERROR, a - b);\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c = a + b;\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\",\"keccak256\":\"0x0647348f27e41d22555d99eebd217dee02a4d737df6accd7cce5347a7487c7de\"},\"contracts/ComptrollerG7.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.sol\\\";\\nimport \\\"./ErrorReporter.sol\\\";\\nimport \\\"./PriceOracle.sol\\\";\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./ComptrollerStorage.sol\\\";\\nimport \\\"./Unitroller.sol\\\";\\nimport \\\"./Governance/Comp.sol\\\";\\n\\n/**\\n * @title Compound's Comptroller Contract\\n * @author Compound\\n */\\ncontract ComptrollerG7 is ComptrollerV5Storage, ComptrollerInterface, ComptrollerErrorReporter, ExponentialNoError {\\n /// @notice Emitted when an admin supports a market\\n event MarketListed(CToken cToken);\\n\\n /// @notice Emitted when an account enters a market\\n event MarketEntered(CToken cToken, address account);\\n\\n /// @notice Emitted when an account exits a market\\n event MarketExited(CToken cToken, 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(CToken cToken, uint oldCollateralFactorMantissa, uint newCollateralFactorMantissa);\\n\\n /// @notice Emitted when liquidation incentive is changed by admin\\n event NewLiquidationIncentive(uint oldLiquidationIncentiveMantissa, uint newLiquidationIncentiveMantissa);\\n\\n /// @notice Emitted when price oracle is changed\\n event NewPriceOracle(PriceOracle oldPriceOracle, PriceOracle newPriceOracle);\\n\\n /// @notice Emitted when pause guardian is changed\\n event NewPauseGuardian(address oldPauseGuardian, address newPauseGuardian);\\n\\n /// @notice Emitted when an action is paused globally\\n event ActionPaused(string action, bool pauseState);\\n\\n /// @notice Emitted when an action is paused on a market\\n event ActionPaused(CToken cToken, string action, bool pauseState);\\n\\n /// @notice Emitted when a new COMP speed is calculated for a market\\n event CompSpeedUpdated(CToken indexed cToken, uint newSpeed);\\n\\n /// @notice Emitted when a new COMP speed is set for a contributor\\n event ContributorCompSpeedUpdated(address indexed contributor, uint newSpeed);\\n\\n /// @notice Emitted when COMP is distributed to a supplier\\n event DistributedSupplierComp(CToken indexed cToken, address indexed supplier, uint compDelta, uint compSupplyIndex);\\n\\n /// @notice Emitted when COMP is distributed to a borrower\\n event DistributedBorrowerComp(CToken indexed cToken, address indexed borrower, uint compDelta, uint compBorrowIndex);\\n\\n /// @notice Emitted when borrow cap for a cToken is changed\\n event NewBorrowCap(CToken indexed cToken, uint newBorrowCap);\\n\\n /// @notice Emitted when borrow cap guardian is changed\\n event NewBorrowCapGuardian(address oldBorrowCapGuardian, address newBorrowCapGuardian);\\n\\n /// @notice Emitted when COMP is granted by admin\\n event CompGranted(address recipient, uint amount);\\n\\n /// @notice The initial COMP index for a market\\n uint224 public constant compInitialIndex = 1e36;\\n\\n // closeFactorMantissa must be strictly greater than this value\\n uint internal constant closeFactorMinMantissa = 0.05e18; // 0.05\\n\\n // closeFactorMantissa must not exceed this value\\n uint internal constant closeFactorMaxMantissa = 0.9e18; // 0.9\\n\\n // No collateralFactorMantissa may exceed this value\\n uint internal constant collateralFactorMaxMantissa = 0.9e18; // 0.9\\n\\n constructor() public {\\n admin = msg.sender;\\n }\\n\\n /*** Assets You Are In ***/\\n\\n /**\\n * @notice Returns the assets an account has entered\\n * @param account The address of the account to pull assets for\\n * @return A dynamic list with the assets the account has entered\\n */\\n function getAssetsIn(address account) external view returns (CToken[] memory) {\\n CToken[] memory assetsIn = accountAssets[account];\\n\\n return assetsIn;\\n }\\n\\n /**\\n * @notice Returns whether the given account is entered in the given asset\\n * @param account The address of the account to check\\n * @param cToken The cToken to check\\n * @return True if the account is in the asset, otherwise false.\\n */\\n function checkMembership(address account, CToken cToken) external view returns (bool) {\\n return markets[address(cToken)].accountMembership[account];\\n }\\n\\n /**\\n * @notice Add assets to be included in account liquidity calculation\\n * @param cTokens The list of addresses of the cToken markets to be enabled\\n * @return Success indicator for whether each corresponding market was entered\\n */\\n function enterMarkets(address[] memory cTokens) public returns (uint[] memory) {\\n uint len = cTokens.length;\\n\\n uint[] memory results = new uint[](len);\\n for (uint i = 0; i < len; i++) {\\n CToken cToken = CToken(cTokens[i]);\\n\\n results[i] = uint(addToMarketInternal(cToken, msg.sender));\\n }\\n\\n return results;\\n }\\n\\n /**\\n * @notice Add the market to the borrower's \\\"assets in\\\" for liquidity calculations\\n * @param cToken The market to enter\\n * @param borrower The address of the account to modify\\n * @return Success indicator for whether the market was entered\\n */\\n function addToMarketInternal(CToken cToken, address borrower) internal returns (Error) {\\n Market storage marketToJoin = markets[address(cToken)];\\n\\n if (!marketToJoin.isListed) {\\n // market is not listed, cannot join\\n return Error.MARKET_NOT_LISTED;\\n }\\n\\n if (marketToJoin.accountMembership[borrower] == true) {\\n // already joined\\n return Error.NO_ERROR;\\n }\\n\\n // survived the gauntlet, add to list\\n // NOTE: we store these somewhat redundantly as a significant optimization\\n // this avoids having to iterate through the list for the most common use cases\\n // that is, only when we need to perform liquidity checks\\n // and not whenever we want to check if an account is in a particular market\\n marketToJoin.accountMembership[borrower] = true;\\n accountAssets[borrower].push(cToken);\\n\\n emit MarketEntered(cToken, borrower);\\n\\n return Error.NO_ERROR;\\n }\\n\\n /**\\n * @notice Removes asset from sender's 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 cTokenAddress The address of the asset to be removed\\n * @return Whether or not the account successfully exited the market\\n */\\n function exitMarket(address cTokenAddress) external returns (uint) {\\n CToken cToken = CToken(cTokenAddress);\\n /* Get sender tokensHeld and amountOwed underlying from the cToken */\\n (uint oErr, uint tokensHeld, uint amountOwed, ) = cToken.getAccountSnapshot(msg.sender);\\n require(oErr == 0, \\\"exitMarket: getAccountSnapshot failed\\\"); // semi-opaque error code\\n\\n /* Fail if the sender has a borrow balance */\\n if (amountOwed != 0) {\\n return fail(Error.NONZERO_BORROW_BALANCE, FailureInfo.EXIT_MARKET_BALANCE_OWED);\\n }\\n\\n /* Fail if the sender is not permitted to redeem all of their tokens */\\n uint allowed = redeemAllowedInternal(cTokenAddress, msg.sender, tokensHeld);\\n if (allowed != 0) {\\n return failOpaque(Error.REJECTION, FailureInfo.EXIT_MARKET_REJECTION, allowed);\\n }\\n\\n Market storage marketToExit = markets[address(cToken)];\\n\\n /* Return true if the sender is not already \\u2018in\\u2019 the market */\\n if (!marketToExit.accountMembership[msg.sender]) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Set cToken account membership to false */\\n delete marketToExit.accountMembership[msg.sender];\\n\\n /* Delete cToken from the account\\u2019s list of assets */\\n // load into memory for faster iteration\\n CToken[] memory userAssetList = accountAssets[msg.sender];\\n uint len = userAssetList.length;\\n uint assetIndex = len;\\n for (uint i = 0; i < len; i++) {\\n if (userAssetList[i] == cToken) {\\n assetIndex = i;\\n break;\\n }\\n }\\n\\n // We *must* have found the asset in the list or our redundant data structure is broken\\n assert(assetIndex < len);\\n\\n // copy last item in list to location of item to be removed, reduce length by 1\\n CToken[] storage storedList = accountAssets[msg.sender];\\n storedList[assetIndex] = storedList[storedList.length - 1];\\n storedList.length--;\\n\\n emit MarketExited(cToken, 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 cToken The market to verify the mint against\\n * @param minter The account which would get the minted tokens\\n * @param mintAmount The amount of underlying being supplied to the market in exchange for tokens\\n * @return 0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function mintAllowed(address cToken, address minter, uint mintAmount) external returns (uint) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n require(!mintGuardianPaused[cToken], \\\"mint is paused\\\");\\n\\n // Shh - currently unused\\n minter;\\n mintAmount;\\n\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n // Keep the flywheel moving\\n updateCompSupplyIndex(cToken);\\n distributeSupplierComp(cToken, minter);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates mint and reverts on rejection. May emit logs.\\n * @param cToken Asset being minted\\n * @param minter The address minting the tokens\\n * @param actualMintAmount The amount of the underlying asset being minted\\n * @param mintTokens The number of tokens being minted\\n */\\n function mintVerify(address cToken, address minter, uint actualMintAmount, uint mintTokens) external {\\n // Shh - currently unused\\n cToken;\\n minter;\\n actualMintAmount;\\n mintTokens;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to redeem tokens in the given market\\n * @param cToken The market to verify the redeem against\\n * @param redeemer The account which would redeem the tokens\\n * @param redeemTokens The number of cTokens to exchange for the underlying asset in the market\\n * @return 0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function redeemAllowed(address cToken, address redeemer, uint redeemTokens) external returns (uint) {\\n uint allowed = redeemAllowedInternal(cToken, redeemer, redeemTokens);\\n if (allowed != uint(Error.NO_ERROR)) {\\n return allowed;\\n }\\n\\n // Keep the flywheel moving\\n updateCompSupplyIndex(cToken);\\n distributeSupplierComp(cToken, redeemer);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n function redeemAllowedInternal(address cToken, address redeemer, uint redeemTokens) internal view returns (uint) {\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!markets[cToken].accountMembership[redeemer]) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n (Error err, , uint shortfall) = getHypotheticalAccountLiquidityInternal(redeemer, CToken(cToken), redeemTokens, 0);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n if (shortfall > 0) {\\n return uint(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates redeem and reverts on rejection. May emit logs.\\n * @param cToken Asset being redeemed\\n * @param redeemer The address redeeming the tokens\\n * @param redeemAmount The amount of the underlying asset being redeemed\\n * @param redeemTokens The number of tokens being redeemed\\n */\\n function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) external {\\n // Shh - currently unused\\n cToken;\\n redeemer;\\n\\n // Require tokens is zero or amount is also zero\\n if (redeemTokens == 0 && redeemAmount > 0) {\\n revert(\\\"redeemTokens zero\\\");\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to borrow the underlying asset of the given market\\n * @param cToken The market to verify the borrow against\\n * @param borrower The account which would borrow the asset\\n * @param borrowAmount The amount of underlying the account would borrow\\n * @return 0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function borrowAllowed(address cToken, address borrower, uint borrowAmount) external returns (uint) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n require(!borrowGuardianPaused[cToken], \\\"borrow is paused\\\");\\n\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n if (!markets[cToken].accountMembership[borrower]) {\\n // only cTokens may call borrowAllowed if borrower not in market\\n require(msg.sender == cToken, \\\"sender must be cToken\\\");\\n\\n // attempt to add borrower to the market\\n Error err = addToMarketInternal(CToken(msg.sender), borrower);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n\\n // it should be impossible to break the important invariant\\n assert(markets[cToken].accountMembership[borrower]);\\n }\\n\\n if (oracle.getUnderlyingPrice(CToken(cToken)) == 0) {\\n return uint(Error.PRICE_ERROR);\\n }\\n\\n\\n uint borrowCap = borrowCaps[cToken];\\n // Borrow cap of 0 corresponds to unlimited borrowing\\n if (borrowCap != 0) {\\n uint totalBorrows = CToken(cToken).totalBorrows();\\n uint nextTotalBorrows = add_(totalBorrows, borrowAmount);\\n require(nextTotalBorrows < borrowCap, \\\"market borrow cap reached\\\");\\n }\\n\\n (Error err, , uint shortfall) = getHypotheticalAccountLiquidityInternal(borrower, CToken(cToken), 0, borrowAmount);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n if (shortfall > 0) {\\n return uint(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n\\n // Keep the flywheel moving\\n Exp memory borrowIndex = Exp({mantissa: CToken(cToken).borrowIndex()});\\n updateCompBorrowIndex(cToken, borrowIndex);\\n distributeBorrowerComp(cToken, 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 cToken Asset whose underlying is being borrowed\\n * @param borrower The address borrowing the underlying\\n * @param borrowAmount The amount of the underlying asset requested to borrow\\n */\\n function borrowVerify(address cToken, address borrower, uint borrowAmount) external {\\n // Shh - currently unused\\n cToken;\\n borrower;\\n borrowAmount;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to repay a borrow in the given market\\n * @param cToken The market to verify the repay against\\n * @param payer The account which would repay the asset\\n * @param borrower The account which would borrowed the asset\\n * @param repayAmount The amount of the underlying asset the account would repay\\n * @return 0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function repayBorrowAllowed(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount) external returns (uint) {\\n // Shh - currently unused\\n payer;\\n borrower;\\n repayAmount;\\n\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n // Keep the flywheel moving\\n Exp memory borrowIndex = Exp({mantissa: CToken(cToken).borrowIndex()});\\n updateCompBorrowIndex(cToken, borrowIndex);\\n distributeBorrowerComp(cToken, borrower, borrowIndex);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates repayBorrow and reverts on rejection. May emit logs.\\n * @param cToken Asset being repaid\\n * @param payer The address repaying the borrow\\n * @param borrower The address of the borrower\\n * @param actualRepayAmount The amount of underlying being repaid\\n */\\n function repayBorrowVerify(\\n address cToken,\\n address payer,\\n address borrower,\\n uint actualRepayAmount,\\n uint borrowerIndex) external {\\n // Shh - currently unused\\n cToken;\\n payer;\\n borrower;\\n actualRepayAmount;\\n borrowerIndex;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the liquidation should be allowed to occur\\n * @param cTokenBorrowed Asset which was borrowed by the borrower\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param repayAmount The amount of underlying being repaid\\n */\\n function liquidateBorrowAllowed(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount) external returns (uint) {\\n // Shh - currently unused\\n liquidator;\\n\\n if (!markets[cTokenBorrowed].isListed || !markets[cTokenCollateral].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n /* The borrower must have shortfall in order to be liquidatable */\\n (Error err, , uint shortfall) = getAccountLiquidityInternal(borrower);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n if (shortfall == 0) {\\n return uint(Error.INSUFFICIENT_SHORTFALL);\\n }\\n\\n /* The liquidator may not repay more than what is allowed by the closeFactor */\\n uint borrowBalance = CToken(cTokenBorrowed).borrowBalanceStored(borrower);\\n uint maxClose = mul_ScalarTruncate(Exp({mantissa: closeFactorMantissa}), borrowBalance);\\n if (repayAmount > 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 cTokenBorrowed Asset which was borrowed by the borrower\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param actualRepayAmount The amount of underlying being repaid\\n */\\n function liquidateBorrowVerify(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint actualRepayAmount,\\n uint seizeTokens) external {\\n // Shh - currently unused\\n cTokenBorrowed;\\n cTokenCollateral;\\n liquidator;\\n borrower;\\n actualRepayAmount;\\n seizeTokens;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the seizing of assets should be allowed to occur\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param cTokenBorrowed Asset which was borrowed by the borrower\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param seizeTokens The number of collateral tokens to seize\\n */\\n function seizeAllowed(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external returns (uint) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n require(!seizeGuardianPaused, \\\"seize is paused\\\");\\n\\n // Shh - currently unused\\n seizeTokens;\\n\\n if (!markets[cTokenCollateral].isListed || !markets[cTokenBorrowed].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n if (CToken(cTokenCollateral).comptroller() != CToken(cTokenBorrowed).comptroller()) {\\n return uint(Error.COMPTROLLER_MISMATCH);\\n }\\n\\n // Keep the flywheel moving\\n updateCompSupplyIndex(cTokenCollateral);\\n distributeSupplierComp(cTokenCollateral, borrower);\\n distributeSupplierComp(cTokenCollateral, liquidator);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates seize and reverts on rejection. May emit logs.\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param cTokenBorrowed Asset which was borrowed by the borrower\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param seizeTokens The number of collateral tokens to seize\\n */\\n function seizeVerify(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external {\\n // Shh - currently unused\\n cTokenCollateral;\\n cTokenBorrowed;\\n liquidator;\\n borrower;\\n seizeTokens;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to transfer tokens in the given market\\n * @param cToken The market to verify the transfer against\\n * @param src The account which sources the tokens\\n * @param dst The account which receives the tokens\\n * @param transferTokens The number of cTokens to transfer\\n * @return 0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function transferAllowed(address cToken, address src, address dst, uint transferTokens) external returns (uint) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n require(!transferGuardianPaused, \\\"transfer is paused\\\");\\n\\n // Currently the only consideration is whether or not\\n // the src is allowed to redeem this many tokens\\n uint allowed = redeemAllowedInternal(cToken, src, transferTokens);\\n if (allowed != uint(Error.NO_ERROR)) {\\n return allowed;\\n }\\n\\n // Keep the flywheel moving\\n updateCompSupplyIndex(cToken);\\n distributeSupplierComp(cToken, src);\\n distributeSupplierComp(cToken, dst);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates transfer and reverts on rejection. May emit logs.\\n * @param cToken Asset being transferred\\n * @param src The account which sources the tokens\\n * @param dst The account which receives the tokens\\n * @param transferTokens The number of cTokens to transfer\\n */\\n function transferVerify(address cToken, address src, address dst, uint transferTokens) external {\\n // Shh - currently unused\\n cToken;\\n src;\\n dst;\\n transferTokens;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n /**\\n * @dev Local vars for avoiding stack-depth limits in calculating account liquidity.\\n * Note that `cTokenBalance` is the number of cTokens the account owns in the market,\\n * whereas `borrowBalance` is the amount of underlying that the account has borrowed.\\n */\\n struct AccountLiquidityLocalVars {\\n uint sumCollateral;\\n uint sumBorrowPlusEffects;\\n uint cTokenBalance;\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n uint oraclePriceMantissa;\\n Exp collateralFactor;\\n Exp exchangeRate;\\n Exp oraclePrice;\\n Exp tokensToDenom;\\n }\\n\\n /**\\n * @notice Determine the current account liquidity wrt collateral requirements\\n * @return (possible error code (semi-opaque),\\n account liquidity in excess of collateral requirements,\\n * account shortfall below collateral requirements)\\n */\\n function getAccountLiquidity(address account) public view returns (uint, uint, uint) {\\n (Error err, uint liquidity, uint shortfall) = getHypotheticalAccountLiquidityInternal(account, CToken(0), 0, 0);\\n\\n return (uint(err), liquidity, shortfall);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity wrt collateral requirements\\n * @return (possible error code,\\n account liquidity in excess of collateral requirements,\\n * account shortfall below collateral requirements)\\n */\\n function getAccountLiquidityInternal(address account) internal view returns (Error, uint, uint) {\\n return getHypotheticalAccountLiquidityInternal(account, CToken(0), 0, 0);\\n }\\n\\n /**\\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\\n * @param cTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @return (possible error code (semi-opaque),\\n hypothetical account liquidity in excess of collateral requirements,\\n * hypothetical account shortfall below collateral requirements)\\n */\\n function getHypotheticalAccountLiquidity(\\n address account,\\n address cTokenModify,\\n uint redeemTokens,\\n uint borrowAmount) public view returns (uint, uint, uint) {\\n (Error err, uint liquidity, uint shortfall) = getHypotheticalAccountLiquidityInternal(account, CToken(cTokenModify), 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 cTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @dev Note that we calculate the exchangeRateStored for each collateral cToken using stored data,\\n * without calculating accumulated interest.\\n * @return (possible error code,\\n hypothetical account liquidity in excess of collateral requirements,\\n * hypothetical account shortfall below collateral requirements)\\n */\\n function getHypotheticalAccountLiquidityInternal(\\n address account,\\n CToken cTokenModify,\\n uint redeemTokens,\\n uint borrowAmount) internal view returns (Error, uint, uint) {\\n\\n AccountLiquidityLocalVars memory vars; // Holds all our calculation results\\n uint oErr;\\n\\n // For each asset the account is in\\n CToken[] memory assets = accountAssets[account];\\n for (uint i = 0; i < assets.length; i++) {\\n CToken asset = assets[i];\\n\\n // Read the balances and exchange rate from the cToken\\n (oErr, vars.cTokenBalance, vars.borrowBalance, vars.exchangeRateMantissa) = asset.getAccountSnapshot(account);\\n if (oErr != 0) { // semi-opaque error code, we assume NO_ERROR == 0 is invariant between upgrades\\n return (Error.SNAPSHOT_ERROR, 0, 0);\\n }\\n vars.collateralFactor = Exp({mantissa: markets[address(asset)].collateralFactorMantissa});\\n vars.exchangeRate = Exp({mantissa: vars.exchangeRateMantissa});\\n\\n // Get the normalized price of the asset\\n vars.oraclePriceMantissa = oracle.getUnderlyingPrice(asset);\\n if (vars.oraclePriceMantissa == 0) {\\n return (Error.PRICE_ERROR, 0, 0);\\n }\\n vars.oraclePrice = Exp({mantissa: vars.oraclePriceMantissa});\\n\\n // Pre-compute a conversion factor from tokens -> ether (normalized price value)\\n vars.tokensToDenom = mul_(mul_(vars.collateralFactor, vars.exchangeRate), vars.oraclePrice);\\n\\n // sumCollateral += tokensToDenom * cTokenBalance\\n vars.sumCollateral = mul_ScalarTruncateAddUInt(vars.tokensToDenom, vars.cTokenBalance, vars.sumCollateral);\\n\\n // sumBorrowPlusEffects += oraclePrice * borrowBalance\\n vars.sumBorrowPlusEffects = mul_ScalarTruncateAddUInt(vars.oraclePrice, vars.borrowBalance, vars.sumBorrowPlusEffects);\\n\\n // Calculate effects of interacting with cTokenModify\\n if (asset == cTokenModify) {\\n // redeem effect\\n // sumBorrowPlusEffects += tokensToDenom * redeemTokens\\n vars.sumBorrowPlusEffects = mul_ScalarTruncateAddUInt(vars.tokensToDenom, redeemTokens, vars.sumBorrowPlusEffects);\\n\\n // borrow effect\\n // sumBorrowPlusEffects += oraclePrice * borrowAmount\\n vars.sumBorrowPlusEffects = mul_ScalarTruncateAddUInt(vars.oraclePrice, borrowAmount, vars.sumBorrowPlusEffects);\\n }\\n }\\n\\n // These are safe, as the underflow condition is checked first\\n if (vars.sumCollateral > vars.sumBorrowPlusEffects) {\\n return (Error.NO_ERROR, vars.sumCollateral - vars.sumBorrowPlusEffects, 0);\\n } else {\\n return (Error.NO_ERROR, 0, vars.sumBorrowPlusEffects - vars.sumCollateral);\\n }\\n }\\n\\n /**\\n * @notice Calculate number of tokens of collateral asset to seize given an underlying amount\\n * @dev Used in liquidation (called in cToken.liquidateBorrowFresh)\\n * @param cTokenBorrowed The address of the borrowed cToken\\n * @param cTokenCollateral The address of the collateral cToken\\n * @param actualRepayAmount The amount of cTokenBorrowed underlying to convert into cTokenCollateral tokens\\n * @return (errorCode, number of cTokenCollateral tokens to be seized in a liquidation)\\n */\\n function liquidateCalculateSeizeTokens(address cTokenBorrowed, address cTokenCollateral, uint actualRepayAmount) external view returns (uint, uint) {\\n /* Read oracle prices for borrowed and collateral markets */\\n uint priceBorrowedMantissa = oracle.getUnderlyingPrice(CToken(cTokenBorrowed));\\n uint priceCollateralMantissa = oracle.getUnderlyingPrice(CToken(cTokenCollateral));\\n if (priceBorrowedMantissa == 0 || priceCollateralMantissa == 0) {\\n return (uint(Error.PRICE_ERROR), 0);\\n }\\n\\n /*\\n * Get the exchange rate and calculate the number of collateral tokens to seize:\\n * seizeAmount = actualRepayAmount * liquidationIncentive * priceBorrowed / priceCollateral\\n * seizeTokens = seizeAmount / exchangeRate\\n * = actualRepayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate)\\n */\\n uint exchangeRateMantissa = CToken(cTokenCollateral).exchangeRateStored(); // Note: reverts on error\\n uint seizeTokens;\\n Exp memory numerator;\\n Exp memory denominator;\\n Exp memory ratio;\\n\\n numerator = mul_(Exp({mantissa: liquidationIncentiveMantissa}), Exp({mantissa: priceBorrowedMantissa}));\\n denominator = mul_(Exp({mantissa: priceCollateralMantissa}), Exp({mantissa: exchangeRateMantissa}));\\n ratio = div_(numerator, denominator);\\n\\n seizeTokens = mul_ScalarTruncate(ratio, actualRepayAmount);\\n\\n return (uint(Error.NO_ERROR), seizeTokens);\\n }\\n\\n /*** Admin Functions ***/\\n\\n /**\\n * @notice Sets a new price oracle for the comptroller\\n * @dev Admin function to set a new price oracle\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPriceOracle(PriceOracle newOracle) public returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PRICE_ORACLE_OWNER_CHECK);\\n }\\n\\n // Track the old oracle for the comptroller\\n PriceOracle oldOracle = oracle;\\n\\n // Set comptroller's oracle to newOracle\\n oracle = newOracle;\\n\\n // Emit NewPriceOracle(oldOracle, newOracle)\\n emit NewPriceOracle(oldOracle, newOracle);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets the closeFactor used when liquidating borrows\\n * @dev Admin function to set closeFactor\\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\\n * @return uint 0=success, otherwise a failure\\n */\\n function _setCloseFactor(uint newCloseFactorMantissa) external returns (uint) {\\n // Check caller is admin\\n \\trequire(msg.sender == admin, \\\"only admin can set close factor\\\");\\n\\n uint oldCloseFactorMantissa = closeFactorMantissa;\\n closeFactorMantissa = newCloseFactorMantissa;\\n emit NewCloseFactor(oldCloseFactorMantissa, closeFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets the collateralFactor for a market\\n * @dev Admin function to set per-market collateralFactor\\n * @param cToken The market to set the factor on\\n * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18\\n * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function _setCollateralFactor(CToken cToken, 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(cToken)];\\n if (!market.isListed) {\\n return fail(Error.MARKET_NOT_LISTED, FailureInfo.SET_COLLATERAL_FACTOR_NO_EXISTS);\\n }\\n\\n Exp memory newCollateralFactorExp = Exp({mantissa: newCollateralFactorMantissa});\\n\\n // Check collateral factor <= 0.9\\n Exp memory highLimit = Exp({mantissa: collateralFactorMaxMantissa});\\n if (lessThanExp(highLimit, newCollateralFactorExp)) {\\n return fail(Error.INVALID_COLLATERAL_FACTOR, FailureInfo.SET_COLLATERAL_FACTOR_VALIDATION);\\n }\\n\\n // If collateral factor != 0, fail if price == 0\\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(cToken) == 0) {\\n return fail(Error.PRICE_ERROR, FailureInfo.SET_COLLATERAL_FACTOR_WITHOUT_PRICE);\\n }\\n\\n // Set market's collateral factor to new collateral factor, remember old value\\n uint oldCollateralFactorMantissa = market.collateralFactorMantissa;\\n market.collateralFactorMantissa = newCollateralFactorMantissa;\\n\\n // Emit event with asset, old collateral factor, and new collateral factor\\n emit NewCollateralFactor(cToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets liquidationIncentive\\n * @dev Admin function to set liquidationIncentive\\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\\n * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function _setLiquidationIncentive(uint newLiquidationIncentiveMantissa) external returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_LIQUIDATION_INCENTIVE_OWNER_CHECK);\\n }\\n\\n // Save current value for use in log\\n uint oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa;\\n\\n // Set liquidation incentive to new incentive\\n liquidationIncentiveMantissa = newLiquidationIncentiveMantissa;\\n\\n // Emit event with old incentive, new incentive\\n emit NewLiquidationIncentive(oldLiquidationIncentiveMantissa, newLiquidationIncentiveMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Add the market to the markets mapping and set it as listed\\n * @dev Admin function to set isListed and add support for the market\\n * @param cToken The address of the market (token) to list\\n * @return uint 0=success, otherwise a failure. (See enum Error for details)\\n */\\n function _supportMarket(CToken cToken) external returns (uint) {\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SUPPORT_MARKET_OWNER_CHECK);\\n }\\n\\n if (markets[address(cToken)].isListed) {\\n return fail(Error.MARKET_ALREADY_LISTED, FailureInfo.SUPPORT_MARKET_EXISTS);\\n }\\n\\n cToken.isCToken(); // Sanity check to make sure its really a CToken\\n\\n // Note that isComped is not in active use anymore\\n markets[address(cToken)] = Market({isListed: true, isComped: false, collateralFactorMantissa: 0});\\n\\n _addMarketInternal(address(cToken));\\n\\n emit MarketListed(cToken);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n function _addMarketInternal(address cToken) internal {\\n for (uint i = 0; i < allMarkets.length; i ++) {\\n require(allMarkets[i] != CToken(cToken), \\\"market already added\\\");\\n }\\n allMarkets.push(CToken(cToken));\\n }\\n\\n\\n /**\\n * @notice Set the given borrow caps for the given cToken markets. Borrowing that brings total borrows to or above borrow cap will revert.\\n * @dev Admin or borrowCapGuardian function to set the borrow caps. A borrow cap of 0 corresponds to unlimited borrowing.\\n * @param cTokens The addresses of the markets (tokens) to change the borrow caps for\\n * @param newBorrowCaps The new borrow cap values in underlying to be set. A value of 0 corresponds to unlimited borrowing.\\n */\\n function _setMarketBorrowCaps(CToken[] calldata cTokens, uint[] calldata newBorrowCaps) external {\\n \\trequire(msg.sender == admin || msg.sender == borrowCapGuardian, \\\"only admin or borrow cap guardian can set borrow caps\\\"); \\n\\n uint numMarkets = cTokens.length;\\n uint numBorrowCaps = newBorrowCaps.length;\\n\\n require(numMarkets != 0 && numMarkets == numBorrowCaps, \\\"invalid input\\\");\\n\\n for(uint i = 0; i < numMarkets; i++) {\\n borrowCaps[address(cTokens[i])] = newBorrowCaps[i];\\n emit NewBorrowCap(cTokens[i], newBorrowCaps[i]);\\n }\\n }\\n\\n /**\\n * @notice Admin function to change the Borrow Cap Guardian\\n * @param newBorrowCapGuardian The address of the new Borrow Cap Guardian\\n */\\n function _setBorrowCapGuardian(address newBorrowCapGuardian) external {\\n require(msg.sender == admin, \\\"only admin can set borrow cap guardian\\\");\\n\\n // Save current value for inclusion in log\\n address oldBorrowCapGuardian = borrowCapGuardian;\\n\\n // Store borrowCapGuardian with value newBorrowCapGuardian\\n borrowCapGuardian = newBorrowCapGuardian;\\n\\n // Emit NewBorrowCapGuardian(OldBorrowCapGuardian, NewBorrowCapGuardian)\\n emit NewBorrowCapGuardian(oldBorrowCapGuardian, newBorrowCapGuardian);\\n }\\n\\n /**\\n * @notice Admin function to change the Pause Guardian\\n * @param newPauseGuardian The address of the new Pause Guardian\\n * @return uint 0=success, otherwise a failure. (See enum Error for details)\\n */\\n function _setPauseGuardian(address newPauseGuardian) public returns (uint) {\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PAUSE_GUARDIAN_OWNER_CHECK);\\n }\\n\\n // Save current value for inclusion in log\\n address oldPauseGuardian = pauseGuardian;\\n\\n // Store pauseGuardian with value newPauseGuardian\\n pauseGuardian = newPauseGuardian;\\n\\n // Emit NewPauseGuardian(OldPauseGuardian, NewPauseGuardian)\\n emit NewPauseGuardian(oldPauseGuardian, pauseGuardian);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n function _setMintPaused(CToken cToken, bool state) public returns (bool) {\\n require(markets[address(cToken)].isListed, \\\"cannot pause a market that is not listed\\\");\\n require(msg.sender == pauseGuardian || msg.sender == admin, \\\"only pause guardian and admin can pause\\\");\\n require(msg.sender == admin || state == true, \\\"only admin can unpause\\\");\\n\\n mintGuardianPaused[address(cToken)] = state;\\n emit ActionPaused(cToken, \\\"Mint\\\", state);\\n return state;\\n }\\n\\n function _setBorrowPaused(CToken cToken, bool state) public returns (bool) {\\n require(markets[address(cToken)].isListed, \\\"cannot pause a market that is not listed\\\");\\n require(msg.sender == pauseGuardian || msg.sender == admin, \\\"only pause guardian and admin can pause\\\");\\n require(msg.sender == admin || state == true, \\\"only admin can unpause\\\");\\n\\n borrowGuardianPaused[address(cToken)] = state;\\n emit ActionPaused(cToken, \\\"Borrow\\\", state);\\n return state;\\n }\\n\\n function _setTransferPaused(bool state) public returns (bool) {\\n require(msg.sender == pauseGuardian || msg.sender == admin, \\\"only pause guardian and admin can pause\\\");\\n require(msg.sender == admin || state == true, \\\"only admin can unpause\\\");\\n\\n transferGuardianPaused = state;\\n emit ActionPaused(\\\"Transfer\\\", state);\\n return state;\\n }\\n\\n function _setSeizePaused(bool state) public returns (bool) {\\n require(msg.sender == pauseGuardian || msg.sender == admin, \\\"only pause guardian and admin can pause\\\");\\n require(msg.sender == admin || state == true, \\\"only admin can unpause\\\");\\n\\n seizeGuardianPaused = state;\\n emit ActionPaused(\\\"Seize\\\", state);\\n return state;\\n }\\n\\n function _become(Unitroller unitroller) public {\\n require(msg.sender == unitroller.admin(), \\\"only unitroller admin can change brains\\\");\\n require(unitroller._acceptImplementation() == 0, \\\"change not authorized\\\");\\n }\\n\\n /**\\n * @notice Checks caller is admin, or this contract is becoming the new implementation\\n */\\n function adminOrInitializing() internal view returns (bool) {\\n return msg.sender == admin || msg.sender == comptrollerImplementation;\\n }\\n\\n /*** Comp Distribution ***/\\n\\n /**\\n * @notice Set COMP speed for a single market\\n * @param cToken The market whose COMP speed to update\\n * @param compSpeed New COMP speed for market\\n */\\n function setCompSpeedInternal(CToken cToken, uint compSpeed) internal {\\n uint currentCompSpeed = compSpeeds[address(cToken)];\\n if (currentCompSpeed != 0) {\\n // note that COMP speed could be set to 0 to halt liquidity rewards for a market\\n Exp memory borrowIndex = Exp({mantissa: cToken.borrowIndex()});\\n updateCompSupplyIndex(address(cToken));\\n updateCompBorrowIndex(address(cToken), borrowIndex);\\n } else if (compSpeed != 0) {\\n // Add the COMP market\\n Market storage market = markets[address(cToken)];\\n require(market.isListed == true, \\\"comp market is not listed\\\");\\n\\n if (compSupplyState[address(cToken)].index == 0 && compSupplyState[address(cToken)].block == 0) {\\n compSupplyState[address(cToken)] = CompMarketState({\\n index: compInitialIndex,\\n block: safe32(getBlockNumber(), \\\"block number exceeds 32 bits\\\")\\n });\\n }\\n\\n if (compBorrowState[address(cToken)].index == 0 && compBorrowState[address(cToken)].block == 0) {\\n compBorrowState[address(cToken)] = CompMarketState({\\n index: compInitialIndex,\\n block: safe32(getBlockNumber(), \\\"block number exceeds 32 bits\\\")\\n });\\n }\\n }\\n\\n if (currentCompSpeed != compSpeed) {\\n compSpeeds[address(cToken)] = compSpeed;\\n emit CompSpeedUpdated(cToken, compSpeed);\\n }\\n }\\n\\n /**\\n * @notice Accrue COMP to the market by updating the supply index\\n * @param cToken The market whose supply index to update\\n */\\n function updateCompSupplyIndex(address cToken) internal {\\n CompMarketState storage supplyState = compSupplyState[cToken];\\n uint supplySpeed = compSpeeds[cToken];\\n uint blockNumber = getBlockNumber();\\n uint deltaBlocks = sub_(blockNumber, uint(supplyState.block));\\n if (deltaBlocks > 0 && supplySpeed > 0) {\\n uint supplyTokens = CToken(cToken).totalSupply();\\n uint compAccrued = mul_(deltaBlocks, supplySpeed);\\n Double memory ratio = supplyTokens > 0 ? fraction(compAccrued, supplyTokens) : Double({mantissa: 0});\\n Double memory index = add_(Double({mantissa: supplyState.index}), ratio);\\n compSupplyState[cToken] = CompMarketState({\\n index: safe224(index.mantissa, \\\"new index exceeds 224 bits\\\"),\\n block: safe32(blockNumber, \\\"block number exceeds 32 bits\\\")\\n });\\n } else if (deltaBlocks > 0) {\\n supplyState.block = safe32(blockNumber, \\\"block number exceeds 32 bits\\\");\\n }\\n }\\n\\n /**\\n * @notice Accrue COMP to the market by updating the borrow index\\n * @param cToken The market whose borrow index to update\\n */\\n function updateCompBorrowIndex(address cToken, Exp memory marketBorrowIndex) internal {\\n CompMarketState storage borrowState = compBorrowState[cToken];\\n uint borrowSpeed = compSpeeds[cToken];\\n uint blockNumber = getBlockNumber();\\n uint deltaBlocks = sub_(blockNumber, uint(borrowState.block));\\n if (deltaBlocks > 0 && borrowSpeed > 0) {\\n uint borrowAmount = div_(CToken(cToken).totalBorrows(), marketBorrowIndex);\\n uint compAccrued = mul_(deltaBlocks, borrowSpeed);\\n Double memory ratio = borrowAmount > 0 ? fraction(compAccrued, borrowAmount) : Double({mantissa: 0});\\n Double memory index = add_(Double({mantissa: borrowState.index}), ratio);\\n compBorrowState[cToken] = CompMarketState({\\n index: safe224(index.mantissa, \\\"new index exceeds 224 bits\\\"),\\n block: safe32(blockNumber, \\\"block number exceeds 32 bits\\\")\\n });\\n } else if (deltaBlocks > 0) {\\n borrowState.block = safe32(blockNumber, \\\"block number exceeds 32 bits\\\");\\n }\\n }\\n\\n /**\\n * @notice Calculate COMP accrued by a supplier and possibly transfer it to them\\n * @param cToken The market in which the supplier is interacting\\n * @param supplier The address of the supplier to distribute COMP to\\n */\\n function distributeSupplierComp(address cToken, address supplier) internal {\\n CompMarketState storage supplyState = compSupplyState[cToken];\\n Double memory supplyIndex = Double({mantissa: supplyState.index});\\n Double memory supplierIndex = Double({mantissa: compSupplierIndex[cToken][supplier]});\\n compSupplierIndex[cToken][supplier] = supplyIndex.mantissa;\\n\\n if (supplierIndex.mantissa == 0 && supplyIndex.mantissa > 0) {\\n supplierIndex.mantissa = compInitialIndex;\\n }\\n\\n Double memory deltaIndex = sub_(supplyIndex, supplierIndex);\\n uint supplierTokens = CToken(cToken).balanceOf(supplier);\\n uint supplierDelta = mul_(supplierTokens, deltaIndex);\\n uint supplierAccrued = add_(compAccrued[supplier], supplierDelta);\\n compAccrued[supplier] = supplierAccrued;\\n emit DistributedSupplierComp(CToken(cToken), supplier, supplierDelta, supplyIndex.mantissa);\\n }\\n\\n /**\\n * @notice Calculate COMP accrued by a borrower and possibly transfer it to them\\n * @dev Borrowers will not begin to accrue until after the first interaction with the protocol.\\n * @param cToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute COMP to\\n */\\n function distributeBorrowerComp(address cToken, address borrower, Exp memory marketBorrowIndex) internal {\\n CompMarketState storage borrowState = compBorrowState[cToken];\\n Double memory borrowIndex = Double({mantissa: borrowState.index});\\n Double memory borrowerIndex = Double({mantissa: compBorrowerIndex[cToken][borrower]});\\n compBorrowerIndex[cToken][borrower] = borrowIndex.mantissa;\\n\\n if (borrowerIndex.mantissa > 0) {\\n Double memory deltaIndex = sub_(borrowIndex, borrowerIndex);\\n uint borrowerAmount = div_(CToken(cToken).borrowBalanceStored(borrower), marketBorrowIndex);\\n uint borrowerDelta = mul_(borrowerAmount, deltaIndex);\\n uint borrowerAccrued = add_(compAccrued[borrower], borrowerDelta);\\n compAccrued[borrower] = borrowerAccrued;\\n emit DistributedBorrowerComp(CToken(cToken), borrower, borrowerDelta, borrowIndex.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Calculate additional accrued COMP for a contributor since last accrual\\n * @param contributor The address to calculate contributor rewards for\\n */\\n function updateContributorRewards(address contributor) public {\\n uint compSpeed = compContributorSpeeds[contributor];\\n uint blockNumber = getBlockNumber();\\n uint deltaBlocks = sub_(blockNumber, lastContributorBlock[contributor]);\\n if (deltaBlocks > 0 && compSpeed > 0) {\\n uint newAccrued = mul_(deltaBlocks, compSpeed);\\n uint contributorAccrued = add_(compAccrued[contributor], newAccrued);\\n\\n compAccrued[contributor] = contributorAccrued;\\n lastContributorBlock[contributor] = blockNumber;\\n }\\n }\\n\\n /**\\n * @notice Claim all the comp accrued by holder in all markets\\n * @param holder The address to claim COMP for\\n */\\n function claimComp(address holder) public {\\n return claimComp(holder, allMarkets);\\n }\\n\\n /**\\n * @notice Claim all the comp accrued by holder in the specified markets\\n * @param holder The address to claim COMP for\\n * @param cTokens The list of markets to claim COMP in\\n */\\n function claimComp(address holder, CToken[] memory cTokens) public {\\n address[] memory holders = new address[](1);\\n holders[0] = holder;\\n claimComp(holders, cTokens, true, true);\\n }\\n\\n /**\\n * @notice Claim all comp accrued by the holders\\n * @param holders The addresses to claim COMP for\\n * @param cTokens The list of markets to claim COMP in\\n * @param borrowers Whether or not to claim COMP earned by borrowing\\n * @param suppliers Whether or not to claim COMP earned by supplying\\n */\\n function claimComp(address[] memory holders, CToken[] memory cTokens, bool borrowers, bool suppliers) public {\\n for (uint i = 0; i < cTokens.length; i++) {\\n CToken cToken = cTokens[i];\\n require(markets[address(cToken)].isListed, \\\"market must be listed\\\");\\n if (borrowers == true) {\\n Exp memory borrowIndex = Exp({mantissa: cToken.borrowIndex()});\\n updateCompBorrowIndex(address(cToken), borrowIndex);\\n for (uint j = 0; j < holders.length; j++) {\\n distributeBorrowerComp(address(cToken), holders[j], borrowIndex);\\n compAccrued[holders[j]] = grantCompInternal(holders[j], compAccrued[holders[j]]);\\n }\\n }\\n if (suppliers == true) {\\n updateCompSupplyIndex(address(cToken));\\n for (uint j = 0; j < holders.length; j++) {\\n distributeSupplierComp(address(cToken), holders[j]);\\n compAccrued[holders[j]] = grantCompInternal(holders[j], compAccrued[holders[j]]);\\n }\\n }\\n }\\n }\\n\\n /**\\n * @notice Transfer COMP to the user\\n * @dev Note: If there is not enough COMP, we do not perform the transfer all.\\n * @param user The address of the user to transfer COMP to\\n * @param amount The amount of COMP to (possibly) transfer\\n * @return The amount of COMP which was NOT transferred to the user\\n */\\n function grantCompInternal(address user, uint amount) internal returns (uint) {\\n Comp comp = Comp(getCompAddress());\\n uint compRemaining = comp.balanceOf(address(this));\\n if (amount > 0 && amount <= compRemaining) {\\n comp.transfer(user, amount);\\n return 0;\\n }\\n return amount;\\n }\\n\\n /*** Comp Distribution Admin ***/\\n\\n /**\\n * @notice Transfer COMP to the recipient\\n * @dev Note: If there is not enough COMP, we do not perform the transfer all.\\n * @param recipient The address of the recipient to transfer COMP to\\n * @param amount The amount of COMP to (possibly) transfer\\n */\\n function _grantComp(address recipient, uint amount) public {\\n require(adminOrInitializing(), \\\"only admin can grant comp\\\");\\n uint amountLeft = grantCompInternal(recipient, amount);\\n require(amountLeft == 0, \\\"insufficient comp for grant\\\");\\n emit CompGranted(recipient, amount);\\n }\\n\\n /**\\n * @notice Set COMP speed for a single market\\n * @param cToken The market whose COMP speed to update\\n * @param compSpeed New COMP speed for market\\n */\\n function _setCompSpeed(CToken cToken, uint compSpeed) public {\\n require(adminOrInitializing(), \\\"only admin can set comp speed\\\");\\n setCompSpeedInternal(cToken, compSpeed);\\n }\\n\\n /**\\n * @notice Set COMP speed for a single contributor\\n * @param contributor The contributor whose COMP speed to update\\n * @param compSpeed New COMP speed for contributor\\n */\\n function _setContributorCompSpeed(address contributor, uint compSpeed) public {\\n require(adminOrInitializing(), \\\"only admin can set comp speed\\\");\\n\\n // note that COMP speed could be set to 0 to halt liquidity rewards for a contributor\\n updateContributorRewards(contributor);\\n if (compSpeed == 0) {\\n // release storage\\n delete lastContributorBlock[contributor];\\n } else {\\n lastContributorBlock[contributor] = getBlockNumber();\\n }\\n compContributorSpeeds[contributor] = compSpeed;\\n\\n emit ContributorCompSpeedUpdated(contributor, compSpeed);\\n }\\n\\n /**\\n * @notice Return all of the markets\\n * @dev The automatic getter may be used to access an individual market.\\n * @return The list of market addresses\\n */\\n function getAllMarkets() public view returns (CToken[] memory) {\\n return allMarkets;\\n }\\n\\n function getBlockNumber() public view returns (uint) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Return the address of the COMP token\\n * @return The address of COMP\\n */\\n function getCompAddress() public view returns (address) {\\n return 0xc00e94Cb662C3520282E6f5717214004A7f26888;\\n }\\n}\",\"keccak256\":\"0xbdc5dd5da44b48582b2405864b059a7736cffe52ec64d6561896dc99c5329b30\"},\"contracts/ComptrollerInterface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\ncontract ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n bool public constant isComptroller = true;\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata cTokens) external returns (uint[] memory);\\n function exitMarket(address cToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address cToken, address minter, uint mintAmount) external returns (uint);\\n function mintVerify(address cToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address cToken, address redeemer, uint redeemTokens) external returns (uint);\\n function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address cToken, address borrower, uint borrowAmount) external returns (uint);\\n function borrowVerify(address cToken, address borrower, uint borrowAmount) external;\\n\\n function repayBorrowAllowed(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount) external returns (uint);\\n function repayBorrowVerify(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex) external;\\n\\n function liquidateBorrowAllowed(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount) external returns (uint);\\n function liquidateBorrowVerify(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens) external;\\n\\n function seizeAllowed(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external returns (uint);\\n function seizeVerify(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external;\\n\\n function transferAllowed(address cToken, address src, address dst, uint transferTokens) external returns (uint);\\n function transferVerify(address cToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n uint repayAmount) external view returns (uint, uint);\\n}\\n\",\"keccak256\":\"0xede7670d2dd7b25d0187aecd2c28b7b5ca7d7c1bdac144fbedecf5d4bdd92a6b\"},\"contracts/ComptrollerStorage.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.sol\\\";\\nimport \\\"./PriceOracle.sol\\\";\\n\\ncontract UnitrollerAdminStorage {\\n /**\\n * @notice Administrator for this contract\\n */\\n address public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address public pendingAdmin;\\n\\n /**\\n * @notice Active brains of Unitroller\\n */\\n address public comptrollerImplementation;\\n\\n /**\\n * @notice Pending brains of Unitroller\\n */\\n address public pendingComptrollerImplementation;\\n}\\n\\ncontract ComptrollerV1Storage is UnitrollerAdminStorage {\\n\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n PriceOracle public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives\\n */\\n uint public liquidationIncentiveMantissa;\\n\\n /**\\n * @notice Max number of assets a single account can participate in (borrow or use as collateral)\\n */\\n uint public maxAssets;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\\n */\\n mapping(address => CToken[]) public accountAssets;\\n\\n}\\n\\ncontract ComptrollerV2Storage is ComptrollerV1Storage {\\n struct Market {\\n /// @notice Whether or not this market is listed\\n bool isListed;\\n\\n /**\\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\\n * For instance, 0.9 to allow borrowing 90% of collateral value.\\n * Must be between 0 and 1, and stored as a mantissa.\\n */\\n uint collateralFactorMantissa;\\n\\n /// @notice Per-market mapping of \\\"accounts in this asset\\\"\\n mapping(address => bool) accountMembership;\\n\\n /// @notice Whether or not this market receives COMP\\n bool isComped;\\n }\\n\\n /**\\n * @notice Official mapping of cTokens -> Market metadata\\n * @dev Used e.g. to determine if a market is supported\\n */\\n mapping(address => Market) public markets;\\n\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n * Actions which allow users to remove their own assets cannot be paused.\\n * Liquidation / seizing / transfer can only be paused globally, not by market.\\n */\\n address public pauseGuardian;\\n bool public _mintGuardianPaused;\\n bool public _borrowGuardianPaused;\\n bool public transferGuardianPaused;\\n bool public seizeGuardianPaused;\\n mapping(address => bool) public mintGuardianPaused;\\n mapping(address => bool) public borrowGuardianPaused;\\n}\\n\\ncontract ComptrollerV3Storage is ComptrollerV2Storage {\\n struct CompMarketState {\\n /// @notice The market's last updated compBorrowIndex or compSupplyIndex\\n uint224 index;\\n\\n /// @notice The block number the index was last updated at\\n uint32 block;\\n }\\n\\n /// @notice A list of all markets\\n CToken[] public allMarkets;\\n\\n /// @notice The rate at which the flywheel distributes COMP, per block\\n uint public compRate;\\n\\n /// @notice The portion of compRate that each market currently receives\\n mapping(address => uint) public compSpeeds;\\n\\n /// @notice The COMP market supply state for each market\\n mapping(address => CompMarketState) public compSupplyState;\\n\\n /// @notice The COMP market borrow state for each market\\n mapping(address => CompMarketState) public compBorrowState;\\n\\n /// @notice The COMP borrow index for each market for each supplier as of the last time they accrued COMP\\n mapping(address => mapping(address => uint)) public compSupplierIndex;\\n\\n /// @notice The COMP borrow index for each market for each borrower as of the last time they accrued COMP\\n mapping(address => mapping(address => uint)) public compBorrowerIndex;\\n\\n /// @notice The COMP accrued but not yet transferred to each user\\n mapping(address => uint) public compAccrued;\\n}\\n\\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\\n // @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\\n address public borrowCapGuardian;\\n\\n // @notice Borrow caps enforced by borrowAllowed for each cToken address. Defaults to zero which corresponds to unlimited borrowing.\\n mapping(address => uint) public borrowCaps;\\n}\\n\\ncontract ComptrollerV5Storage is ComptrollerV4Storage {\\n /// @notice The portion of COMP that each contributor receives per block\\n mapping(address => uint) public compContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's COMP rewards have been allocated\\n mapping(address => uint) public lastContributorBlock;\\n}\\n\",\"keccak256\":\"0x5db970485549f493618b5e36bfd4d799d4f8701a136bf71ed6e0117e1ed8c254\"},\"contracts/EIP20Interface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title ERC 20 Token Standard Interface\\n * https://eips.ethereum.org/EIPS/eip-20\\n */\\ninterface EIP20Interface {\\n function name() external view returns (string memory);\\n function symbol() external view returns (string memory);\\n function decimals() external view returns (uint8);\\n\\n /**\\n * @notice Get the total number of tokens in circulation\\n * @return The supply of tokens\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @notice Gets the balance of the specified address\\n * @param owner The address from which the balance will be retrieved\\n * @return The balance\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transfer(address dst, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferFrom(address src, address dst, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (-1 means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (-1 means infinite)\\n */\\n function allowance(address owner, address spender) external view returns (uint256 remaining);\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n}\\n\",\"keccak256\":\"0xfd8ed2eac6d0b4d9ee6b32628ba68bae17544b66f190a5f7ce0c6ad024579dc8\"},\"contracts/EIP20NonStandardInterface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title EIP20NonStandardInterface\\n * @dev Version of ERC20 with no return values for `transfer` and `transferFrom`\\n * See https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\\n */\\ninterface EIP20NonStandardInterface {\\n\\n /**\\n * @notice Get the total number of tokens in circulation\\n * @return The supply of tokens\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @notice Gets the balance of the specified address\\n * @param owner The address from which the balance will be retrieved\\n * @return The balance\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n ///\\n /// !!!!!!!!!!!!!!\\n /// !!! NOTICE !!! `transfer` does not return a value, in violation of the ERC-20 specification\\n /// !!!!!!!!!!!!!!\\n ///\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n */\\n function transfer(address dst, uint256 amount) external;\\n\\n ///\\n /// !!!!!!!!!!!!!!\\n /// !!! NOTICE !!! `transferFrom` does not return a value, in violation of the ERC-20 specification\\n /// !!!!!!!!!!!!!!\\n ///\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n */\\n function transferFrom(address src, address dst, uint256 amount) external;\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent\\n */\\n function allowance(address owner, address spender) external view returns (uint256 remaining);\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n}\\n\",\"keccak256\":\"0x9719f12e4b80b51147ac195553a198cf8b0c516e7e4d04fc324a23ed15cbafb2\"},\"contracts/ErrorReporter.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\ncontract ComptrollerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\",\"keccak256\":\"0x5179afb1071c0fd555e5c1f1d2565f72dbe1740cc3dd02f6e52037f150afc5c9\"},\"contracts/Exponential.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CarefulMath.sol\\\";\\nimport \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @dev Legacy contract for compatibility reasons with existing contracts that still use MathError\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: rational}));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({mantissa: result}));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({mantissa: result}));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: scaledMantissa}));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: descaledMantissa}));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) pure internal returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({mantissa: 0}));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({mantissa: product}));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) pure internal returns (MathError, Exp memory) {\\n return mulExp(Exp({mantissa: a}), Exp({mantissa: b}));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) pure internal returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6ff054d65a0289dbb43c9f437d6909f9cf1207c9b8f984b3cb8e97a9de76a434\"},\"contracts/ExponentialNoError.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\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 Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) pure internal returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) pure internal returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) pure internal returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) pure internal returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) pure internal returns (uint224) {\\n require(n < 2**224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) pure internal returns (uint32) {\\n require(n < 2**32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: add_(a.mantissa, b.mantissa)});\\n }\\n\\n function add_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: add_(a.mantissa, b.mantissa)});\\n }\\n\\n function add_(uint a, uint b) pure internal returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: sub_(a.mantissa, b.mantissa)});\\n }\\n\\n function sub_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: sub_(a.mantissa, b.mantissa)});\\n }\\n\\n function sub_(uint a, uint b) pure internal returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: mul_(a.mantissa, b.mantissa) / expScale});\\n }\\n\\n function mul_(Exp memory a, uint b) pure internal returns (Exp memory) {\\n return Exp({mantissa: mul_(a.mantissa, b)});\\n }\\n\\n function mul_(uint a, Exp memory b) pure internal returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: mul_(a.mantissa, b.mantissa) / doubleScale});\\n }\\n\\n function mul_(Double memory a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: mul_(a.mantissa, b)});\\n }\\n\\n function mul_(uint a, Double memory b) pure internal returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) pure internal returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) pure internal 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) pure internal returns (Exp memory) {\\n return Exp({mantissa: div_(mul_(a.mantissa, expScale), b.mantissa)});\\n }\\n\\n function div_(Exp memory a, uint b) pure internal returns (Exp memory) {\\n return Exp({mantissa: div_(a.mantissa, b)});\\n }\\n\\n function div_(uint a, Exp memory b) pure internal returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa)});\\n }\\n\\n function div_(Double memory a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(a.mantissa, b)});\\n }\\n\\n function div_(uint a, Double memory b) pure internal returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) pure internal returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(mul_(a, doubleScale), b)});\\n }\\n}\\n\",\"keccak256\":\"0x7cb184b7cee71a5e707053dfba7eebbd46f11974004028100510ccce19b6694d\"},\"contracts/Governance/Comp.sol\":{\"content\":\"pragma solidity ^0.5.16;\\npragma experimental ABIEncoderV2;\\n\\ncontract Comp {\\n /// @notice EIP-20 token name for this token\\n string public constant name = \\\"Compound\\\";\\n\\n /// @notice EIP-20 token symbol for this token\\n string public constant symbol = \\\"COMP\\\";\\n\\n /// @notice EIP-20 token decimals for this token\\n uint8 public constant decimals = 18;\\n\\n /// @notice Total number of tokens in circulation\\n uint public constant totalSupply = 10000000e18; // 10 million Comp\\n\\n /// @notice Allowance amounts on behalf of others\\n mapping (address => mapping (address => uint96)) internal allowances;\\n\\n /// @notice Official record of token balances for each account\\n mapping (address => uint96) internal balances;\\n\\n /// @notice A record of each accounts delegate\\n mapping (address => address) public delegates;\\n\\n /// @notice A checkpoint for marking number of votes from a given block\\n struct Checkpoint {\\n uint32 fromBlock;\\n uint96 votes;\\n }\\n\\n /// @notice A record of votes checkpoints for each account, by index\\n mapping (address => mapping (uint32 => Checkpoint)) public checkpoints;\\n\\n /// @notice The number of checkpoints for each account\\n mapping (address => uint32) public numCheckpoints;\\n\\n /// @notice The EIP-712 typehash for the contract's domain\\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\\\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\\\");\\n\\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\\\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\\\");\\n\\n /// @notice A record of states for signing / validating signatures\\n mapping (address => uint) public nonces;\\n\\n /// @notice An event thats emitted when an account changes its delegate\\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\\n\\n /// @notice An event thats emitted when a delegate account's vote balance changes\\n event DelegateVotesChanged(address indexed delegate, uint previousBalance, uint newBalance);\\n\\n /// @notice The standard EIP-20 transfer event\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n\\n /// @notice The standard EIP-20 approval event\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n\\n /**\\n * @notice Construct a new Comp token\\n * @param account The initial account to grant all the tokens\\n */\\n constructor(address account) public {\\n balances[account] = uint96(totalSupply);\\n emit Transfer(address(0), account, totalSupply);\\n }\\n\\n /**\\n * @notice Get the number of tokens `spender` is approved to spend on behalf of `account`\\n * @param account The address of the account holding the funds\\n * @param spender The address of the account spending the funds\\n * @return The number of tokens approved\\n */\\n function allowance(address account, address spender) external view returns (uint) {\\n return allowances[account][spender];\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param rawAmount The number of tokens that are approved (2^256-1 means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint rawAmount) external returns (bool) {\\n uint96 amount;\\n if (rawAmount == uint(-1)) {\\n amount = uint96(-1);\\n } else {\\n amount = safe96(rawAmount, \\\"Comp::approve: amount exceeds 96 bits\\\");\\n }\\n\\n allowances[msg.sender][spender] = amount;\\n\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the number of tokens held by the `account`\\n * @param account The address of the account to get the balance of\\n * @return The number of tokens held\\n */\\n function balanceOf(address account) external view returns (uint) {\\n return balances[account];\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param rawAmount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transfer(address dst, uint rawAmount) external returns (bool) {\\n uint96 amount = safe96(rawAmount, \\\"Comp::transfer: amount exceeds 96 bits\\\");\\n _transferTokens(msg.sender, dst, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param rawAmount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferFrom(address src, address dst, uint rawAmount) external returns (bool) {\\n address spender = msg.sender;\\n uint96 spenderAllowance = allowances[src][spender];\\n uint96 amount = safe96(rawAmount, \\\"Comp::approve: amount exceeds 96 bits\\\");\\n\\n if (spender != src && spenderAllowance != uint96(-1)) {\\n uint96 newAllowance = sub96(spenderAllowance, amount, \\\"Comp::transferFrom: transfer amount exceeds spender allowance\\\");\\n allowances[src][spender] = newAllowance;\\n\\n emit Approval(src, spender, newAllowance);\\n }\\n\\n _transferTokens(src, dst, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Delegate votes from `msg.sender` to `delegatee`\\n * @param delegatee The address to delegate votes to\\n */\\n function delegate(address delegatee) public {\\n return _delegate(msg.sender, delegatee);\\n }\\n\\n /**\\n * @notice Delegates votes from signatory to `delegatee`\\n * @param delegatee The address to delegate votes to\\n * @param nonce The contract state required to match the signature\\n * @param expiry The time at which to expire the signature\\n * @param v The recovery byte of the signature\\n * @param r Half of the ECDSA signature pair\\n * @param s Half of the ECDSA signature pair\\n */\\n function delegateBySig(address delegatee, uint nonce, uint expiry, uint8 v, bytes32 r, bytes32 s) public {\\n bytes32 domainSeparator = keccak256(abi.encode(DOMAIN_TYPEHASH, keccak256(bytes(name)), getChainId(), address(this)));\\n bytes32 structHash = keccak256(abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry));\\n bytes32 digest = keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash));\\n address signatory = ecrecover(digest, v, r, s);\\n require(signatory != address(0), \\\"Comp::delegateBySig: invalid signature\\\");\\n require(nonce == nonces[signatory]++, \\\"Comp::delegateBySig: invalid nonce\\\");\\n require(now <= expiry, \\\"Comp::delegateBySig: signature expired\\\");\\n return _delegate(signatory, delegatee);\\n }\\n\\n /**\\n * @notice Gets the current votes balance for `account`\\n * @param account The address to get votes balance\\n * @return The number of current votes for `account`\\n */\\n function getCurrentVotes(address account) external view returns (uint96) {\\n uint32 nCheckpoints = numCheckpoints[account];\\n return nCheckpoints > 0 ? checkpoints[account][nCheckpoints - 1].votes : 0;\\n }\\n\\n /**\\n * @notice Determine the prior number of votes for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param account The address of the account to check\\n * @param blockNumber The block number to get the vote balance at\\n * @return The number of votes the account had as of the given block\\n */\\n function getPriorVotes(address account, uint blockNumber) public view returns (uint96) {\\n require(blockNumber < block.number, \\\"Comp::getPriorVotes: not yet determined\\\");\\n\\n uint32 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (checkpoints[account][nCheckpoints - 1].fromBlock <= blockNumber) {\\n return checkpoints[account][nCheckpoints - 1].votes;\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[account][0].fromBlock > blockNumber) {\\n return 0;\\n }\\n\\n uint32 lower = 0;\\n uint32 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[account][center];\\n if (cp.fromBlock == blockNumber) {\\n return cp.votes;\\n } else if (cp.fromBlock < blockNumber) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return checkpoints[account][lower].votes;\\n }\\n\\n function _delegate(address delegator, address delegatee) internal {\\n address currentDelegate = delegates[delegator];\\n uint96 delegatorBalance = balances[delegator];\\n delegates[delegator] = delegatee;\\n\\n emit DelegateChanged(delegator, currentDelegate, delegatee);\\n\\n _moveDelegates(currentDelegate, delegatee, delegatorBalance);\\n }\\n\\n function _transferTokens(address src, address dst, uint96 amount) internal {\\n require(src != address(0), \\\"Comp::_transferTokens: cannot transfer from the zero address\\\");\\n require(dst != address(0), \\\"Comp::_transferTokens: cannot transfer to the zero address\\\");\\n\\n balances[src] = sub96(balances[src], amount, \\\"Comp::_transferTokens: transfer amount exceeds balance\\\");\\n balances[dst] = add96(balances[dst], amount, \\\"Comp::_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 && amount > 0) {\\n if (srcRep != address(0)) {\\n uint32 srcRepNum = numCheckpoints[srcRep];\\n uint96 srcRepOld = srcRepNum > 0 ? checkpoints[srcRep][srcRepNum - 1].votes : 0;\\n uint96 srcRepNew = sub96(srcRepOld, amount, \\\"Comp::_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 > 0 ? checkpoints[dstRep][dstRepNum - 1].votes : 0;\\n uint96 dstRepNew = add96(dstRepOld, amount, \\\"Comp::_moveVotes: vote amount overflows\\\");\\n _writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew);\\n }\\n }\\n }\\n\\n function _writeCheckpoint(address delegatee, uint32 nCheckpoints, uint96 oldVotes, uint96 newVotes) internal {\\n uint32 blockNumber = safe32(block.number, \\\"Comp::_writeCheckpoint: block number exceeds 32 bits\\\");\\n\\n if (nCheckpoints > 0 && checkpoints[delegatee][nCheckpoints - 1].fromBlock == blockNumber) {\\n checkpoints[delegatee][nCheckpoints - 1].votes = newVotes;\\n } else {\\n checkpoints[delegatee][nCheckpoints] = Checkpoint(blockNumber, newVotes);\\n numCheckpoints[delegatee] = nCheckpoints + 1;\\n }\\n\\n emit DelegateVotesChanged(delegatee, oldVotes, newVotes);\\n }\\n\\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\\n require(n < 2**32, errorMessage);\\n return uint32(n);\\n }\\n\\n function safe96(uint n, string memory errorMessage) internal pure returns (uint96) {\\n require(n < 2**96, errorMessage);\\n return uint96(n);\\n }\\n\\n function add96(uint96 a, uint96 b, string memory errorMessage) internal pure returns (uint96) {\\n uint96 c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub96(uint96 a, uint96 b, string memory errorMessage) internal pure returns (uint96) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function getChainId() internal pure returns (uint) {\\n uint256 chainId;\\n assembly { chainId := chainid() }\\n return chainId;\\n }\\n}\\n\",\"keccak256\":\"0x539f7158013dd91efd3ad42dc6a56e0f7aebdca06063d40ce7b6e9a981b726a3\"},\"contracts/InterestRateModel.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Compound's InterestRateModel Interface\\n * @author Compound\\n */\\ncontract InterestRateModel {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint cash, uint borrows, uint reserves) external view returns (uint);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) external view returns (uint);\\n\\n}\\n\",\"keccak256\":\"0x929282d73c79e6d700ebe79f9fafc1e414b3848acff5a56d6740afd1dc908678\"},\"contracts/PriceOracle.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.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 cToken asset\\n * @param cToken The cToken to get the underlying price of\\n * @return The underlying asset price mantissa (scaled by 1e18).\\n * Zero means the price is unavailable.\\n */\\n function getUnderlyingPrice(CToken cToken) external view returns (uint);\\n}\\n\",\"keccak256\":\"0xe79ebc23bba508eb2479e7b3340abf566da1ab62131f106aee1aac3dc53816ef\"},\"contracts/Unitroller.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ErrorReporter.sol\\\";\\nimport \\\"./ComptrollerStorage.sol\\\";\\n/**\\n * @title ComptrollerCore\\n * @dev Storage for the comptroller is at this address, while execution is delegated to the `comptrollerImplementation`.\\n * CTokens should reference this contract as their comptroller.\\n */\\ncontract Unitroller is UnitrollerAdminStorage, ComptrollerErrorReporter {\\n\\n /**\\n * @notice Emitted when pendingComptrollerImplementation is changed\\n */\\n event NewPendingImplementation(address oldPendingImplementation, address newPendingImplementation);\\n\\n /**\\n * @notice Emitted when pendingComptrollerImplementation is accepted, which means comptroller implementation is updated\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Emitted when pendingAdmin is accepted, which means admin is updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n constructor() public {\\n // Set admin to caller\\n admin = msg.sender;\\n }\\n\\n /*** Admin Functions ***/\\n function _setPendingImplementation(address newPendingImplementation) public returns (uint) {\\n\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_IMPLEMENTATION_OWNER_CHECK);\\n }\\n\\n address oldPendingImplementation = pendingComptrollerImplementation;\\n\\n pendingComptrollerImplementation = newPendingImplementation;\\n\\n emit NewPendingImplementation(oldPendingImplementation, pendingComptrollerImplementation);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts new implementation of comptroller. msg.sender must be pendingImplementation\\n * @dev Admin function for new implementation to accept it's role as implementation\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptImplementation() public returns (uint) {\\n // Check caller is pendingImplementation and pendingImplementation \\u2260 address(0)\\n if (msg.sender != pendingComptrollerImplementation || pendingComptrollerImplementation == address(0)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldImplementation = comptrollerImplementation;\\n address oldPendingImplementation = pendingComptrollerImplementation;\\n\\n comptrollerImplementation = pendingComptrollerImplementation;\\n\\n pendingComptrollerImplementation = address(0);\\n\\n emit NewImplementation(oldImplementation, comptrollerImplementation);\\n emit NewPendingImplementation(oldPendingImplementation, pendingComptrollerImplementation);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPendingAdmin(address newPendingAdmin) public returns (uint) {\\n // Check caller = admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\\n }\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptAdmin() public returns (uint) {\\n // Check caller is pendingAdmin and pendingAdmin \\u2260 address(0)\\n if (msg.sender != pendingAdmin || msg.sender == address(0)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = address(0);\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return 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 () payable external {\\n // delegate all other functions to current implementation\\n (bool success, ) = comptrollerImplementation.delegatecall(msg.data);\\n\\n assembly {\\n let free_mem_ptr := mload(0x40)\\n returndatacopy(free_mem_ptr, 0, returndatasize)\\n\\n switch success\\n case 0 { revert(free_mem_ptr, returndatasize) }\\n default { return(free_mem_ptr, returndatasize) }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x51f81451eab9d5c4849507e724f2b2c53e41f54e5359fdbeae89432a727c16df\"}},\"version\":1}" + }, + "contracts/ComptrollerStorage.sol:ComptrollerV1Storage": { + "abi": "[{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"liquidationIncentiveMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}]", + "bin": "608060405234801561001057600080fd5b506101f9806100206000396000f3fe608060405234801561001057600080fd5b50600436106100935760003560e01c8063bb82aa5e11610066578063bb82aa5e146100e6578063dce15449146100ee578063dcfbc0c71461011a578063e875544614610122578063f851a4401461012a57610093565b806326782247146100985780634ada90af146100bc5780637dc0d1d0146100d657806394b2294b146100de575b600080fd5b6100a0610132565b604080516001600160a01b039092168252519081900360200190f35b6100c4610141565b60408051918252519081900360200190f35b6100a0610147565b6100c4610156565b6100a061015c565b6100a06004803603604081101561010457600080fd5b506001600160a01b03813516906020013561016b565b6100a06101a0565b6100c46101af565b6100a06101b5565b6001546001600160a01b031681565b60065481565b6004546001600160a01b031681565b60075481565b6002546001600160a01b031681565b6008602052816000526040600020818154811061018457fe5b6000918252602090912001546001600160a01b03169150829050565b6003546001600160a01b031681565b60055481565b6000546001600160a01b03168156fea265627a7a72315820616f4badeb3c514a4ccbbfbb7e9d0daf46fe191b523ae851604b1f16704972a264736f6c63430005100032", + "metadata": "{\"compiler\":{\"version\":\"0.5.16+commit.9c3226ce\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"liquidationIncentiveMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"methods\":{}},\"userdoc\":{\"methods\":{}}},\"settings\":{\"compilationTarget\":{\"contracts/ComptrollerStorage.sol\":\"ComptrollerV1Storage\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/CToken.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./CTokenInterfaces.sol\\\";\\nimport \\\"./ErrorReporter.sol\\\";\\nimport \\\"./Exponential.sol\\\";\\nimport \\\"./EIP20Interface.sol\\\";\\nimport \\\"./InterestRateModel.sol\\\";\\n\\n/**\\n * @title Compound's CToken Contract\\n * @notice Abstract base for CTokens\\n * @author Compound\\n */\\ncontract CToken is CTokenInterface, Exponential, TokenErrorReporter {\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_) public {\\n require(msg.sender == admin, \\\"only admin may initialize the market\\\");\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = getBlockNumber();\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Transfer `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = uint(-1);\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srcTokensNew;\\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, srcTokensNew) = 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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srcTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != uint(-1)) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n // unused function\\n // comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transfer(address dst, uint256 amount) external nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferFrom(address src, address dst, uint256 amount) external nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (-1 means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool) {\\n address src = msg.sender;\\n transferAllowances[src][spender] = amount;\\n emit Approval(src, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (-1 means infinite)\\n */\\n function allowance(address owner, address spender) external view returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external returns (uint) {\\n Exp memory exchangeRate = Exp({mantissa: exchangeRateCurrent()});\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n require(mErr == MathError.NO_ERROR, \\\"balance could not be calculated\\\");\\n return balance;\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view returns (uint, uint, uint, uint) {\\n uint cTokenBalance = accountTokens[account];\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), cTokenBalance, borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @dev Function to simply retrieve block number\\n * This exists mainly for inheriting test contracts to stub this result.\\n */\\n function getBlockNumber() internal view returns (uint) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this cToken\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view returns (uint) {\\n return interestRateModel.getBorrowRate(getCashPrior(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this cToken\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view returns (uint) {\\n return interestRateModel.getSupplyRate(getCashPrior(), totalBorrows, totalReserves, reserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n require(err == MathError.NO_ERROR, \\\"borrowBalanceStored: borrowBalanceStoredInternal failed\\\");\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return (error code, the calculated balance or 0 if error code is non-zero)\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the CToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n require(err == MathError.NO_ERROR, \\\"exchangeRateStored: exchangeRateStoredInternal failed\\\");\\n return result;\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the CToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return (error code, calculated exchange rate scaled by 1e18)\\n */\\n function exchangeRateStoredInternal() internal view returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows - totalReserves) / totalSupply\\n */\\n uint totalCash = getCashPrior();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Get cash balance of this cToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage.\\n */\\n function accrueInterest() public returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = getBlockNumber();\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = getCashPrior();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n require(mathErr == MathError.NO_ERROR, \\\"could not calculate block delta\\\");\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({mantissa: borrowRateMantissa}), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(Exp({mantissa: reserveFactorMantissa}), interestAccumulated, reservesPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives cTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n struct MintLocalVars {\\n Error err;\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives cTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, 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's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the cToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of cTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.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 cTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED\\\");\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\\");\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender redeems cTokens in exchange for the underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemTokens The number of cTokens to redeem into underlying\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemInternal(uint redeemTokens) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(msg.sender, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems cTokens in exchange for a specified amount of underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemAmount The amount of underlying to receive from redeeming cTokens\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemUnderlyingInternal(uint redeemAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(msg.sender, 0, redeemAmount);\\n }\\n\\n struct RedeemLocalVars {\\n Error err;\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n /**\\n * @notice User redeems cTokens in exchange for the underlying asset\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param redeemTokensIn The number of cTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming cTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemFresh(address payable redeemer, uint redeemTokensIn, uint redeemAmountIn) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr));\\n }\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(Exp({mantissa: vars.exchangeRateMantissa}), redeemTokensIn);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(redeemAmountIn, Exp({mantissa: vars.exchangeRateMantissa}));\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REDEEM_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDEEM_FRESHNESS_CHECK);\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDEEM_TRANSFER_OUT_NOT_POSSIBLE);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We invoke doTransferOut for the redeemer and the redeemAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(redeemer, vars.redeemAmount);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n /* We call the defense hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender borrows assets from the protocol to their own address\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function borrowInternal(uint borrowAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(msg.sender, borrowAmount);\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n /**\\n * @notice Users borrow assets from the protocol to their own address\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function borrowFresh(address payable borrower, uint borrowAmount) internal returns (uint) {\\n /* Fail if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.BORROW_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.BORROW_FRESHNESS_CHECK);\\n }\\n\\n /* Fail gracefully if protocol has insufficient underlying cash */\\n if (getCashPrior() < borrowAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.BORROW_CASH_NOT_AVAILABLE);\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We invoke doTransferOut for the borrower and the borrowAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(borrower, borrowAmount);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to borrower\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer the account paying off the borrow\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount the amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED\\\");\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED\\\");\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this cToken to be liquidated\\n * @param cTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) 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 = cTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, cTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this cToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param cTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowFresh(address liquidator, address borrower, uint repayAmount, CTokenInterface cTokenCollateral) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(address(this), address(cTokenCollateral), liquidator, borrower, repayAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify cTokenCollateral market's block number equals current block number */\\n if (cTokenCollateral.accrualBlockNumber() != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = -1 */\\n if (repayAmount == uint(-1)) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & 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(cTokenCollateral), actualRepayAmount);\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(cTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(cTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = cTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(cTokenCollateral), seizeTokens);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.liquidateBorrowVerify(address(this), address(cTokenCollateral), liquidator, borrower, actualRepayAmount, seizeTokens);\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another cToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed cToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of cTokens to seize\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function seize(address liquidator, address borrower, uint seizeTokens) external nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n struct SeizeInternalLocalVars {\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n uint liquidatorSeizeTokens;\\n uint protocolSeizeTokens;\\n uint protocolSeizeAmount;\\n uint exchangeRateMantissa;\\n uint totalReservesNew;\\n uint totalSupplyNew;\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another CToken.\\n * Its absolutely critical to use msg.sender as the seizer cToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed cToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of cTokens to seize\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function seizeInternal(address seizerToken, address liquidator, address borrower, uint seizeTokens) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n SeizeInternalLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (vars.mathErr, vars.borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(vars.mathErr));\\n }\\n\\n vars.protocolSeizeTokens = mul_(seizeTokens, Exp({mantissa: protocolSeizeShareMantissa}));\\n vars.liquidatorSeizeTokens = sub_(seizeTokens, vars.protocolSeizeTokens);\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n require(vars.mathErr == MathError.NO_ERROR, \\\"exchange rate math error\\\");\\n\\n vars.protocolSeizeAmount = mul_ScalarTruncate(Exp({mantissa: vars.exchangeRateMantissa}), vars.protocolSeizeTokens);\\n\\n vars.totalReservesNew = add_(totalReserves, vars.protocolSeizeAmount);\\n vars.totalSupplyNew = sub_(totalSupply, vars.protocolSeizeTokens);\\n\\n (vars.mathErr, vars.liquidatorTokensNew) = addUInt(accountTokens[liquidator], vars.liquidatorSeizeTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(vars.mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n totalReserves = vars.totalReservesNew;\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[borrower] = vars.borrowerTokensNew;\\n accountTokens[liquidator] = vars.liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, vars.liquidatorSeizeTokens);\\n emit Transfer(borrower, address(this), vars.protocolSeizeTokens);\\n emit ReservesAdded(address(this), vars.protocolSeizeAmount, vars.totalReservesNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n\\n /*** Admin Functions ***/\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPendingAdmin(address payable newPendingAdmin) external returns (uint) {\\n // Check caller = admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\\n }\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptAdmin() external returns (uint) {\\n // Check caller is pendingAdmin and pendingAdmin \\u2260 address(0)\\n if (msg.sender != pendingAdmin || msg.sender == address(0)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = address(0);\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setComptroller(ComptrollerInterface newComptroller) public returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_COMPTROLLER_OWNER_CHECK);\\n }\\n\\n ComptrollerInterface oldComptroller = comptroller;\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(oldComptroller, newComptroller);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh\\n * @dev Admin function to accrue interest and set a new reserve factor\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setReserveFactor(uint newReserveFactorMantissa) external nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\\n * @dev Admin function to set a new reserve factor\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_RESERVE_FACTOR_ADMIN_CHECK);\\n }\\n\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring from msg.sender\\n * @param addAmount Amount of addition to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to admin\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _reduceReserves(uint reduceAmount) external nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to admin\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _reduceReservesFresh(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's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n totalReservesNew = totalReserves - reduceAmount;\\n // We checked reduceAmount <= totalReserves above, so this should never revert.\\n require(totalReservesNew <= 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't be sure if side effects occurred.\\n doTransferOut(admin, reduceAmount);\\n\\n emit ReservesReduced(admin, reduceAmount, totalReservesNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Admin function to accrue interest and update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel);\\n }\\n\\n /**\\n * @notice updates the interest rate model (*requires fresh interest accrual)\\n * @dev Admin function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal returns (uint) {\\n\\n // Used to store old model for use in the event that is emitted on success\\n InterestRateModel oldInterestRateModel;\\n\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_INTEREST_RATE_MODEL_OWNER_CHECK);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Track the market's current interest rate model\\n oldInterestRateModel = interestRateModel;\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view returns (uint);\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure tather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal;\\n\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n}\\n\",\"keccak256\":\"0x436ec2e309682995f8a82dfdd9e8f75928599c10a9a680dddbee6c275014008d\"},\"contracts/CTokenInterfaces.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./InterestRateModel.sol\\\";\\nimport \\\"./EIP20NonStandardInterface.sol\\\";\\n\\ncontract CTokenStorage {\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-cToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModel public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first CTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping (address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping (address => mapping (address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Share of seized collateral that is added to reserves\\n */\\n uint public constant protocolSeizeShareMantissa = 2.8e16; //2.8%\\n\\n}\\n\\ncontract CTokenInterface is CTokenStorage {\\n /**\\n * @notice Indicator that this is a CToken contract (for inspection)\\n */\\n bool public constant isCToken = true;\\n\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(address liquidator, address borrower, uint repayAmount, address cTokenCollateral, uint seizeTokens);\\n\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin is updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(InterestRateModel oldInterestRateModel, InterestRateModel newInterestRateModel);\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address admin, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Failure event\\n */\\n event Failure(uint error, uint info, uint detail);\\n\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external returns (bool);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function approve(address spender, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function balanceOfUnderlying(address owner) external returns (uint);\\n function getAccountSnapshot(address account) external view returns (uint, uint, uint, uint);\\n function borrowRatePerBlock() external view returns (uint);\\n function supplyRatePerBlock() external view returns (uint);\\n function totalBorrowsCurrent() external returns (uint);\\n function borrowBalanceCurrent(address account) external returns (uint);\\n function borrowBalanceStored(address account) public view returns (uint);\\n function exchangeRateCurrent() public returns (uint);\\n function exchangeRateStored() public view returns (uint);\\n function getCash() external view returns (uint);\\n function accrueInterest() public returns (uint);\\n function seize(address liquidator, address borrower, uint seizeTokens) external returns (uint);\\n\\n\\n /*** Admin Functions ***/\\n\\n function _setPendingAdmin(address payable newPendingAdmin) external returns (uint);\\n function _acceptAdmin() external returns (uint);\\n function _setComptroller(ComptrollerInterface newComptroller) public returns (uint);\\n function _setReserveFactor(uint newReserveFactorMantissa) external returns (uint);\\n function _reduceReserves(uint reduceAmount) external returns (uint);\\n function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint);\\n}\\n\\ncontract CErc20Storage {\\n /**\\n * @notice Underlying asset for this CToken\\n */\\n address public underlying;\\n}\\n\\ncontract CErc20Interface is CErc20Storage {\\n\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n function redeem(uint redeemTokens) external returns (uint);\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n function borrow(uint borrowAmount) external returns (uint);\\n function repayBorrow(uint repayAmount) external returns (uint);\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n function liquidateBorrow(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) external returns (uint);\\n function sweepToken(EIP20NonStandardInterface token) external;\\n\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ncontract CDelegationStorage {\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n}\\n\\ncontract CDelegatorInterface is CDelegationStorage {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(address implementation_, bool allowResign, bytes memory becomeImplementationData) public;\\n}\\n\\ncontract CDelegateInterface is CDelegationStorage {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) public;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() public;\\n}\\n\",\"keccak256\":\"0x963bbf60b4c0b76900b3fcb2db8c8be634934b37b4113f1055e57a308197d21a\"},\"contracts/CarefulMath.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Careful Math\\n * @author Compound\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c = a * b;\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n return (MathError.NO_ERROR, a - b);\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c = a + b;\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\",\"keccak256\":\"0x0647348f27e41d22555d99eebd217dee02a4d737df6accd7cce5347a7487c7de\"},\"contracts/ComptrollerInterface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\ncontract ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n bool public constant isComptroller = true;\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata cTokens) external returns (uint[] memory);\\n function exitMarket(address cToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address cToken, address minter, uint mintAmount) external returns (uint);\\n function mintVerify(address cToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address cToken, address redeemer, uint redeemTokens) external returns (uint);\\n function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address cToken, address borrower, uint borrowAmount) external returns (uint);\\n function borrowVerify(address cToken, address borrower, uint borrowAmount) external;\\n\\n function repayBorrowAllowed(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount) external returns (uint);\\n function repayBorrowVerify(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex) external;\\n\\n function liquidateBorrowAllowed(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount) external returns (uint);\\n function liquidateBorrowVerify(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens) external;\\n\\n function seizeAllowed(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external returns (uint);\\n function seizeVerify(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external;\\n\\n function transferAllowed(address cToken, address src, address dst, uint transferTokens) external returns (uint);\\n function transferVerify(address cToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n uint repayAmount) external view returns (uint, uint);\\n}\\n\",\"keccak256\":\"0xede7670d2dd7b25d0187aecd2c28b7b5ca7d7c1bdac144fbedecf5d4bdd92a6b\"},\"contracts/ComptrollerStorage.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.sol\\\";\\nimport \\\"./PriceOracle.sol\\\";\\n\\ncontract UnitrollerAdminStorage {\\n /**\\n * @notice Administrator for this contract\\n */\\n address public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address public pendingAdmin;\\n\\n /**\\n * @notice Active brains of Unitroller\\n */\\n address public comptrollerImplementation;\\n\\n /**\\n * @notice Pending brains of Unitroller\\n */\\n address public pendingComptrollerImplementation;\\n}\\n\\ncontract ComptrollerV1Storage is UnitrollerAdminStorage {\\n\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n PriceOracle public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives\\n */\\n uint public liquidationIncentiveMantissa;\\n\\n /**\\n * @notice Max number of assets a single account can participate in (borrow or use as collateral)\\n */\\n uint public maxAssets;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\\n */\\n mapping(address => CToken[]) public accountAssets;\\n\\n}\\n\\ncontract ComptrollerV2Storage is ComptrollerV1Storage {\\n struct Market {\\n /// @notice Whether or not this market is listed\\n bool isListed;\\n\\n /**\\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\\n * For instance, 0.9 to allow borrowing 90% of collateral value.\\n * Must be between 0 and 1, and stored as a mantissa.\\n */\\n uint collateralFactorMantissa;\\n\\n /// @notice Per-market mapping of \\\"accounts in this asset\\\"\\n mapping(address => bool) accountMembership;\\n\\n /// @notice Whether or not this market receives COMP\\n bool isComped;\\n }\\n\\n /**\\n * @notice Official mapping of cTokens -> Market metadata\\n * @dev Used e.g. to determine if a market is supported\\n */\\n mapping(address => Market) public markets;\\n\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n * Actions which allow users to remove their own assets cannot be paused.\\n * Liquidation / seizing / transfer can only be paused globally, not by market.\\n */\\n address public pauseGuardian;\\n bool public _mintGuardianPaused;\\n bool public _borrowGuardianPaused;\\n bool public transferGuardianPaused;\\n bool public seizeGuardianPaused;\\n mapping(address => bool) public mintGuardianPaused;\\n mapping(address => bool) public borrowGuardianPaused;\\n}\\n\\ncontract ComptrollerV3Storage is ComptrollerV2Storage {\\n struct CompMarketState {\\n /// @notice The market's last updated compBorrowIndex or compSupplyIndex\\n uint224 index;\\n\\n /// @notice The block number the index was last updated at\\n uint32 block;\\n }\\n\\n /// @notice A list of all markets\\n CToken[] public allMarkets;\\n\\n /// @notice The rate at which the flywheel distributes COMP, per block\\n uint public compRate;\\n\\n /// @notice The portion of compRate that each market currently receives\\n mapping(address => uint) public compSpeeds;\\n\\n /// @notice The COMP market supply state for each market\\n mapping(address => CompMarketState) public compSupplyState;\\n\\n /// @notice The COMP market borrow state for each market\\n mapping(address => CompMarketState) public compBorrowState;\\n\\n /// @notice The COMP borrow index for each market for each supplier as of the last time they accrued COMP\\n mapping(address => mapping(address => uint)) public compSupplierIndex;\\n\\n /// @notice The COMP borrow index for each market for each borrower as of the last time they accrued COMP\\n mapping(address => mapping(address => uint)) public compBorrowerIndex;\\n\\n /// @notice The COMP accrued but not yet transferred to each user\\n mapping(address => uint) public compAccrued;\\n}\\n\\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\\n // @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\\n address public borrowCapGuardian;\\n\\n // @notice Borrow caps enforced by borrowAllowed for each cToken address. Defaults to zero which corresponds to unlimited borrowing.\\n mapping(address => uint) public borrowCaps;\\n}\\n\\ncontract ComptrollerV5Storage is ComptrollerV4Storage {\\n /// @notice The portion of COMP that each contributor receives per block\\n mapping(address => uint) public compContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's COMP rewards have been allocated\\n mapping(address => uint) public lastContributorBlock;\\n}\\n\",\"keccak256\":\"0x5db970485549f493618b5e36bfd4d799d4f8701a136bf71ed6e0117e1ed8c254\"},\"contracts/EIP20Interface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title ERC 20 Token Standard Interface\\n * https://eips.ethereum.org/EIPS/eip-20\\n */\\ninterface EIP20Interface {\\n function name() external view returns (string memory);\\n function symbol() external view returns (string memory);\\n function decimals() external view returns (uint8);\\n\\n /**\\n * @notice Get the total number of tokens in circulation\\n * @return The supply of tokens\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @notice Gets the balance of the specified address\\n * @param owner The address from which the balance will be retrieved\\n * @return The balance\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transfer(address dst, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferFrom(address src, address dst, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (-1 means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (-1 means infinite)\\n */\\n function allowance(address owner, address spender) external view returns (uint256 remaining);\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n}\\n\",\"keccak256\":\"0xfd8ed2eac6d0b4d9ee6b32628ba68bae17544b66f190a5f7ce0c6ad024579dc8\"},\"contracts/EIP20NonStandardInterface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title EIP20NonStandardInterface\\n * @dev Version of ERC20 with no return values for `transfer` and `transferFrom`\\n * See https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\\n */\\ninterface EIP20NonStandardInterface {\\n\\n /**\\n * @notice Get the total number of tokens in circulation\\n * @return The supply of tokens\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @notice Gets the balance of the specified address\\n * @param owner The address from which the balance will be retrieved\\n * @return The balance\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n ///\\n /// !!!!!!!!!!!!!!\\n /// !!! NOTICE !!! `transfer` does not return a value, in violation of the ERC-20 specification\\n /// !!!!!!!!!!!!!!\\n ///\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n */\\n function transfer(address dst, uint256 amount) external;\\n\\n ///\\n /// !!!!!!!!!!!!!!\\n /// !!! NOTICE !!! `transferFrom` does not return a value, in violation of the ERC-20 specification\\n /// !!!!!!!!!!!!!!\\n ///\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n */\\n function transferFrom(address src, address dst, uint256 amount) external;\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent\\n */\\n function allowance(address owner, address spender) external view returns (uint256 remaining);\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n}\\n\",\"keccak256\":\"0x9719f12e4b80b51147ac195553a198cf8b0c516e7e4d04fc324a23ed15cbafb2\"},\"contracts/ErrorReporter.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\ncontract ComptrollerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\",\"keccak256\":\"0x5179afb1071c0fd555e5c1f1d2565f72dbe1740cc3dd02f6e52037f150afc5c9\"},\"contracts/Exponential.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CarefulMath.sol\\\";\\nimport \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @dev Legacy contract for compatibility reasons with existing contracts that still use MathError\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: rational}));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({mantissa: result}));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({mantissa: result}));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: scaledMantissa}));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: descaledMantissa}));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) pure internal returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({mantissa: 0}));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({mantissa: product}));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) pure internal returns (MathError, Exp memory) {\\n return mulExp(Exp({mantissa: a}), Exp({mantissa: b}));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) pure internal returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6ff054d65a0289dbb43c9f437d6909f9cf1207c9b8f984b3cb8e97a9de76a434\"},\"contracts/ExponentialNoError.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\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 Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) pure internal returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) pure internal returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) pure internal returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) pure internal returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) pure internal returns (uint224) {\\n require(n < 2**224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) pure internal returns (uint32) {\\n require(n < 2**32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: add_(a.mantissa, b.mantissa)});\\n }\\n\\n function add_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: add_(a.mantissa, b.mantissa)});\\n }\\n\\n function add_(uint a, uint b) pure internal returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: sub_(a.mantissa, b.mantissa)});\\n }\\n\\n function sub_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: sub_(a.mantissa, b.mantissa)});\\n }\\n\\n function sub_(uint a, uint b) pure internal returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: mul_(a.mantissa, b.mantissa) / expScale});\\n }\\n\\n function mul_(Exp memory a, uint b) pure internal returns (Exp memory) {\\n return Exp({mantissa: mul_(a.mantissa, b)});\\n }\\n\\n function mul_(uint a, Exp memory b) pure internal returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: mul_(a.mantissa, b.mantissa) / doubleScale});\\n }\\n\\n function mul_(Double memory a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: mul_(a.mantissa, b)});\\n }\\n\\n function mul_(uint a, Double memory b) pure internal returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) pure internal returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) pure internal 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) pure internal returns (Exp memory) {\\n return Exp({mantissa: div_(mul_(a.mantissa, expScale), b.mantissa)});\\n }\\n\\n function div_(Exp memory a, uint b) pure internal returns (Exp memory) {\\n return Exp({mantissa: div_(a.mantissa, b)});\\n }\\n\\n function div_(uint a, Exp memory b) pure internal returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa)});\\n }\\n\\n function div_(Double memory a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(a.mantissa, b)});\\n }\\n\\n function div_(uint a, Double memory b) pure internal returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) pure internal returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(mul_(a, doubleScale), b)});\\n }\\n}\\n\",\"keccak256\":\"0x7cb184b7cee71a5e707053dfba7eebbd46f11974004028100510ccce19b6694d\"},\"contracts/InterestRateModel.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Compound's InterestRateModel Interface\\n * @author Compound\\n */\\ncontract InterestRateModel {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint cash, uint borrows, uint reserves) external view returns (uint);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) external view returns (uint);\\n\\n}\\n\",\"keccak256\":\"0x929282d73c79e6d700ebe79f9fafc1e414b3848acff5a56d6740afd1dc908678\"},\"contracts/PriceOracle.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.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 cToken asset\\n * @param cToken The cToken to get the underlying price of\\n * @return The underlying asset price mantissa (scaled by 1e18).\\n * Zero means the price is unavailable.\\n */\\n function getUnderlyingPrice(CToken cToken) external view returns (uint);\\n}\\n\",\"keccak256\":\"0xe79ebc23bba508eb2479e7b3340abf566da1ab62131f106aee1aac3dc53816ef\"}},\"version\":1}" + }, + "contracts/ComptrollerStorage.sol:ComptrollerV2Storage": { + "abi": "[{\"constant\":true,\"inputs\":[],\"name\":\"_borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"liquidationIncentiveMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"markets\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isComped\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"seizeGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"transferGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}]", + "bin": "608060405234801561001057600080fd5b506103e0806100206000396000f3fe608060405234801561001057600080fd5b506004361061010b5760003560e01c80638e8f294b116100a2578063dce1544911610071578063dce154491461022e578063dcfbc0c71461025a578063e6653f3d14610262578063e87554461461026a578063f851a440146102725761010b565b80638e8f294b146101ce57806394b2294b14610216578063ac0b0bb71461021e578063bb82aa5e146102265761010b565b80636d154ea5116100de5780636d154ea514610172578063731f0c2b146101985780637dc0d1d0146101be57806387f76303146101c65761010b565b806324a3d6221461011057806326782247146101345780633c94786f1461013c5780634ada90af14610158575b600080fd5b61011861027a565b604080516001600160a01b039092168252519081900360200190f35b610118610289565b610144610298565b604080519115158252519081900360200190f35b6101606102a8565b60408051918252519081900360200190f35b6101446004803603602081101561018857600080fd5b50356001600160a01b03166102ae565b610144600480360360208110156101ae57600080fd5b50356001600160a01b03166102c3565b6101186102d8565b6101446102e7565b6101f4600480360360208110156101e457600080fd5b50356001600160a01b03166102f7565b6040805193151584526020840192909252151582820152519081900360600190f35b61016061031d565b610144610323565b610118610333565b6101186004803603604081101561024457600080fd5b506001600160a01b038135169060200135610342565b610118610377565b610144610386565b610160610396565b61011861039c565b600a546001600160a01b031681565b6001546001600160a01b031681565b600a54600160a01b900460ff1681565b60065481565b600c6020526000908152604090205460ff1681565b600b6020526000908152604090205460ff1681565b6004546001600160a01b031681565b600a54600160b01b900460ff1681565b60096020526000908152604090208054600182015460039092015460ff91821692911683565b60075481565b600a54600160b81b900460ff1681565b6002546001600160a01b031681565b6008602052816000526040600020818154811061035b57fe5b6000918252602090912001546001600160a01b03169150829050565b6003546001600160a01b031681565b600a54600160a81b900460ff1681565b60055481565b6000546001600160a01b03168156fea265627a7a72315820e38b64c650d900844180d36272c9f9b0a833379ebcafbeaa9e56a219dbb50d2764736f6c63430005100032", + "metadata": "{\"compiler\":{\"version\":\"0.5.16+commit.9c3226ce\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"constant\":true,\"inputs\":[],\"name\":\"_borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"liquidationIncentiveMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"markets\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isComped\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"seizeGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"transferGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"methods\":{}},\"userdoc\":{\"methods\":{}}},\"settings\":{\"compilationTarget\":{\"contracts/ComptrollerStorage.sol\":\"ComptrollerV2Storage\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/CToken.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./CTokenInterfaces.sol\\\";\\nimport \\\"./ErrorReporter.sol\\\";\\nimport \\\"./Exponential.sol\\\";\\nimport \\\"./EIP20Interface.sol\\\";\\nimport \\\"./InterestRateModel.sol\\\";\\n\\n/**\\n * @title Compound's CToken Contract\\n * @notice Abstract base for CTokens\\n * @author Compound\\n */\\ncontract CToken is CTokenInterface, Exponential, TokenErrorReporter {\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_) public {\\n require(msg.sender == admin, \\\"only admin may initialize the market\\\");\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = getBlockNumber();\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Transfer `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = uint(-1);\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srcTokensNew;\\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, srcTokensNew) = 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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srcTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != uint(-1)) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n // unused function\\n // comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transfer(address dst, uint256 amount) external nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferFrom(address src, address dst, uint256 amount) external nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (-1 means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool) {\\n address src = msg.sender;\\n transferAllowances[src][spender] = amount;\\n emit Approval(src, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (-1 means infinite)\\n */\\n function allowance(address owner, address spender) external view returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external returns (uint) {\\n Exp memory exchangeRate = Exp({mantissa: exchangeRateCurrent()});\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n require(mErr == MathError.NO_ERROR, \\\"balance could not be calculated\\\");\\n return balance;\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view returns (uint, uint, uint, uint) {\\n uint cTokenBalance = accountTokens[account];\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), cTokenBalance, borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @dev Function to simply retrieve block number\\n * This exists mainly for inheriting test contracts to stub this result.\\n */\\n function getBlockNumber() internal view returns (uint) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this cToken\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view returns (uint) {\\n return interestRateModel.getBorrowRate(getCashPrior(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this cToken\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view returns (uint) {\\n return interestRateModel.getSupplyRate(getCashPrior(), totalBorrows, totalReserves, reserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n require(err == MathError.NO_ERROR, \\\"borrowBalanceStored: borrowBalanceStoredInternal failed\\\");\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return (error code, the calculated balance or 0 if error code is non-zero)\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the CToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n require(err == MathError.NO_ERROR, \\\"exchangeRateStored: exchangeRateStoredInternal failed\\\");\\n return result;\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the CToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return (error code, calculated exchange rate scaled by 1e18)\\n */\\n function exchangeRateStoredInternal() internal view returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows - totalReserves) / totalSupply\\n */\\n uint totalCash = getCashPrior();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Get cash balance of this cToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage.\\n */\\n function accrueInterest() public returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = getBlockNumber();\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = getCashPrior();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n require(mathErr == MathError.NO_ERROR, \\\"could not calculate block delta\\\");\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({mantissa: borrowRateMantissa}), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(Exp({mantissa: reserveFactorMantissa}), interestAccumulated, reservesPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives cTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n struct MintLocalVars {\\n Error err;\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives cTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, 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's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the cToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of cTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.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 cTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED\\\");\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\\");\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender redeems cTokens in exchange for the underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemTokens The number of cTokens to redeem into underlying\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemInternal(uint redeemTokens) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(msg.sender, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems cTokens in exchange for a specified amount of underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemAmount The amount of underlying to receive from redeeming cTokens\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemUnderlyingInternal(uint redeemAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(msg.sender, 0, redeemAmount);\\n }\\n\\n struct RedeemLocalVars {\\n Error err;\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n /**\\n * @notice User redeems cTokens in exchange for the underlying asset\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param redeemTokensIn The number of cTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming cTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemFresh(address payable redeemer, uint redeemTokensIn, uint redeemAmountIn) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr));\\n }\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(Exp({mantissa: vars.exchangeRateMantissa}), redeemTokensIn);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(redeemAmountIn, Exp({mantissa: vars.exchangeRateMantissa}));\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REDEEM_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDEEM_FRESHNESS_CHECK);\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDEEM_TRANSFER_OUT_NOT_POSSIBLE);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We invoke doTransferOut for the redeemer and the redeemAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(redeemer, vars.redeemAmount);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n /* We call the defense hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender borrows assets from the protocol to their own address\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function borrowInternal(uint borrowAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(msg.sender, borrowAmount);\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n /**\\n * @notice Users borrow assets from the protocol to their own address\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function borrowFresh(address payable borrower, uint borrowAmount) internal returns (uint) {\\n /* Fail if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.BORROW_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.BORROW_FRESHNESS_CHECK);\\n }\\n\\n /* Fail gracefully if protocol has insufficient underlying cash */\\n if (getCashPrior() < borrowAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.BORROW_CASH_NOT_AVAILABLE);\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We invoke doTransferOut for the borrower and the borrowAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(borrower, borrowAmount);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to borrower\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer the account paying off the borrow\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount the amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED\\\");\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED\\\");\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this cToken to be liquidated\\n * @param cTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) 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 = cTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, cTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this cToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param cTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowFresh(address liquidator, address borrower, uint repayAmount, CTokenInterface cTokenCollateral) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(address(this), address(cTokenCollateral), liquidator, borrower, repayAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify cTokenCollateral market's block number equals current block number */\\n if (cTokenCollateral.accrualBlockNumber() != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = -1 */\\n if (repayAmount == uint(-1)) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & 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(cTokenCollateral), actualRepayAmount);\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(cTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(cTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = cTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(cTokenCollateral), seizeTokens);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.liquidateBorrowVerify(address(this), address(cTokenCollateral), liquidator, borrower, actualRepayAmount, seizeTokens);\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another cToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed cToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of cTokens to seize\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function seize(address liquidator, address borrower, uint seizeTokens) external nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n struct SeizeInternalLocalVars {\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n uint liquidatorSeizeTokens;\\n uint protocolSeizeTokens;\\n uint protocolSeizeAmount;\\n uint exchangeRateMantissa;\\n uint totalReservesNew;\\n uint totalSupplyNew;\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another CToken.\\n * Its absolutely critical to use msg.sender as the seizer cToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed cToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of cTokens to seize\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function seizeInternal(address seizerToken, address liquidator, address borrower, uint seizeTokens) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n SeizeInternalLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (vars.mathErr, vars.borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(vars.mathErr));\\n }\\n\\n vars.protocolSeizeTokens = mul_(seizeTokens, Exp({mantissa: protocolSeizeShareMantissa}));\\n vars.liquidatorSeizeTokens = sub_(seizeTokens, vars.protocolSeizeTokens);\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n require(vars.mathErr == MathError.NO_ERROR, \\\"exchange rate math error\\\");\\n\\n vars.protocolSeizeAmount = mul_ScalarTruncate(Exp({mantissa: vars.exchangeRateMantissa}), vars.protocolSeizeTokens);\\n\\n vars.totalReservesNew = add_(totalReserves, vars.protocolSeizeAmount);\\n vars.totalSupplyNew = sub_(totalSupply, vars.protocolSeizeTokens);\\n\\n (vars.mathErr, vars.liquidatorTokensNew) = addUInt(accountTokens[liquidator], vars.liquidatorSeizeTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(vars.mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n totalReserves = vars.totalReservesNew;\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[borrower] = vars.borrowerTokensNew;\\n accountTokens[liquidator] = vars.liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, vars.liquidatorSeizeTokens);\\n emit Transfer(borrower, address(this), vars.protocolSeizeTokens);\\n emit ReservesAdded(address(this), vars.protocolSeizeAmount, vars.totalReservesNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n\\n /*** Admin Functions ***/\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPendingAdmin(address payable newPendingAdmin) external returns (uint) {\\n // Check caller = admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\\n }\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptAdmin() external returns (uint) {\\n // Check caller is pendingAdmin and pendingAdmin \\u2260 address(0)\\n if (msg.sender != pendingAdmin || msg.sender == address(0)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = address(0);\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setComptroller(ComptrollerInterface newComptroller) public returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_COMPTROLLER_OWNER_CHECK);\\n }\\n\\n ComptrollerInterface oldComptroller = comptroller;\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(oldComptroller, newComptroller);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh\\n * @dev Admin function to accrue interest and set a new reserve factor\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setReserveFactor(uint newReserveFactorMantissa) external nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\\n * @dev Admin function to set a new reserve factor\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_RESERVE_FACTOR_ADMIN_CHECK);\\n }\\n\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring from msg.sender\\n * @param addAmount Amount of addition to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to admin\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _reduceReserves(uint reduceAmount) external nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to admin\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _reduceReservesFresh(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's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n totalReservesNew = totalReserves - reduceAmount;\\n // We checked reduceAmount <= totalReserves above, so this should never revert.\\n require(totalReservesNew <= 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't be sure if side effects occurred.\\n doTransferOut(admin, reduceAmount);\\n\\n emit ReservesReduced(admin, reduceAmount, totalReservesNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Admin function to accrue interest and update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel);\\n }\\n\\n /**\\n * @notice updates the interest rate model (*requires fresh interest accrual)\\n * @dev Admin function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal returns (uint) {\\n\\n // Used to store old model for use in the event that is emitted on success\\n InterestRateModel oldInterestRateModel;\\n\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_INTEREST_RATE_MODEL_OWNER_CHECK);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Track the market's current interest rate model\\n oldInterestRateModel = interestRateModel;\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view returns (uint);\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure tather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal;\\n\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n}\\n\",\"keccak256\":\"0x436ec2e309682995f8a82dfdd9e8f75928599c10a9a680dddbee6c275014008d\"},\"contracts/CTokenInterfaces.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./InterestRateModel.sol\\\";\\nimport \\\"./EIP20NonStandardInterface.sol\\\";\\n\\ncontract CTokenStorage {\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-cToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModel public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first CTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping (address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping (address => mapping (address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Share of seized collateral that is added to reserves\\n */\\n uint public constant protocolSeizeShareMantissa = 2.8e16; //2.8%\\n\\n}\\n\\ncontract CTokenInterface is CTokenStorage {\\n /**\\n * @notice Indicator that this is a CToken contract (for inspection)\\n */\\n bool public constant isCToken = true;\\n\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(address liquidator, address borrower, uint repayAmount, address cTokenCollateral, uint seizeTokens);\\n\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin is updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(InterestRateModel oldInterestRateModel, InterestRateModel newInterestRateModel);\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address admin, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Failure event\\n */\\n event Failure(uint error, uint info, uint detail);\\n\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external returns (bool);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function approve(address spender, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function balanceOfUnderlying(address owner) external returns (uint);\\n function getAccountSnapshot(address account) external view returns (uint, uint, uint, uint);\\n function borrowRatePerBlock() external view returns (uint);\\n function supplyRatePerBlock() external view returns (uint);\\n function totalBorrowsCurrent() external returns (uint);\\n function borrowBalanceCurrent(address account) external returns (uint);\\n function borrowBalanceStored(address account) public view returns (uint);\\n function exchangeRateCurrent() public returns (uint);\\n function exchangeRateStored() public view returns (uint);\\n function getCash() external view returns (uint);\\n function accrueInterest() public returns (uint);\\n function seize(address liquidator, address borrower, uint seizeTokens) external returns (uint);\\n\\n\\n /*** Admin Functions ***/\\n\\n function _setPendingAdmin(address payable newPendingAdmin) external returns (uint);\\n function _acceptAdmin() external returns (uint);\\n function _setComptroller(ComptrollerInterface newComptroller) public returns (uint);\\n function _setReserveFactor(uint newReserveFactorMantissa) external returns (uint);\\n function _reduceReserves(uint reduceAmount) external returns (uint);\\n function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint);\\n}\\n\\ncontract CErc20Storage {\\n /**\\n * @notice Underlying asset for this CToken\\n */\\n address public underlying;\\n}\\n\\ncontract CErc20Interface is CErc20Storage {\\n\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n function redeem(uint redeemTokens) external returns (uint);\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n function borrow(uint borrowAmount) external returns (uint);\\n function repayBorrow(uint repayAmount) external returns (uint);\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n function liquidateBorrow(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) external returns (uint);\\n function sweepToken(EIP20NonStandardInterface token) external;\\n\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ncontract CDelegationStorage {\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n}\\n\\ncontract CDelegatorInterface is CDelegationStorage {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(address implementation_, bool allowResign, bytes memory becomeImplementationData) public;\\n}\\n\\ncontract CDelegateInterface is CDelegationStorage {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) public;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() public;\\n}\\n\",\"keccak256\":\"0x963bbf60b4c0b76900b3fcb2db8c8be634934b37b4113f1055e57a308197d21a\"},\"contracts/CarefulMath.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Careful Math\\n * @author Compound\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c = a * b;\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n return (MathError.NO_ERROR, a - b);\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c = a + b;\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\",\"keccak256\":\"0x0647348f27e41d22555d99eebd217dee02a4d737df6accd7cce5347a7487c7de\"},\"contracts/ComptrollerInterface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\ncontract ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n bool public constant isComptroller = true;\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata cTokens) external returns (uint[] memory);\\n function exitMarket(address cToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address cToken, address minter, uint mintAmount) external returns (uint);\\n function mintVerify(address cToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address cToken, address redeemer, uint redeemTokens) external returns (uint);\\n function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address cToken, address borrower, uint borrowAmount) external returns (uint);\\n function borrowVerify(address cToken, address borrower, uint borrowAmount) external;\\n\\n function repayBorrowAllowed(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount) external returns (uint);\\n function repayBorrowVerify(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex) external;\\n\\n function liquidateBorrowAllowed(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount) external returns (uint);\\n function liquidateBorrowVerify(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens) external;\\n\\n function seizeAllowed(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external returns (uint);\\n function seizeVerify(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external;\\n\\n function transferAllowed(address cToken, address src, address dst, uint transferTokens) external returns (uint);\\n function transferVerify(address cToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n uint repayAmount) external view returns (uint, uint);\\n}\\n\",\"keccak256\":\"0xede7670d2dd7b25d0187aecd2c28b7b5ca7d7c1bdac144fbedecf5d4bdd92a6b\"},\"contracts/ComptrollerStorage.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.sol\\\";\\nimport \\\"./PriceOracle.sol\\\";\\n\\ncontract UnitrollerAdminStorage {\\n /**\\n * @notice Administrator for this contract\\n */\\n address public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address public pendingAdmin;\\n\\n /**\\n * @notice Active brains of Unitroller\\n */\\n address public comptrollerImplementation;\\n\\n /**\\n * @notice Pending brains of Unitroller\\n */\\n address public pendingComptrollerImplementation;\\n}\\n\\ncontract ComptrollerV1Storage is UnitrollerAdminStorage {\\n\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n PriceOracle public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives\\n */\\n uint public liquidationIncentiveMantissa;\\n\\n /**\\n * @notice Max number of assets a single account can participate in (borrow or use as collateral)\\n */\\n uint public maxAssets;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\\n */\\n mapping(address => CToken[]) public accountAssets;\\n\\n}\\n\\ncontract ComptrollerV2Storage is ComptrollerV1Storage {\\n struct Market {\\n /// @notice Whether or not this market is listed\\n bool isListed;\\n\\n /**\\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\\n * For instance, 0.9 to allow borrowing 90% of collateral value.\\n * Must be between 0 and 1, and stored as a mantissa.\\n */\\n uint collateralFactorMantissa;\\n\\n /// @notice Per-market mapping of \\\"accounts in this asset\\\"\\n mapping(address => bool) accountMembership;\\n\\n /// @notice Whether or not this market receives COMP\\n bool isComped;\\n }\\n\\n /**\\n * @notice Official mapping of cTokens -> Market metadata\\n * @dev Used e.g. to determine if a market is supported\\n */\\n mapping(address => Market) public markets;\\n\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n * Actions which allow users to remove their own assets cannot be paused.\\n * Liquidation / seizing / transfer can only be paused globally, not by market.\\n */\\n address public pauseGuardian;\\n bool public _mintGuardianPaused;\\n bool public _borrowGuardianPaused;\\n bool public transferGuardianPaused;\\n bool public seizeGuardianPaused;\\n mapping(address => bool) public mintGuardianPaused;\\n mapping(address => bool) public borrowGuardianPaused;\\n}\\n\\ncontract ComptrollerV3Storage is ComptrollerV2Storage {\\n struct CompMarketState {\\n /// @notice The market's last updated compBorrowIndex or compSupplyIndex\\n uint224 index;\\n\\n /// @notice The block number the index was last updated at\\n uint32 block;\\n }\\n\\n /// @notice A list of all markets\\n CToken[] public allMarkets;\\n\\n /// @notice The rate at which the flywheel distributes COMP, per block\\n uint public compRate;\\n\\n /// @notice The portion of compRate that each market currently receives\\n mapping(address => uint) public compSpeeds;\\n\\n /// @notice The COMP market supply state for each market\\n mapping(address => CompMarketState) public compSupplyState;\\n\\n /// @notice The COMP market borrow state for each market\\n mapping(address => CompMarketState) public compBorrowState;\\n\\n /// @notice The COMP borrow index for each market for each supplier as of the last time they accrued COMP\\n mapping(address => mapping(address => uint)) public compSupplierIndex;\\n\\n /// @notice The COMP borrow index for each market for each borrower as of the last time they accrued COMP\\n mapping(address => mapping(address => uint)) public compBorrowerIndex;\\n\\n /// @notice The COMP accrued but not yet transferred to each user\\n mapping(address => uint) public compAccrued;\\n}\\n\\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\\n // @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\\n address public borrowCapGuardian;\\n\\n // @notice Borrow caps enforced by borrowAllowed for each cToken address. Defaults to zero which corresponds to unlimited borrowing.\\n mapping(address => uint) public borrowCaps;\\n}\\n\\ncontract ComptrollerV5Storage is ComptrollerV4Storage {\\n /// @notice The portion of COMP that each contributor receives per block\\n mapping(address => uint) public compContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's COMP rewards have been allocated\\n mapping(address => uint) public lastContributorBlock;\\n}\\n\",\"keccak256\":\"0x5db970485549f493618b5e36bfd4d799d4f8701a136bf71ed6e0117e1ed8c254\"},\"contracts/EIP20Interface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title ERC 20 Token Standard Interface\\n * https://eips.ethereum.org/EIPS/eip-20\\n */\\ninterface EIP20Interface {\\n function name() external view returns (string memory);\\n function symbol() external view returns (string memory);\\n function decimals() external view returns (uint8);\\n\\n /**\\n * @notice Get the total number of tokens in circulation\\n * @return The supply of tokens\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @notice Gets the balance of the specified address\\n * @param owner The address from which the balance will be retrieved\\n * @return The balance\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transfer(address dst, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferFrom(address src, address dst, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (-1 means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (-1 means infinite)\\n */\\n function allowance(address owner, address spender) external view returns (uint256 remaining);\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n}\\n\",\"keccak256\":\"0xfd8ed2eac6d0b4d9ee6b32628ba68bae17544b66f190a5f7ce0c6ad024579dc8\"},\"contracts/EIP20NonStandardInterface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title EIP20NonStandardInterface\\n * @dev Version of ERC20 with no return values for `transfer` and `transferFrom`\\n * See https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\\n */\\ninterface EIP20NonStandardInterface {\\n\\n /**\\n * @notice Get the total number of tokens in circulation\\n * @return The supply of tokens\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @notice Gets the balance of the specified address\\n * @param owner The address from which the balance will be retrieved\\n * @return The balance\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n ///\\n /// !!!!!!!!!!!!!!\\n /// !!! NOTICE !!! `transfer` does not return a value, in violation of the ERC-20 specification\\n /// !!!!!!!!!!!!!!\\n ///\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n */\\n function transfer(address dst, uint256 amount) external;\\n\\n ///\\n /// !!!!!!!!!!!!!!\\n /// !!! NOTICE !!! `transferFrom` does not return a value, in violation of the ERC-20 specification\\n /// !!!!!!!!!!!!!!\\n ///\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n */\\n function transferFrom(address src, address dst, uint256 amount) external;\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent\\n */\\n function allowance(address owner, address spender) external view returns (uint256 remaining);\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n}\\n\",\"keccak256\":\"0x9719f12e4b80b51147ac195553a198cf8b0c516e7e4d04fc324a23ed15cbafb2\"},\"contracts/ErrorReporter.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\ncontract ComptrollerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\",\"keccak256\":\"0x5179afb1071c0fd555e5c1f1d2565f72dbe1740cc3dd02f6e52037f150afc5c9\"},\"contracts/Exponential.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CarefulMath.sol\\\";\\nimport \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @dev Legacy contract for compatibility reasons with existing contracts that still use MathError\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: rational}));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({mantissa: result}));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({mantissa: result}));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: scaledMantissa}));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: descaledMantissa}));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) pure internal returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({mantissa: 0}));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({mantissa: product}));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) pure internal returns (MathError, Exp memory) {\\n return mulExp(Exp({mantissa: a}), Exp({mantissa: b}));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) pure internal returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6ff054d65a0289dbb43c9f437d6909f9cf1207c9b8f984b3cb8e97a9de76a434\"},\"contracts/ExponentialNoError.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\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 Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) pure internal returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) pure internal returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) pure internal returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) pure internal returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) pure internal returns (uint224) {\\n require(n < 2**224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) pure internal returns (uint32) {\\n require(n < 2**32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: add_(a.mantissa, b.mantissa)});\\n }\\n\\n function add_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: add_(a.mantissa, b.mantissa)});\\n }\\n\\n function add_(uint a, uint b) pure internal returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: sub_(a.mantissa, b.mantissa)});\\n }\\n\\n function sub_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: sub_(a.mantissa, b.mantissa)});\\n }\\n\\n function sub_(uint a, uint b) pure internal returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: mul_(a.mantissa, b.mantissa) / expScale});\\n }\\n\\n function mul_(Exp memory a, uint b) pure internal returns (Exp memory) {\\n return Exp({mantissa: mul_(a.mantissa, b)});\\n }\\n\\n function mul_(uint a, Exp memory b) pure internal returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: mul_(a.mantissa, b.mantissa) / doubleScale});\\n }\\n\\n function mul_(Double memory a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: mul_(a.mantissa, b)});\\n }\\n\\n function mul_(uint a, Double memory b) pure internal returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) pure internal returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) pure internal 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) pure internal returns (Exp memory) {\\n return Exp({mantissa: div_(mul_(a.mantissa, expScale), b.mantissa)});\\n }\\n\\n function div_(Exp memory a, uint b) pure internal returns (Exp memory) {\\n return Exp({mantissa: div_(a.mantissa, b)});\\n }\\n\\n function div_(uint a, Exp memory b) pure internal returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa)});\\n }\\n\\n function div_(Double memory a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(a.mantissa, b)});\\n }\\n\\n function div_(uint a, Double memory b) pure internal returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) pure internal returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(mul_(a, doubleScale), b)});\\n }\\n}\\n\",\"keccak256\":\"0x7cb184b7cee71a5e707053dfba7eebbd46f11974004028100510ccce19b6694d\"},\"contracts/InterestRateModel.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Compound's InterestRateModel Interface\\n * @author Compound\\n */\\ncontract InterestRateModel {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint cash, uint borrows, uint reserves) external view returns (uint);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) external view returns (uint);\\n\\n}\\n\",\"keccak256\":\"0x929282d73c79e6d700ebe79f9fafc1e414b3848acff5a56d6740afd1dc908678\"},\"contracts/PriceOracle.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.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 cToken asset\\n * @param cToken The cToken to get the underlying price of\\n * @return The underlying asset price mantissa (scaled by 1e18).\\n * Zero means the price is unavailable.\\n */\\n function getUnderlyingPrice(CToken cToken) external view returns (uint);\\n}\\n\",\"keccak256\":\"0xe79ebc23bba508eb2479e7b3340abf566da1ab62131f106aee1aac3dc53816ef\"}},\"version\":1}" + }, + "contracts/ComptrollerStorage.sol:ComptrollerV3Storage": { + "abi": "[{\"constant\":true,\"inputs\":[],\"name\":\"_borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allMarkets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compAccrued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compBorrowState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compBorrowerIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSupplierIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSupplyState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"liquidationIncentiveMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"markets\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isComped\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"seizeGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"transferGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}]", + "bin": "608060405234801561001057600080fd5b50610668806100206000396000f3fe608060405234801561001057600080fd5b50600436106101735760003560e01c80638e8f294b116100de578063ca0af04311610097578063dcfbc0c711610071578063dcfbc0c714610403578063e6653f3d1461040b578063e875544614610413578063f851a4401461041b57610173565b8063ca0af04314610383578063cc7ebdc4146103b1578063dce15449146103d757610173565b80638e8f294b146102ed57806394b2294b14610335578063aa9007541461033d578063ac0b0bb714610345578063b21be7fd1461034d578063bb82aa5e1461037b57610173565b80636b79c38d116101305780636b79c38d1461021d5780636d154ea51461026b578063731f0c2b146102915780637dc0d1d0146102b757806387f76303146102bf5780638c57804e146102c757610173565b80631d7b33d71461017857806324a3d622146101b057806326782247146101d45780633c94786f146101dc5780634ada90af146101f857806352d84d1e14610200575b600080fd5b61019e6004803603602081101561018e57600080fd5b50356001600160a01b0316610423565b60408051918252519081900360200190f35b6101b8610435565b604080516001600160a01b039092168252519081900360200190f35b6101b8610444565b6101e4610453565b604080519115158252519081900360200190f35b61019e610463565b6101b86004803603602081101561021657600080fd5b5035610469565b6102436004803603602081101561023357600080fd5b50356001600160a01b0316610490565b604080516001600160e01b03909316835263ffffffff90911660208301528051918290030190f35b6101e46004803603602081101561028157600080fd5b50356001600160a01b03166104ba565b6101e4600480360360208110156102a757600080fd5b50356001600160a01b03166104cf565b6101b86104e4565b6101e46104f3565b610243600480360360208110156102dd57600080fd5b50356001600160a01b0316610503565b6103136004803603602081101561030357600080fd5b50356001600160a01b031661052d565b6040805193151584526020840192909252151582820152519081900360600190f35b61019e610553565b61019e610559565b6101e461055f565b61019e6004803603604081101561036357600080fd5b506001600160a01b038135811691602001351661056f565b6101b861058c565b61019e6004803603604081101561039957600080fd5b506001600160a01b038135811691602001351661059b565b61019e600480360360208110156103c757600080fd5b50356001600160a01b03166105b8565b6101b8600480360360408110156103ed57600080fd5b506001600160a01b0381351690602001356105ca565b6101b86105ff565b6101e461060e565b61019e61061e565b6101b8610624565b600f6020526000908152604090205481565b600a546001600160a01b031681565b6001546001600160a01b031681565b600a54600160a01b900460ff1681565b60065481565b600d818154811061047657fe5b6000918252602090912001546001600160a01b0316905081565b6010602052600090815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b600c6020526000908152604090205460ff1681565b600b6020526000908152604090205460ff1681565b6004546001600160a01b031681565b600a54600160b01b900460ff1681565b6011602052600090815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b60096020526000908152604090208054600182015460039092015460ff91821692911683565b60075481565b600e5481565b600a54600160b81b900460ff1681565b601260209081526000928352604080842090915290825290205481565b6002546001600160a01b031681565b601360209081526000928352604080842090915290825290205481565b60146020526000908152604090205481565b600860205281600052604060002081815481106105e357fe5b6000918252602090912001546001600160a01b03169150829050565b6003546001600160a01b031681565b600a54600160a81b900460ff1681565b60055481565b6000546001600160a01b03168156fea265627a7a723158204f3f87eb208065c9d4c243b9d50928d16fa0899b44a952ebefa64692094eedd564736f6c63430005100032", + "metadata": "{\"compiler\":{\"version\":\"0.5.16+commit.9c3226ce\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"constant\":true,\"inputs\":[],\"name\":\"_borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allMarkets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compAccrued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compBorrowState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compBorrowerIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSupplierIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSupplyState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"liquidationIncentiveMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"markets\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isComped\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"seizeGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"transferGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"methods\":{}},\"userdoc\":{\"methods\":{}}},\"settings\":{\"compilationTarget\":{\"contracts/ComptrollerStorage.sol\":\"ComptrollerV3Storage\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/CToken.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./CTokenInterfaces.sol\\\";\\nimport \\\"./ErrorReporter.sol\\\";\\nimport \\\"./Exponential.sol\\\";\\nimport \\\"./EIP20Interface.sol\\\";\\nimport \\\"./InterestRateModel.sol\\\";\\n\\n/**\\n * @title Compound's CToken Contract\\n * @notice Abstract base for CTokens\\n * @author Compound\\n */\\ncontract CToken is CTokenInterface, Exponential, TokenErrorReporter {\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_) public {\\n require(msg.sender == admin, \\\"only admin may initialize the market\\\");\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = getBlockNumber();\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Transfer `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = uint(-1);\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srcTokensNew;\\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, srcTokensNew) = 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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srcTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != uint(-1)) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n // unused function\\n // comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transfer(address dst, uint256 amount) external nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferFrom(address src, address dst, uint256 amount) external nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (-1 means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool) {\\n address src = msg.sender;\\n transferAllowances[src][spender] = amount;\\n emit Approval(src, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (-1 means infinite)\\n */\\n function allowance(address owner, address spender) external view returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external returns (uint) {\\n Exp memory exchangeRate = Exp({mantissa: exchangeRateCurrent()});\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n require(mErr == MathError.NO_ERROR, \\\"balance could not be calculated\\\");\\n return balance;\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view returns (uint, uint, uint, uint) {\\n uint cTokenBalance = accountTokens[account];\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), cTokenBalance, borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @dev Function to simply retrieve block number\\n * This exists mainly for inheriting test contracts to stub this result.\\n */\\n function getBlockNumber() internal view returns (uint) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this cToken\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view returns (uint) {\\n return interestRateModel.getBorrowRate(getCashPrior(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this cToken\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view returns (uint) {\\n return interestRateModel.getSupplyRate(getCashPrior(), totalBorrows, totalReserves, reserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n require(err == MathError.NO_ERROR, \\\"borrowBalanceStored: borrowBalanceStoredInternal failed\\\");\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return (error code, the calculated balance or 0 if error code is non-zero)\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the CToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n require(err == MathError.NO_ERROR, \\\"exchangeRateStored: exchangeRateStoredInternal failed\\\");\\n return result;\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the CToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return (error code, calculated exchange rate scaled by 1e18)\\n */\\n function exchangeRateStoredInternal() internal view returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows - totalReserves) / totalSupply\\n */\\n uint totalCash = getCashPrior();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Get cash balance of this cToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage.\\n */\\n function accrueInterest() public returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = getBlockNumber();\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = getCashPrior();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n require(mathErr == MathError.NO_ERROR, \\\"could not calculate block delta\\\");\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({mantissa: borrowRateMantissa}), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(Exp({mantissa: reserveFactorMantissa}), interestAccumulated, reservesPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives cTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n struct MintLocalVars {\\n Error err;\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives cTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, 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's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the cToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of cTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.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 cTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED\\\");\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\\");\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender redeems cTokens in exchange for the underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemTokens The number of cTokens to redeem into underlying\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemInternal(uint redeemTokens) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(msg.sender, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems cTokens in exchange for a specified amount of underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemAmount The amount of underlying to receive from redeeming cTokens\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemUnderlyingInternal(uint redeemAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(msg.sender, 0, redeemAmount);\\n }\\n\\n struct RedeemLocalVars {\\n Error err;\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n /**\\n * @notice User redeems cTokens in exchange for the underlying asset\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param redeemTokensIn The number of cTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming cTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemFresh(address payable redeemer, uint redeemTokensIn, uint redeemAmountIn) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr));\\n }\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(Exp({mantissa: vars.exchangeRateMantissa}), redeemTokensIn);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(redeemAmountIn, Exp({mantissa: vars.exchangeRateMantissa}));\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REDEEM_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDEEM_FRESHNESS_CHECK);\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDEEM_TRANSFER_OUT_NOT_POSSIBLE);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We invoke doTransferOut for the redeemer and the redeemAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(redeemer, vars.redeemAmount);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n /* We call the defense hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender borrows assets from the protocol to their own address\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function borrowInternal(uint borrowAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(msg.sender, borrowAmount);\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n /**\\n * @notice Users borrow assets from the protocol to their own address\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function borrowFresh(address payable borrower, uint borrowAmount) internal returns (uint) {\\n /* Fail if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.BORROW_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.BORROW_FRESHNESS_CHECK);\\n }\\n\\n /* Fail gracefully if protocol has insufficient underlying cash */\\n if (getCashPrior() < borrowAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.BORROW_CASH_NOT_AVAILABLE);\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We invoke doTransferOut for the borrower and the borrowAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(borrower, borrowAmount);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to borrower\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer the account paying off the borrow\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount the amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED\\\");\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED\\\");\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this cToken to be liquidated\\n * @param cTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) 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 = cTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, cTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this cToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param cTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowFresh(address liquidator, address borrower, uint repayAmount, CTokenInterface cTokenCollateral) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(address(this), address(cTokenCollateral), liquidator, borrower, repayAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify cTokenCollateral market's block number equals current block number */\\n if (cTokenCollateral.accrualBlockNumber() != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = -1 */\\n if (repayAmount == uint(-1)) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & 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(cTokenCollateral), actualRepayAmount);\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(cTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(cTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = cTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(cTokenCollateral), seizeTokens);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.liquidateBorrowVerify(address(this), address(cTokenCollateral), liquidator, borrower, actualRepayAmount, seizeTokens);\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another cToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed cToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of cTokens to seize\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function seize(address liquidator, address borrower, uint seizeTokens) external nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n struct SeizeInternalLocalVars {\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n uint liquidatorSeizeTokens;\\n uint protocolSeizeTokens;\\n uint protocolSeizeAmount;\\n uint exchangeRateMantissa;\\n uint totalReservesNew;\\n uint totalSupplyNew;\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another CToken.\\n * Its absolutely critical to use msg.sender as the seizer cToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed cToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of cTokens to seize\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function seizeInternal(address seizerToken, address liquidator, address borrower, uint seizeTokens) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n SeizeInternalLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (vars.mathErr, vars.borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(vars.mathErr));\\n }\\n\\n vars.protocolSeizeTokens = mul_(seizeTokens, Exp({mantissa: protocolSeizeShareMantissa}));\\n vars.liquidatorSeizeTokens = sub_(seizeTokens, vars.protocolSeizeTokens);\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n require(vars.mathErr == MathError.NO_ERROR, \\\"exchange rate math error\\\");\\n\\n vars.protocolSeizeAmount = mul_ScalarTruncate(Exp({mantissa: vars.exchangeRateMantissa}), vars.protocolSeizeTokens);\\n\\n vars.totalReservesNew = add_(totalReserves, vars.protocolSeizeAmount);\\n vars.totalSupplyNew = sub_(totalSupply, vars.protocolSeizeTokens);\\n\\n (vars.mathErr, vars.liquidatorTokensNew) = addUInt(accountTokens[liquidator], vars.liquidatorSeizeTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(vars.mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n totalReserves = vars.totalReservesNew;\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[borrower] = vars.borrowerTokensNew;\\n accountTokens[liquidator] = vars.liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, vars.liquidatorSeizeTokens);\\n emit Transfer(borrower, address(this), vars.protocolSeizeTokens);\\n emit ReservesAdded(address(this), vars.protocolSeizeAmount, vars.totalReservesNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n\\n /*** Admin Functions ***/\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPendingAdmin(address payable newPendingAdmin) external returns (uint) {\\n // Check caller = admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\\n }\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptAdmin() external returns (uint) {\\n // Check caller is pendingAdmin and pendingAdmin \\u2260 address(0)\\n if (msg.sender != pendingAdmin || msg.sender == address(0)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = address(0);\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setComptroller(ComptrollerInterface newComptroller) public returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_COMPTROLLER_OWNER_CHECK);\\n }\\n\\n ComptrollerInterface oldComptroller = comptroller;\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(oldComptroller, newComptroller);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh\\n * @dev Admin function to accrue interest and set a new reserve factor\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setReserveFactor(uint newReserveFactorMantissa) external nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\\n * @dev Admin function to set a new reserve factor\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_RESERVE_FACTOR_ADMIN_CHECK);\\n }\\n\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring from msg.sender\\n * @param addAmount Amount of addition to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to admin\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _reduceReserves(uint reduceAmount) external nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to admin\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _reduceReservesFresh(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's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n totalReservesNew = totalReserves - reduceAmount;\\n // We checked reduceAmount <= totalReserves above, so this should never revert.\\n require(totalReservesNew <= 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't be sure if side effects occurred.\\n doTransferOut(admin, reduceAmount);\\n\\n emit ReservesReduced(admin, reduceAmount, totalReservesNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Admin function to accrue interest and update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel);\\n }\\n\\n /**\\n * @notice updates the interest rate model (*requires fresh interest accrual)\\n * @dev Admin function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal returns (uint) {\\n\\n // Used to store old model for use in the event that is emitted on success\\n InterestRateModel oldInterestRateModel;\\n\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_INTEREST_RATE_MODEL_OWNER_CHECK);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Track the market's current interest rate model\\n oldInterestRateModel = interestRateModel;\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view returns (uint);\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure tather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal;\\n\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n}\\n\",\"keccak256\":\"0x436ec2e309682995f8a82dfdd9e8f75928599c10a9a680dddbee6c275014008d\"},\"contracts/CTokenInterfaces.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./InterestRateModel.sol\\\";\\nimport \\\"./EIP20NonStandardInterface.sol\\\";\\n\\ncontract CTokenStorage {\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-cToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModel public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first CTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping (address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping (address => mapping (address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Share of seized collateral that is added to reserves\\n */\\n uint public constant protocolSeizeShareMantissa = 2.8e16; //2.8%\\n\\n}\\n\\ncontract CTokenInterface is CTokenStorage {\\n /**\\n * @notice Indicator that this is a CToken contract (for inspection)\\n */\\n bool public constant isCToken = true;\\n\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(address liquidator, address borrower, uint repayAmount, address cTokenCollateral, uint seizeTokens);\\n\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin is updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(InterestRateModel oldInterestRateModel, InterestRateModel newInterestRateModel);\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address admin, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Failure event\\n */\\n event Failure(uint error, uint info, uint detail);\\n\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external returns (bool);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function approve(address spender, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function balanceOfUnderlying(address owner) external returns (uint);\\n function getAccountSnapshot(address account) external view returns (uint, uint, uint, uint);\\n function borrowRatePerBlock() external view returns (uint);\\n function supplyRatePerBlock() external view returns (uint);\\n function totalBorrowsCurrent() external returns (uint);\\n function borrowBalanceCurrent(address account) external returns (uint);\\n function borrowBalanceStored(address account) public view returns (uint);\\n function exchangeRateCurrent() public returns (uint);\\n function exchangeRateStored() public view returns (uint);\\n function getCash() external view returns (uint);\\n function accrueInterest() public returns (uint);\\n function seize(address liquidator, address borrower, uint seizeTokens) external returns (uint);\\n\\n\\n /*** Admin Functions ***/\\n\\n function _setPendingAdmin(address payable newPendingAdmin) external returns (uint);\\n function _acceptAdmin() external returns (uint);\\n function _setComptroller(ComptrollerInterface newComptroller) public returns (uint);\\n function _setReserveFactor(uint newReserveFactorMantissa) external returns (uint);\\n function _reduceReserves(uint reduceAmount) external returns (uint);\\n function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint);\\n}\\n\\ncontract CErc20Storage {\\n /**\\n * @notice Underlying asset for this CToken\\n */\\n address public underlying;\\n}\\n\\ncontract CErc20Interface is CErc20Storage {\\n\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n function redeem(uint redeemTokens) external returns (uint);\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n function borrow(uint borrowAmount) external returns (uint);\\n function repayBorrow(uint repayAmount) external returns (uint);\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n function liquidateBorrow(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) external returns (uint);\\n function sweepToken(EIP20NonStandardInterface token) external;\\n\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ncontract CDelegationStorage {\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n}\\n\\ncontract CDelegatorInterface is CDelegationStorage {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(address implementation_, bool allowResign, bytes memory becomeImplementationData) public;\\n}\\n\\ncontract CDelegateInterface is CDelegationStorage {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) public;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() public;\\n}\\n\",\"keccak256\":\"0x963bbf60b4c0b76900b3fcb2db8c8be634934b37b4113f1055e57a308197d21a\"},\"contracts/CarefulMath.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Careful Math\\n * @author Compound\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c = a * b;\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n return (MathError.NO_ERROR, a - b);\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c = a + b;\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\",\"keccak256\":\"0x0647348f27e41d22555d99eebd217dee02a4d737df6accd7cce5347a7487c7de\"},\"contracts/ComptrollerInterface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\ncontract ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n bool public constant isComptroller = true;\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata cTokens) external returns (uint[] memory);\\n function exitMarket(address cToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address cToken, address minter, uint mintAmount) external returns (uint);\\n function mintVerify(address cToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address cToken, address redeemer, uint redeemTokens) external returns (uint);\\n function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address cToken, address borrower, uint borrowAmount) external returns (uint);\\n function borrowVerify(address cToken, address borrower, uint borrowAmount) external;\\n\\n function repayBorrowAllowed(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount) external returns (uint);\\n function repayBorrowVerify(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex) external;\\n\\n function liquidateBorrowAllowed(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount) external returns (uint);\\n function liquidateBorrowVerify(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens) external;\\n\\n function seizeAllowed(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external returns (uint);\\n function seizeVerify(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external;\\n\\n function transferAllowed(address cToken, address src, address dst, uint transferTokens) external returns (uint);\\n function transferVerify(address cToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n uint repayAmount) external view returns (uint, uint);\\n}\\n\",\"keccak256\":\"0xede7670d2dd7b25d0187aecd2c28b7b5ca7d7c1bdac144fbedecf5d4bdd92a6b\"},\"contracts/ComptrollerStorage.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.sol\\\";\\nimport \\\"./PriceOracle.sol\\\";\\n\\ncontract UnitrollerAdminStorage {\\n /**\\n * @notice Administrator for this contract\\n */\\n address public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address public pendingAdmin;\\n\\n /**\\n * @notice Active brains of Unitroller\\n */\\n address public comptrollerImplementation;\\n\\n /**\\n * @notice Pending brains of Unitroller\\n */\\n address public pendingComptrollerImplementation;\\n}\\n\\ncontract ComptrollerV1Storage is UnitrollerAdminStorage {\\n\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n PriceOracle public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives\\n */\\n uint public liquidationIncentiveMantissa;\\n\\n /**\\n * @notice Max number of assets a single account can participate in (borrow or use as collateral)\\n */\\n uint public maxAssets;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\\n */\\n mapping(address => CToken[]) public accountAssets;\\n\\n}\\n\\ncontract ComptrollerV2Storage is ComptrollerV1Storage {\\n struct Market {\\n /// @notice Whether or not this market is listed\\n bool isListed;\\n\\n /**\\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\\n * For instance, 0.9 to allow borrowing 90% of collateral value.\\n * Must be between 0 and 1, and stored as a mantissa.\\n */\\n uint collateralFactorMantissa;\\n\\n /// @notice Per-market mapping of \\\"accounts in this asset\\\"\\n mapping(address => bool) accountMembership;\\n\\n /// @notice Whether or not this market receives COMP\\n bool isComped;\\n }\\n\\n /**\\n * @notice Official mapping of cTokens -> Market metadata\\n * @dev Used e.g. to determine if a market is supported\\n */\\n mapping(address => Market) public markets;\\n\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n * Actions which allow users to remove their own assets cannot be paused.\\n * Liquidation / seizing / transfer can only be paused globally, not by market.\\n */\\n address public pauseGuardian;\\n bool public _mintGuardianPaused;\\n bool public _borrowGuardianPaused;\\n bool public transferGuardianPaused;\\n bool public seizeGuardianPaused;\\n mapping(address => bool) public mintGuardianPaused;\\n mapping(address => bool) public borrowGuardianPaused;\\n}\\n\\ncontract ComptrollerV3Storage is ComptrollerV2Storage {\\n struct CompMarketState {\\n /// @notice The market's last updated compBorrowIndex or compSupplyIndex\\n uint224 index;\\n\\n /// @notice The block number the index was last updated at\\n uint32 block;\\n }\\n\\n /// @notice A list of all markets\\n CToken[] public allMarkets;\\n\\n /// @notice The rate at which the flywheel distributes COMP, per block\\n uint public compRate;\\n\\n /// @notice The portion of compRate that each market currently receives\\n mapping(address => uint) public compSpeeds;\\n\\n /// @notice The COMP market supply state for each market\\n mapping(address => CompMarketState) public compSupplyState;\\n\\n /// @notice The COMP market borrow state for each market\\n mapping(address => CompMarketState) public compBorrowState;\\n\\n /// @notice The COMP borrow index for each market for each supplier as of the last time they accrued COMP\\n mapping(address => mapping(address => uint)) public compSupplierIndex;\\n\\n /// @notice The COMP borrow index for each market for each borrower as of the last time they accrued COMP\\n mapping(address => mapping(address => uint)) public compBorrowerIndex;\\n\\n /// @notice The COMP accrued but not yet transferred to each user\\n mapping(address => uint) public compAccrued;\\n}\\n\\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\\n // @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\\n address public borrowCapGuardian;\\n\\n // @notice Borrow caps enforced by borrowAllowed for each cToken address. Defaults to zero which corresponds to unlimited borrowing.\\n mapping(address => uint) public borrowCaps;\\n}\\n\\ncontract ComptrollerV5Storage is ComptrollerV4Storage {\\n /// @notice The portion of COMP that each contributor receives per block\\n mapping(address => uint) public compContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's COMP rewards have been allocated\\n mapping(address => uint) public lastContributorBlock;\\n}\\n\",\"keccak256\":\"0x5db970485549f493618b5e36bfd4d799d4f8701a136bf71ed6e0117e1ed8c254\"},\"contracts/EIP20Interface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title ERC 20 Token Standard Interface\\n * https://eips.ethereum.org/EIPS/eip-20\\n */\\ninterface EIP20Interface {\\n function name() external view returns (string memory);\\n function symbol() external view returns (string memory);\\n function decimals() external view returns (uint8);\\n\\n /**\\n * @notice Get the total number of tokens in circulation\\n * @return The supply of tokens\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @notice Gets the balance of the specified address\\n * @param owner The address from which the balance will be retrieved\\n * @return The balance\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transfer(address dst, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferFrom(address src, address dst, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (-1 means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (-1 means infinite)\\n */\\n function allowance(address owner, address spender) external view returns (uint256 remaining);\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n}\\n\",\"keccak256\":\"0xfd8ed2eac6d0b4d9ee6b32628ba68bae17544b66f190a5f7ce0c6ad024579dc8\"},\"contracts/EIP20NonStandardInterface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title EIP20NonStandardInterface\\n * @dev Version of ERC20 with no return values for `transfer` and `transferFrom`\\n * See https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\\n */\\ninterface EIP20NonStandardInterface {\\n\\n /**\\n * @notice Get the total number of tokens in circulation\\n * @return The supply of tokens\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @notice Gets the balance of the specified address\\n * @param owner The address from which the balance will be retrieved\\n * @return The balance\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n ///\\n /// !!!!!!!!!!!!!!\\n /// !!! NOTICE !!! `transfer` does not return a value, in violation of the ERC-20 specification\\n /// !!!!!!!!!!!!!!\\n ///\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n */\\n function transfer(address dst, uint256 amount) external;\\n\\n ///\\n /// !!!!!!!!!!!!!!\\n /// !!! NOTICE !!! `transferFrom` does not return a value, in violation of the ERC-20 specification\\n /// !!!!!!!!!!!!!!\\n ///\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n */\\n function transferFrom(address src, address dst, uint256 amount) external;\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent\\n */\\n function allowance(address owner, address spender) external view returns (uint256 remaining);\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n}\\n\",\"keccak256\":\"0x9719f12e4b80b51147ac195553a198cf8b0c516e7e4d04fc324a23ed15cbafb2\"},\"contracts/ErrorReporter.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\ncontract ComptrollerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\",\"keccak256\":\"0x5179afb1071c0fd555e5c1f1d2565f72dbe1740cc3dd02f6e52037f150afc5c9\"},\"contracts/Exponential.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CarefulMath.sol\\\";\\nimport \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @dev Legacy contract for compatibility reasons with existing contracts that still use MathError\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: rational}));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({mantissa: result}));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({mantissa: result}));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: scaledMantissa}));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: descaledMantissa}));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) pure internal returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({mantissa: 0}));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({mantissa: product}));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) pure internal returns (MathError, Exp memory) {\\n return mulExp(Exp({mantissa: a}), Exp({mantissa: b}));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) pure internal returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6ff054d65a0289dbb43c9f437d6909f9cf1207c9b8f984b3cb8e97a9de76a434\"},\"contracts/ExponentialNoError.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\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 Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) pure internal returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) pure internal returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) pure internal returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) pure internal returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) pure internal returns (uint224) {\\n require(n < 2**224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) pure internal returns (uint32) {\\n require(n < 2**32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: add_(a.mantissa, b.mantissa)});\\n }\\n\\n function add_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: add_(a.mantissa, b.mantissa)});\\n }\\n\\n function add_(uint a, uint b) pure internal returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: sub_(a.mantissa, b.mantissa)});\\n }\\n\\n function sub_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: sub_(a.mantissa, b.mantissa)});\\n }\\n\\n function sub_(uint a, uint b) pure internal returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: mul_(a.mantissa, b.mantissa) / expScale});\\n }\\n\\n function mul_(Exp memory a, uint b) pure internal returns (Exp memory) {\\n return Exp({mantissa: mul_(a.mantissa, b)});\\n }\\n\\n function mul_(uint a, Exp memory b) pure internal returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: mul_(a.mantissa, b.mantissa) / doubleScale});\\n }\\n\\n function mul_(Double memory a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: mul_(a.mantissa, b)});\\n }\\n\\n function mul_(uint a, Double memory b) pure internal returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) pure internal returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) pure internal 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) pure internal returns (Exp memory) {\\n return Exp({mantissa: div_(mul_(a.mantissa, expScale), b.mantissa)});\\n }\\n\\n function div_(Exp memory a, uint b) pure internal returns (Exp memory) {\\n return Exp({mantissa: div_(a.mantissa, b)});\\n }\\n\\n function div_(uint a, Exp memory b) pure internal returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa)});\\n }\\n\\n function div_(Double memory a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(a.mantissa, b)});\\n }\\n\\n function div_(uint a, Double memory b) pure internal returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) pure internal returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(mul_(a, doubleScale), b)});\\n }\\n}\\n\",\"keccak256\":\"0x7cb184b7cee71a5e707053dfba7eebbd46f11974004028100510ccce19b6694d\"},\"contracts/InterestRateModel.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Compound's InterestRateModel Interface\\n * @author Compound\\n */\\ncontract InterestRateModel {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint cash, uint borrows, uint reserves) external view returns (uint);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) external view returns (uint);\\n\\n}\\n\",\"keccak256\":\"0x929282d73c79e6d700ebe79f9fafc1e414b3848acff5a56d6740afd1dc908678\"},\"contracts/PriceOracle.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.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 cToken asset\\n * @param cToken The cToken to get the underlying price of\\n * @return The underlying asset price mantissa (scaled by 1e18).\\n * Zero means the price is unavailable.\\n */\\n function getUnderlyingPrice(CToken cToken) external view returns (uint);\\n}\\n\",\"keccak256\":\"0xe79ebc23bba508eb2479e7b3340abf566da1ab62131f106aee1aac3dc53816ef\"}},\"version\":1}" + }, + "contracts/ComptrollerStorage.sol:ComptrollerV4Storage": { + "abi": "[{\"constant\":true,\"inputs\":[],\"name\":\"_borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allMarkets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"borrowCapGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compAccrued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compBorrowState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compBorrowerIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSupplierIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSupplyState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"liquidationIncentiveMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"markets\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isComped\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"seizeGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"transferGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}]", + "bin": "608060405234801561001057600080fd5b506106ed806100206000396000f3fe608060405234801561001057600080fd5b50600436106101a95760003560e01c80638c57804e116100f9578063ca0af04311610097578063dcfbc0c711610071578063dcfbc0c714610467578063e6653f3d1461046f578063e875544614610477578063f851a4401461047f576101a9565b8063ca0af043146103e7578063cc7ebdc414610415578063dce154491461043b576101a9565b8063aa900754116100d3578063aa900754146103a1578063ac0b0bb7146103a9578063b21be7fd146103b1578063bb82aa5e146103df576101a9565b80638c57804e1461032b5780638e8f294b1461035157806394b2294b14610399576101a9565b80634ada90af116101665780636d154ea5116101405780636d154ea5146102cf578063731f0c2b146102f55780637dc0d1d01461031b57806387f7630314610323576101a9565b80634ada90af1461025c57806352d84d1e146102645780636b79c38d14610281576101a9565b80631d7b33d7146101ae57806321af4569146101e657806324a3d6221461020a57806326782247146102125780633c94786f1461021a5780634a58443214610236575b600080fd5b6101d4600480360360208110156101c457600080fd5b50356001600160a01b0316610487565b60408051918252519081900360200190f35b6101ee610499565b604080516001600160a01b039092168252519081900360200190f35b6101ee6104a8565b6101ee6104b7565b6102226104c6565b604080519115158252519081900360200190f35b6101d46004803603602081101561024c57600080fd5b50356001600160a01b03166104d6565b6101d46104e8565b6101ee6004803603602081101561027a57600080fd5b50356104ee565b6102a76004803603602081101561029757600080fd5b50356001600160a01b0316610515565b604080516001600160e01b03909316835263ffffffff90911660208301528051918290030190f35b610222600480360360208110156102e557600080fd5b50356001600160a01b031661053f565b6102226004803603602081101561030b57600080fd5b50356001600160a01b0316610554565b6101ee610569565b610222610578565b6102a76004803603602081101561034157600080fd5b50356001600160a01b0316610588565b6103776004803603602081101561036757600080fd5b50356001600160a01b03166105b2565b6040805193151584526020840192909252151582820152519081900360600190f35b6101d46105d8565b6101d46105de565b6102226105e4565b6101d4600480360360408110156103c757600080fd5b506001600160a01b03813581169160200135166105f4565b6101ee610611565b6101d4600480360360408110156103fd57600080fd5b506001600160a01b0381358116916020013516610620565b6101d46004803603602081101561042b57600080fd5b50356001600160a01b031661063d565b6101ee6004803603604081101561045157600080fd5b506001600160a01b03813516906020013561064f565b6101ee610684565b610222610693565b6101d46106a3565b6101ee6106a9565b600f6020526000908152604090205481565b6015546001600160a01b031681565b600a546001600160a01b031681565b6001546001600160a01b031681565b600a54600160a01b900460ff1681565b60166020526000908152604090205481565b60065481565b600d81815481106104fb57fe5b6000918252602090912001546001600160a01b0316905081565b6010602052600090815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b600c6020526000908152604090205460ff1681565b600b6020526000908152604090205460ff1681565b6004546001600160a01b031681565b600a54600160b01b900460ff1681565b6011602052600090815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b60096020526000908152604090208054600182015460039092015460ff91821692911683565b60075481565b600e5481565b600a54600160b81b900460ff1681565b601260209081526000928352604080842090915290825290205481565b6002546001600160a01b031681565b601360209081526000928352604080842090915290825290205481565b60146020526000908152604090205481565b6008602052816000526040600020818154811061066857fe5b6000918252602090912001546001600160a01b03169150829050565b6003546001600160a01b031681565b600a54600160a81b900460ff1681565b60055481565b6000546001600160a01b03168156fea265627a7a72315820c7666d6f288bec1fc7f415f478ea72107c1ce9a717248c6ca98ede58789ce00164736f6c63430005100032", + "metadata": "{\"compiler\":{\"version\":\"0.5.16+commit.9c3226ce\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"constant\":true,\"inputs\":[],\"name\":\"_borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allMarkets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"borrowCapGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compAccrued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compBorrowState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compBorrowerIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSupplierIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSupplyState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"liquidationIncentiveMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"markets\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isComped\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"seizeGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"transferGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"methods\":{}},\"userdoc\":{\"methods\":{}}},\"settings\":{\"compilationTarget\":{\"contracts/ComptrollerStorage.sol\":\"ComptrollerV4Storage\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/CToken.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./CTokenInterfaces.sol\\\";\\nimport \\\"./ErrorReporter.sol\\\";\\nimport \\\"./Exponential.sol\\\";\\nimport \\\"./EIP20Interface.sol\\\";\\nimport \\\"./InterestRateModel.sol\\\";\\n\\n/**\\n * @title Compound's CToken Contract\\n * @notice Abstract base for CTokens\\n * @author Compound\\n */\\ncontract CToken is CTokenInterface, Exponential, TokenErrorReporter {\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_) public {\\n require(msg.sender == admin, \\\"only admin may initialize the market\\\");\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = getBlockNumber();\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Transfer `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = uint(-1);\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srcTokensNew;\\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, srcTokensNew) = 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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srcTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != uint(-1)) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n // unused function\\n // comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transfer(address dst, uint256 amount) external nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferFrom(address src, address dst, uint256 amount) external nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (-1 means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool) {\\n address src = msg.sender;\\n transferAllowances[src][spender] = amount;\\n emit Approval(src, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (-1 means infinite)\\n */\\n function allowance(address owner, address spender) external view returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external returns (uint) {\\n Exp memory exchangeRate = Exp({mantissa: exchangeRateCurrent()});\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n require(mErr == MathError.NO_ERROR, \\\"balance could not be calculated\\\");\\n return balance;\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view returns (uint, uint, uint, uint) {\\n uint cTokenBalance = accountTokens[account];\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), cTokenBalance, borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @dev Function to simply retrieve block number\\n * This exists mainly for inheriting test contracts to stub this result.\\n */\\n function getBlockNumber() internal view returns (uint) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this cToken\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view returns (uint) {\\n return interestRateModel.getBorrowRate(getCashPrior(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this cToken\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view returns (uint) {\\n return interestRateModel.getSupplyRate(getCashPrior(), totalBorrows, totalReserves, reserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n require(err == MathError.NO_ERROR, \\\"borrowBalanceStored: borrowBalanceStoredInternal failed\\\");\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return (error code, the calculated balance or 0 if error code is non-zero)\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the CToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n require(err == MathError.NO_ERROR, \\\"exchangeRateStored: exchangeRateStoredInternal failed\\\");\\n return result;\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the CToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return (error code, calculated exchange rate scaled by 1e18)\\n */\\n function exchangeRateStoredInternal() internal view returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows - totalReserves) / totalSupply\\n */\\n uint totalCash = getCashPrior();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Get cash balance of this cToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage.\\n */\\n function accrueInterest() public returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = getBlockNumber();\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = getCashPrior();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n require(mathErr == MathError.NO_ERROR, \\\"could not calculate block delta\\\");\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({mantissa: borrowRateMantissa}), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(Exp({mantissa: reserveFactorMantissa}), interestAccumulated, reservesPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives cTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n struct MintLocalVars {\\n Error err;\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives cTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, 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's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the cToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of cTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.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 cTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED\\\");\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\\");\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender redeems cTokens in exchange for the underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemTokens The number of cTokens to redeem into underlying\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemInternal(uint redeemTokens) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(msg.sender, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems cTokens in exchange for a specified amount of underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemAmount The amount of underlying to receive from redeeming cTokens\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemUnderlyingInternal(uint redeemAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(msg.sender, 0, redeemAmount);\\n }\\n\\n struct RedeemLocalVars {\\n Error err;\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n /**\\n * @notice User redeems cTokens in exchange for the underlying asset\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param redeemTokensIn The number of cTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming cTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemFresh(address payable redeemer, uint redeemTokensIn, uint redeemAmountIn) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr));\\n }\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(Exp({mantissa: vars.exchangeRateMantissa}), redeemTokensIn);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(redeemAmountIn, Exp({mantissa: vars.exchangeRateMantissa}));\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REDEEM_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDEEM_FRESHNESS_CHECK);\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDEEM_TRANSFER_OUT_NOT_POSSIBLE);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We invoke doTransferOut for the redeemer and the redeemAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(redeemer, vars.redeemAmount);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n /* We call the defense hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender borrows assets from the protocol to their own address\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function borrowInternal(uint borrowAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(msg.sender, borrowAmount);\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n /**\\n * @notice Users borrow assets from the protocol to their own address\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function borrowFresh(address payable borrower, uint borrowAmount) internal returns (uint) {\\n /* Fail if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.BORROW_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.BORROW_FRESHNESS_CHECK);\\n }\\n\\n /* Fail gracefully if protocol has insufficient underlying cash */\\n if (getCashPrior() < borrowAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.BORROW_CASH_NOT_AVAILABLE);\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We invoke doTransferOut for the borrower and the borrowAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(borrower, borrowAmount);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to borrower\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer the account paying off the borrow\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount the amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED\\\");\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED\\\");\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this cToken to be liquidated\\n * @param cTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) 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 = cTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, cTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this cToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param cTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowFresh(address liquidator, address borrower, uint repayAmount, CTokenInterface cTokenCollateral) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(address(this), address(cTokenCollateral), liquidator, borrower, repayAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify cTokenCollateral market's block number equals current block number */\\n if (cTokenCollateral.accrualBlockNumber() != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = -1 */\\n if (repayAmount == uint(-1)) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & 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(cTokenCollateral), actualRepayAmount);\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(cTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(cTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = cTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(cTokenCollateral), seizeTokens);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.liquidateBorrowVerify(address(this), address(cTokenCollateral), liquidator, borrower, actualRepayAmount, seizeTokens);\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another cToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed cToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of cTokens to seize\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function seize(address liquidator, address borrower, uint seizeTokens) external nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n struct SeizeInternalLocalVars {\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n uint liquidatorSeizeTokens;\\n uint protocolSeizeTokens;\\n uint protocolSeizeAmount;\\n uint exchangeRateMantissa;\\n uint totalReservesNew;\\n uint totalSupplyNew;\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another CToken.\\n * Its absolutely critical to use msg.sender as the seizer cToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed cToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of cTokens to seize\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function seizeInternal(address seizerToken, address liquidator, address borrower, uint seizeTokens) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n SeizeInternalLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (vars.mathErr, vars.borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(vars.mathErr));\\n }\\n\\n vars.protocolSeizeTokens = mul_(seizeTokens, Exp({mantissa: protocolSeizeShareMantissa}));\\n vars.liquidatorSeizeTokens = sub_(seizeTokens, vars.protocolSeizeTokens);\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n require(vars.mathErr == MathError.NO_ERROR, \\\"exchange rate math error\\\");\\n\\n vars.protocolSeizeAmount = mul_ScalarTruncate(Exp({mantissa: vars.exchangeRateMantissa}), vars.protocolSeizeTokens);\\n\\n vars.totalReservesNew = add_(totalReserves, vars.protocolSeizeAmount);\\n vars.totalSupplyNew = sub_(totalSupply, vars.protocolSeizeTokens);\\n\\n (vars.mathErr, vars.liquidatorTokensNew) = addUInt(accountTokens[liquidator], vars.liquidatorSeizeTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(vars.mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n totalReserves = vars.totalReservesNew;\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[borrower] = vars.borrowerTokensNew;\\n accountTokens[liquidator] = vars.liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, vars.liquidatorSeizeTokens);\\n emit Transfer(borrower, address(this), vars.protocolSeizeTokens);\\n emit ReservesAdded(address(this), vars.protocolSeizeAmount, vars.totalReservesNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n\\n /*** Admin Functions ***/\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPendingAdmin(address payable newPendingAdmin) external returns (uint) {\\n // Check caller = admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\\n }\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptAdmin() external returns (uint) {\\n // Check caller is pendingAdmin and pendingAdmin \\u2260 address(0)\\n if (msg.sender != pendingAdmin || msg.sender == address(0)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = address(0);\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setComptroller(ComptrollerInterface newComptroller) public returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_COMPTROLLER_OWNER_CHECK);\\n }\\n\\n ComptrollerInterface oldComptroller = comptroller;\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(oldComptroller, newComptroller);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh\\n * @dev Admin function to accrue interest and set a new reserve factor\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setReserveFactor(uint newReserveFactorMantissa) external nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\\n * @dev Admin function to set a new reserve factor\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_RESERVE_FACTOR_ADMIN_CHECK);\\n }\\n\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring from msg.sender\\n * @param addAmount Amount of addition to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to admin\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _reduceReserves(uint reduceAmount) external nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to admin\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _reduceReservesFresh(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's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n totalReservesNew = totalReserves - reduceAmount;\\n // We checked reduceAmount <= totalReserves above, so this should never revert.\\n require(totalReservesNew <= 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't be sure if side effects occurred.\\n doTransferOut(admin, reduceAmount);\\n\\n emit ReservesReduced(admin, reduceAmount, totalReservesNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Admin function to accrue interest and update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel);\\n }\\n\\n /**\\n * @notice updates the interest rate model (*requires fresh interest accrual)\\n * @dev Admin function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal returns (uint) {\\n\\n // Used to store old model for use in the event that is emitted on success\\n InterestRateModel oldInterestRateModel;\\n\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_INTEREST_RATE_MODEL_OWNER_CHECK);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Track the market's current interest rate model\\n oldInterestRateModel = interestRateModel;\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view returns (uint);\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure tather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal;\\n\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n}\\n\",\"keccak256\":\"0x436ec2e309682995f8a82dfdd9e8f75928599c10a9a680dddbee6c275014008d\"},\"contracts/CTokenInterfaces.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./InterestRateModel.sol\\\";\\nimport \\\"./EIP20NonStandardInterface.sol\\\";\\n\\ncontract CTokenStorage {\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-cToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModel public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first CTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping (address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping (address => mapping (address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Share of seized collateral that is added to reserves\\n */\\n uint public constant protocolSeizeShareMantissa = 2.8e16; //2.8%\\n\\n}\\n\\ncontract CTokenInterface is CTokenStorage {\\n /**\\n * @notice Indicator that this is a CToken contract (for inspection)\\n */\\n bool public constant isCToken = true;\\n\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(address liquidator, address borrower, uint repayAmount, address cTokenCollateral, uint seizeTokens);\\n\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin is updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(InterestRateModel oldInterestRateModel, InterestRateModel newInterestRateModel);\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address admin, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Failure event\\n */\\n event Failure(uint error, uint info, uint detail);\\n\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external returns (bool);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function approve(address spender, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function balanceOfUnderlying(address owner) external returns (uint);\\n function getAccountSnapshot(address account) external view returns (uint, uint, uint, uint);\\n function borrowRatePerBlock() external view returns (uint);\\n function supplyRatePerBlock() external view returns (uint);\\n function totalBorrowsCurrent() external returns (uint);\\n function borrowBalanceCurrent(address account) external returns (uint);\\n function borrowBalanceStored(address account) public view returns (uint);\\n function exchangeRateCurrent() public returns (uint);\\n function exchangeRateStored() public view returns (uint);\\n function getCash() external view returns (uint);\\n function accrueInterest() public returns (uint);\\n function seize(address liquidator, address borrower, uint seizeTokens) external returns (uint);\\n\\n\\n /*** Admin Functions ***/\\n\\n function _setPendingAdmin(address payable newPendingAdmin) external returns (uint);\\n function _acceptAdmin() external returns (uint);\\n function _setComptroller(ComptrollerInterface newComptroller) public returns (uint);\\n function _setReserveFactor(uint newReserveFactorMantissa) external returns (uint);\\n function _reduceReserves(uint reduceAmount) external returns (uint);\\n function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint);\\n}\\n\\ncontract CErc20Storage {\\n /**\\n * @notice Underlying asset for this CToken\\n */\\n address public underlying;\\n}\\n\\ncontract CErc20Interface is CErc20Storage {\\n\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n function redeem(uint redeemTokens) external returns (uint);\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n function borrow(uint borrowAmount) external returns (uint);\\n function repayBorrow(uint repayAmount) external returns (uint);\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n function liquidateBorrow(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) external returns (uint);\\n function sweepToken(EIP20NonStandardInterface token) external;\\n\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ncontract CDelegationStorage {\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n}\\n\\ncontract CDelegatorInterface is CDelegationStorage {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(address implementation_, bool allowResign, bytes memory becomeImplementationData) public;\\n}\\n\\ncontract CDelegateInterface is CDelegationStorage {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) public;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() public;\\n}\\n\",\"keccak256\":\"0x963bbf60b4c0b76900b3fcb2db8c8be634934b37b4113f1055e57a308197d21a\"},\"contracts/CarefulMath.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Careful Math\\n * @author Compound\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c = a * b;\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n return (MathError.NO_ERROR, a - b);\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c = a + b;\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\",\"keccak256\":\"0x0647348f27e41d22555d99eebd217dee02a4d737df6accd7cce5347a7487c7de\"},\"contracts/ComptrollerInterface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\ncontract ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n bool public constant isComptroller = true;\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata cTokens) external returns (uint[] memory);\\n function exitMarket(address cToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address cToken, address minter, uint mintAmount) external returns (uint);\\n function mintVerify(address cToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address cToken, address redeemer, uint redeemTokens) external returns (uint);\\n function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address cToken, address borrower, uint borrowAmount) external returns (uint);\\n function borrowVerify(address cToken, address borrower, uint borrowAmount) external;\\n\\n function repayBorrowAllowed(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount) external returns (uint);\\n function repayBorrowVerify(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex) external;\\n\\n function liquidateBorrowAllowed(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount) external returns (uint);\\n function liquidateBorrowVerify(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens) external;\\n\\n function seizeAllowed(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external returns (uint);\\n function seizeVerify(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external;\\n\\n function transferAllowed(address cToken, address src, address dst, uint transferTokens) external returns (uint);\\n function transferVerify(address cToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n uint repayAmount) external view returns (uint, uint);\\n}\\n\",\"keccak256\":\"0xede7670d2dd7b25d0187aecd2c28b7b5ca7d7c1bdac144fbedecf5d4bdd92a6b\"},\"contracts/ComptrollerStorage.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.sol\\\";\\nimport \\\"./PriceOracle.sol\\\";\\n\\ncontract UnitrollerAdminStorage {\\n /**\\n * @notice Administrator for this contract\\n */\\n address public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address public pendingAdmin;\\n\\n /**\\n * @notice Active brains of Unitroller\\n */\\n address public comptrollerImplementation;\\n\\n /**\\n * @notice Pending brains of Unitroller\\n */\\n address public pendingComptrollerImplementation;\\n}\\n\\ncontract ComptrollerV1Storage is UnitrollerAdminStorage {\\n\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n PriceOracle public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives\\n */\\n uint public liquidationIncentiveMantissa;\\n\\n /**\\n * @notice Max number of assets a single account can participate in (borrow or use as collateral)\\n */\\n uint public maxAssets;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\\n */\\n mapping(address => CToken[]) public accountAssets;\\n\\n}\\n\\ncontract ComptrollerV2Storage is ComptrollerV1Storage {\\n struct Market {\\n /// @notice Whether or not this market is listed\\n bool isListed;\\n\\n /**\\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\\n * For instance, 0.9 to allow borrowing 90% of collateral value.\\n * Must be between 0 and 1, and stored as a mantissa.\\n */\\n uint collateralFactorMantissa;\\n\\n /// @notice Per-market mapping of \\\"accounts in this asset\\\"\\n mapping(address => bool) accountMembership;\\n\\n /// @notice Whether or not this market receives COMP\\n bool isComped;\\n }\\n\\n /**\\n * @notice Official mapping of cTokens -> Market metadata\\n * @dev Used e.g. to determine if a market is supported\\n */\\n mapping(address => Market) public markets;\\n\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n * Actions which allow users to remove their own assets cannot be paused.\\n * Liquidation / seizing / transfer can only be paused globally, not by market.\\n */\\n address public pauseGuardian;\\n bool public _mintGuardianPaused;\\n bool public _borrowGuardianPaused;\\n bool public transferGuardianPaused;\\n bool public seizeGuardianPaused;\\n mapping(address => bool) public mintGuardianPaused;\\n mapping(address => bool) public borrowGuardianPaused;\\n}\\n\\ncontract ComptrollerV3Storage is ComptrollerV2Storage {\\n struct CompMarketState {\\n /// @notice The market's last updated compBorrowIndex or compSupplyIndex\\n uint224 index;\\n\\n /// @notice The block number the index was last updated at\\n uint32 block;\\n }\\n\\n /// @notice A list of all markets\\n CToken[] public allMarkets;\\n\\n /// @notice The rate at which the flywheel distributes COMP, per block\\n uint public compRate;\\n\\n /// @notice The portion of compRate that each market currently receives\\n mapping(address => uint) public compSpeeds;\\n\\n /// @notice The COMP market supply state for each market\\n mapping(address => CompMarketState) public compSupplyState;\\n\\n /// @notice The COMP market borrow state for each market\\n mapping(address => CompMarketState) public compBorrowState;\\n\\n /// @notice The COMP borrow index for each market for each supplier as of the last time they accrued COMP\\n mapping(address => mapping(address => uint)) public compSupplierIndex;\\n\\n /// @notice The COMP borrow index for each market for each borrower as of the last time they accrued COMP\\n mapping(address => mapping(address => uint)) public compBorrowerIndex;\\n\\n /// @notice The COMP accrued but not yet transferred to each user\\n mapping(address => uint) public compAccrued;\\n}\\n\\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\\n // @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\\n address public borrowCapGuardian;\\n\\n // @notice Borrow caps enforced by borrowAllowed for each cToken address. Defaults to zero which corresponds to unlimited borrowing.\\n mapping(address => uint) public borrowCaps;\\n}\\n\\ncontract ComptrollerV5Storage is ComptrollerV4Storage {\\n /// @notice The portion of COMP that each contributor receives per block\\n mapping(address => uint) public compContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's COMP rewards have been allocated\\n mapping(address => uint) public lastContributorBlock;\\n}\\n\",\"keccak256\":\"0x5db970485549f493618b5e36bfd4d799d4f8701a136bf71ed6e0117e1ed8c254\"},\"contracts/EIP20Interface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title ERC 20 Token Standard Interface\\n * https://eips.ethereum.org/EIPS/eip-20\\n */\\ninterface EIP20Interface {\\n function name() external view returns (string memory);\\n function symbol() external view returns (string memory);\\n function decimals() external view returns (uint8);\\n\\n /**\\n * @notice Get the total number of tokens in circulation\\n * @return The supply of tokens\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @notice Gets the balance of the specified address\\n * @param owner The address from which the balance will be retrieved\\n * @return The balance\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transfer(address dst, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferFrom(address src, address dst, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (-1 means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (-1 means infinite)\\n */\\n function allowance(address owner, address spender) external view returns (uint256 remaining);\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n}\\n\",\"keccak256\":\"0xfd8ed2eac6d0b4d9ee6b32628ba68bae17544b66f190a5f7ce0c6ad024579dc8\"},\"contracts/EIP20NonStandardInterface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title EIP20NonStandardInterface\\n * @dev Version of ERC20 with no return values for `transfer` and `transferFrom`\\n * See https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\\n */\\ninterface EIP20NonStandardInterface {\\n\\n /**\\n * @notice Get the total number of tokens in circulation\\n * @return The supply of tokens\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @notice Gets the balance of the specified address\\n * @param owner The address from which the balance will be retrieved\\n * @return The balance\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n ///\\n /// !!!!!!!!!!!!!!\\n /// !!! NOTICE !!! `transfer` does not return a value, in violation of the ERC-20 specification\\n /// !!!!!!!!!!!!!!\\n ///\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n */\\n function transfer(address dst, uint256 amount) external;\\n\\n ///\\n /// !!!!!!!!!!!!!!\\n /// !!! NOTICE !!! `transferFrom` does not return a value, in violation of the ERC-20 specification\\n /// !!!!!!!!!!!!!!\\n ///\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n */\\n function transferFrom(address src, address dst, uint256 amount) external;\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent\\n */\\n function allowance(address owner, address spender) external view returns (uint256 remaining);\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n}\\n\",\"keccak256\":\"0x9719f12e4b80b51147ac195553a198cf8b0c516e7e4d04fc324a23ed15cbafb2\"},\"contracts/ErrorReporter.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\ncontract ComptrollerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\",\"keccak256\":\"0x5179afb1071c0fd555e5c1f1d2565f72dbe1740cc3dd02f6e52037f150afc5c9\"},\"contracts/Exponential.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CarefulMath.sol\\\";\\nimport \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @dev Legacy contract for compatibility reasons with existing contracts that still use MathError\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: rational}));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({mantissa: result}));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({mantissa: result}));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: scaledMantissa}));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: descaledMantissa}));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) pure internal returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({mantissa: 0}));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({mantissa: product}));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) pure internal returns (MathError, Exp memory) {\\n return mulExp(Exp({mantissa: a}), Exp({mantissa: b}));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) pure internal returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6ff054d65a0289dbb43c9f437d6909f9cf1207c9b8f984b3cb8e97a9de76a434\"},\"contracts/ExponentialNoError.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\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 Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) pure internal returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) pure internal returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) pure internal returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) pure internal returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) pure internal returns (uint224) {\\n require(n < 2**224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) pure internal returns (uint32) {\\n require(n < 2**32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: add_(a.mantissa, b.mantissa)});\\n }\\n\\n function add_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: add_(a.mantissa, b.mantissa)});\\n }\\n\\n function add_(uint a, uint b) pure internal returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: sub_(a.mantissa, b.mantissa)});\\n }\\n\\n function sub_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: sub_(a.mantissa, b.mantissa)});\\n }\\n\\n function sub_(uint a, uint b) pure internal returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: mul_(a.mantissa, b.mantissa) / expScale});\\n }\\n\\n function mul_(Exp memory a, uint b) pure internal returns (Exp memory) {\\n return Exp({mantissa: mul_(a.mantissa, b)});\\n }\\n\\n function mul_(uint a, Exp memory b) pure internal returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: mul_(a.mantissa, b.mantissa) / doubleScale});\\n }\\n\\n function mul_(Double memory a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: mul_(a.mantissa, b)});\\n }\\n\\n function mul_(uint a, Double memory b) pure internal returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) pure internal returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) pure internal 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) pure internal returns (Exp memory) {\\n return Exp({mantissa: div_(mul_(a.mantissa, expScale), b.mantissa)});\\n }\\n\\n function div_(Exp memory a, uint b) pure internal returns (Exp memory) {\\n return Exp({mantissa: div_(a.mantissa, b)});\\n }\\n\\n function div_(uint a, Exp memory b) pure internal returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa)});\\n }\\n\\n function div_(Double memory a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(a.mantissa, b)});\\n }\\n\\n function div_(uint a, Double memory b) pure internal returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) pure internal returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(mul_(a, doubleScale), b)});\\n }\\n}\\n\",\"keccak256\":\"0x7cb184b7cee71a5e707053dfba7eebbd46f11974004028100510ccce19b6694d\"},\"contracts/InterestRateModel.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Compound's InterestRateModel Interface\\n * @author Compound\\n */\\ncontract InterestRateModel {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint cash, uint borrows, uint reserves) external view returns (uint);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) external view returns (uint);\\n\\n}\\n\",\"keccak256\":\"0x929282d73c79e6d700ebe79f9fafc1e414b3848acff5a56d6740afd1dc908678\"},\"contracts/PriceOracle.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.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 cToken asset\\n * @param cToken The cToken to get the underlying price of\\n * @return The underlying asset price mantissa (scaled by 1e18).\\n * Zero means the price is unavailable.\\n */\\n function getUnderlyingPrice(CToken cToken) external view returns (uint);\\n}\\n\",\"keccak256\":\"0xe79ebc23bba508eb2479e7b3340abf566da1ab62131f106aee1aac3dc53816ef\"}},\"version\":1}" + }, + "contracts/ComptrollerStorage.sol:ComptrollerV5Storage": { + "abi": "[{\"constant\":true,\"inputs\":[],\"name\":\"_borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allMarkets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"borrowCapGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compAccrued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compBorrowState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compBorrowerIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compContributorSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSupplierIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSupplyState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"lastContributorBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"liquidationIncentiveMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"markets\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isComped\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"seizeGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"transferGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}]", + "bin": "608060405234801561001057600080fd5b50610783806100206000396000f3fe608060405234801561001057600080fd5b50600436106101cf5760003560e01c80638e8f294b11610104578063bea6b8b8116100a2578063dcfbc0c711610071578063dcfbc0c7146104d9578063e6653f3d146104e1578063e8755446146104e9578063f851a440146104f1576101cf565b8063bea6b8b814610433578063ca0af04314610459578063cc7ebdc414610487578063dce15449146104ad576101cf565b8063aa900754116100de578063aa900754146103ed578063ac0b0bb7146103f5578063b21be7fd146103fd578063bb82aa5e1461042b576101cf565b80638e8f294b1461037757806394b2294b146103bf578063986ab838146103c7576101cf565b806352d84d1e11610171578063731f0c2b1161014b578063731f0c2b1461031b5780637dc0d1d01461034157806387f76303146103495780638c57804e14610351576101cf565b806352d84d1e1461028a5780636b79c38d146102a75780636d154ea5146102f5576101cf565b806326782247116101ad57806326782247146102385780633c94786f146102405780634a5844321461025c5780634ada90af14610282576101cf565b80631d7b33d7146101d457806321af45691461020c57806324a3d62214610230575b600080fd5b6101fa600480360360208110156101ea57600080fd5b50356001600160a01b03166104f9565b60408051918252519081900360200190f35b61021461050b565b604080516001600160a01b039092168252519081900360200190f35b61021461051a565b610214610529565b610248610538565b604080519115158252519081900360200190f35b6101fa6004803603602081101561027257600080fd5b50356001600160a01b0316610548565b6101fa61055a565b610214600480360360208110156102a057600080fd5b5035610560565b6102cd600480360360208110156102bd57600080fd5b50356001600160a01b0316610587565b604080516001600160e01b03909316835263ffffffff90911660208301528051918290030190f35b6102486004803603602081101561030b57600080fd5b50356001600160a01b03166105b1565b6102486004803603602081101561033157600080fd5b50356001600160a01b03166105c6565b6102146105db565b6102486105ea565b6102cd6004803603602081101561036757600080fd5b50356001600160a01b03166105fa565b61039d6004803603602081101561038d57600080fd5b50356001600160a01b0316610624565b6040805193151584526020840192909252151582820152519081900360600190f35b6101fa61064a565b6101fa600480360360208110156103dd57600080fd5b50356001600160a01b0316610650565b6101fa610662565b610248610668565b6101fa6004803603604081101561041357600080fd5b506001600160a01b0381358116916020013516610678565b610214610695565b6101fa6004803603602081101561044957600080fd5b50356001600160a01b03166106a4565b6101fa6004803603604081101561046f57600080fd5b506001600160a01b03813581169160200135166106b6565b6101fa6004803603602081101561049d57600080fd5b50356001600160a01b03166106d3565b610214600480360360408110156104c357600080fd5b506001600160a01b0381351690602001356106e5565b61021461071a565b610248610729565b6101fa610739565b61021461073f565b600f6020526000908152604090205481565b6015546001600160a01b031681565b600a546001600160a01b031681565b6001546001600160a01b031681565b600a54600160a01b900460ff1681565b60166020526000908152604090205481565b60065481565b600d818154811061056d57fe5b6000918252602090912001546001600160a01b0316905081565b6010602052600090815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b600c6020526000908152604090205460ff1681565b600b6020526000908152604090205460ff1681565b6004546001600160a01b031681565b600a54600160b01b900460ff1681565b6011602052600090815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b60096020526000908152604090208054600182015460039092015460ff91821692911683565b60075481565b60176020526000908152604090205481565b600e5481565b600a54600160b81b900460ff1681565b601260209081526000928352604080842090915290825290205481565b6002546001600160a01b031681565b60186020526000908152604090205481565b601360209081526000928352604080842090915290825290205481565b60146020526000908152604090205481565b600860205281600052604060002081815481106106fe57fe5b6000918252602090912001546001600160a01b03169150829050565b6003546001600160a01b031681565b600a54600160a81b900460ff1681565b60055481565b6000546001600160a01b03168156fea265627a7a72315820744357a921ff973b50c59df9fb14a4fe83d6142889adae9fbe12c677a92eb85d64736f6c63430005100032", + "metadata": "{\"compiler\":{\"version\":\"0.5.16+commit.9c3226ce\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"constant\":true,\"inputs\":[],\"name\":\"_borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allMarkets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"borrowCapGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compAccrued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compBorrowState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compBorrowerIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compContributorSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSupplierIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSupplyState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"lastContributorBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"liquidationIncentiveMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"markets\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isComped\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"seizeGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"transferGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"methods\":{}},\"userdoc\":{\"methods\":{}}},\"settings\":{\"compilationTarget\":{\"contracts/ComptrollerStorage.sol\":\"ComptrollerV5Storage\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/CToken.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./CTokenInterfaces.sol\\\";\\nimport \\\"./ErrorReporter.sol\\\";\\nimport \\\"./Exponential.sol\\\";\\nimport \\\"./EIP20Interface.sol\\\";\\nimport \\\"./InterestRateModel.sol\\\";\\n\\n/**\\n * @title Compound's CToken Contract\\n * @notice Abstract base for CTokens\\n * @author Compound\\n */\\ncontract CToken is CTokenInterface, Exponential, TokenErrorReporter {\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_) public {\\n require(msg.sender == admin, \\\"only admin may initialize the market\\\");\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = getBlockNumber();\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Transfer `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = uint(-1);\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srcTokensNew;\\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, srcTokensNew) = 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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srcTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != uint(-1)) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n // unused function\\n // comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transfer(address dst, uint256 amount) external nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferFrom(address src, address dst, uint256 amount) external nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (-1 means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool) {\\n address src = msg.sender;\\n transferAllowances[src][spender] = amount;\\n emit Approval(src, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (-1 means infinite)\\n */\\n function allowance(address owner, address spender) external view returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external returns (uint) {\\n Exp memory exchangeRate = Exp({mantissa: exchangeRateCurrent()});\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n require(mErr == MathError.NO_ERROR, \\\"balance could not be calculated\\\");\\n return balance;\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view returns (uint, uint, uint, uint) {\\n uint cTokenBalance = accountTokens[account];\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), cTokenBalance, borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @dev Function to simply retrieve block number\\n * This exists mainly for inheriting test contracts to stub this result.\\n */\\n function getBlockNumber() internal view returns (uint) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this cToken\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view returns (uint) {\\n return interestRateModel.getBorrowRate(getCashPrior(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this cToken\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view returns (uint) {\\n return interestRateModel.getSupplyRate(getCashPrior(), totalBorrows, totalReserves, reserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n require(err == MathError.NO_ERROR, \\\"borrowBalanceStored: borrowBalanceStoredInternal failed\\\");\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return (error code, the calculated balance or 0 if error code is non-zero)\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the CToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n require(err == MathError.NO_ERROR, \\\"exchangeRateStored: exchangeRateStoredInternal failed\\\");\\n return result;\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the CToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return (error code, calculated exchange rate scaled by 1e18)\\n */\\n function exchangeRateStoredInternal() internal view returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows - totalReserves) / totalSupply\\n */\\n uint totalCash = getCashPrior();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Get cash balance of this cToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage.\\n */\\n function accrueInterest() public returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = getBlockNumber();\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = getCashPrior();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n require(mathErr == MathError.NO_ERROR, \\\"could not calculate block delta\\\");\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({mantissa: borrowRateMantissa}), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(Exp({mantissa: reserveFactorMantissa}), interestAccumulated, reservesPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives cTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n struct MintLocalVars {\\n Error err;\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives cTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, 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's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the cToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of cTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.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 cTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED\\\");\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\\");\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender redeems cTokens in exchange for the underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemTokens The number of cTokens to redeem into underlying\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemInternal(uint redeemTokens) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(msg.sender, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems cTokens in exchange for a specified amount of underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemAmount The amount of underlying to receive from redeeming cTokens\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemUnderlyingInternal(uint redeemAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(msg.sender, 0, redeemAmount);\\n }\\n\\n struct RedeemLocalVars {\\n Error err;\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n /**\\n * @notice User redeems cTokens in exchange for the underlying asset\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param redeemTokensIn The number of cTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming cTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemFresh(address payable redeemer, uint redeemTokensIn, uint redeemAmountIn) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr));\\n }\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(Exp({mantissa: vars.exchangeRateMantissa}), redeemTokensIn);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(redeemAmountIn, Exp({mantissa: vars.exchangeRateMantissa}));\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REDEEM_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDEEM_FRESHNESS_CHECK);\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDEEM_TRANSFER_OUT_NOT_POSSIBLE);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We invoke doTransferOut for the redeemer and the redeemAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(redeemer, vars.redeemAmount);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n /* We call the defense hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender borrows assets from the protocol to their own address\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function borrowInternal(uint borrowAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(msg.sender, borrowAmount);\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n /**\\n * @notice Users borrow assets from the protocol to their own address\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function borrowFresh(address payable borrower, uint borrowAmount) internal returns (uint) {\\n /* Fail if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.BORROW_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.BORROW_FRESHNESS_CHECK);\\n }\\n\\n /* Fail gracefully if protocol has insufficient underlying cash */\\n if (getCashPrior() < borrowAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.BORROW_CASH_NOT_AVAILABLE);\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We invoke doTransferOut for the borrower and the borrowAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(borrower, borrowAmount);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to borrower\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer the account paying off the borrow\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount the amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED\\\");\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED\\\");\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this cToken to be liquidated\\n * @param cTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) 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 = cTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, cTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this cToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param cTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowFresh(address liquidator, address borrower, uint repayAmount, CTokenInterface cTokenCollateral) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(address(this), address(cTokenCollateral), liquidator, borrower, repayAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify cTokenCollateral market's block number equals current block number */\\n if (cTokenCollateral.accrualBlockNumber() != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = -1 */\\n if (repayAmount == uint(-1)) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & 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(cTokenCollateral), actualRepayAmount);\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(cTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(cTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = cTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(cTokenCollateral), seizeTokens);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.liquidateBorrowVerify(address(this), address(cTokenCollateral), liquidator, borrower, actualRepayAmount, seizeTokens);\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another cToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed cToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of cTokens to seize\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function seize(address liquidator, address borrower, uint seizeTokens) external nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n struct SeizeInternalLocalVars {\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n uint liquidatorSeizeTokens;\\n uint protocolSeizeTokens;\\n uint protocolSeizeAmount;\\n uint exchangeRateMantissa;\\n uint totalReservesNew;\\n uint totalSupplyNew;\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another CToken.\\n * Its absolutely critical to use msg.sender as the seizer cToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed cToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of cTokens to seize\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function seizeInternal(address seizerToken, address liquidator, address borrower, uint seizeTokens) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n SeizeInternalLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (vars.mathErr, vars.borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(vars.mathErr));\\n }\\n\\n vars.protocolSeizeTokens = mul_(seizeTokens, Exp({mantissa: protocolSeizeShareMantissa}));\\n vars.liquidatorSeizeTokens = sub_(seizeTokens, vars.protocolSeizeTokens);\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n require(vars.mathErr == MathError.NO_ERROR, \\\"exchange rate math error\\\");\\n\\n vars.protocolSeizeAmount = mul_ScalarTruncate(Exp({mantissa: vars.exchangeRateMantissa}), vars.protocolSeizeTokens);\\n\\n vars.totalReservesNew = add_(totalReserves, vars.protocolSeizeAmount);\\n vars.totalSupplyNew = sub_(totalSupply, vars.protocolSeizeTokens);\\n\\n (vars.mathErr, vars.liquidatorTokensNew) = addUInt(accountTokens[liquidator], vars.liquidatorSeizeTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(vars.mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n totalReserves = vars.totalReservesNew;\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[borrower] = vars.borrowerTokensNew;\\n accountTokens[liquidator] = vars.liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, vars.liquidatorSeizeTokens);\\n emit Transfer(borrower, address(this), vars.protocolSeizeTokens);\\n emit ReservesAdded(address(this), vars.protocolSeizeAmount, vars.totalReservesNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n\\n /*** Admin Functions ***/\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPendingAdmin(address payable newPendingAdmin) external returns (uint) {\\n // Check caller = admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\\n }\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptAdmin() external returns (uint) {\\n // Check caller is pendingAdmin and pendingAdmin \\u2260 address(0)\\n if (msg.sender != pendingAdmin || msg.sender == address(0)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = address(0);\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setComptroller(ComptrollerInterface newComptroller) public returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_COMPTROLLER_OWNER_CHECK);\\n }\\n\\n ComptrollerInterface oldComptroller = comptroller;\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(oldComptroller, newComptroller);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh\\n * @dev Admin function to accrue interest and set a new reserve factor\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setReserveFactor(uint newReserveFactorMantissa) external nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\\n * @dev Admin function to set a new reserve factor\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_RESERVE_FACTOR_ADMIN_CHECK);\\n }\\n\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring from msg.sender\\n * @param addAmount Amount of addition to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to admin\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _reduceReserves(uint reduceAmount) external nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to admin\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _reduceReservesFresh(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's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n totalReservesNew = totalReserves - reduceAmount;\\n // We checked reduceAmount <= totalReserves above, so this should never revert.\\n require(totalReservesNew <= 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't be sure if side effects occurred.\\n doTransferOut(admin, reduceAmount);\\n\\n emit ReservesReduced(admin, reduceAmount, totalReservesNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Admin function to accrue interest and update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel);\\n }\\n\\n /**\\n * @notice updates the interest rate model (*requires fresh interest accrual)\\n * @dev Admin function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal returns (uint) {\\n\\n // Used to store old model for use in the event that is emitted on success\\n InterestRateModel oldInterestRateModel;\\n\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_INTEREST_RATE_MODEL_OWNER_CHECK);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Track the market's current interest rate model\\n oldInterestRateModel = interestRateModel;\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view returns (uint);\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure tather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal;\\n\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n}\\n\",\"keccak256\":\"0x436ec2e309682995f8a82dfdd9e8f75928599c10a9a680dddbee6c275014008d\"},\"contracts/CTokenInterfaces.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./InterestRateModel.sol\\\";\\nimport \\\"./EIP20NonStandardInterface.sol\\\";\\n\\ncontract CTokenStorage {\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-cToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModel public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first CTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping (address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping (address => mapping (address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Share of seized collateral that is added to reserves\\n */\\n uint public constant protocolSeizeShareMantissa = 2.8e16; //2.8%\\n\\n}\\n\\ncontract CTokenInterface is CTokenStorage {\\n /**\\n * @notice Indicator that this is a CToken contract (for inspection)\\n */\\n bool public constant isCToken = true;\\n\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(address liquidator, address borrower, uint repayAmount, address cTokenCollateral, uint seizeTokens);\\n\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin is updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(InterestRateModel oldInterestRateModel, InterestRateModel newInterestRateModel);\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address admin, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Failure event\\n */\\n event Failure(uint error, uint info, uint detail);\\n\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external returns (bool);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function approve(address spender, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function balanceOfUnderlying(address owner) external returns (uint);\\n function getAccountSnapshot(address account) external view returns (uint, uint, uint, uint);\\n function borrowRatePerBlock() external view returns (uint);\\n function supplyRatePerBlock() external view returns (uint);\\n function totalBorrowsCurrent() external returns (uint);\\n function borrowBalanceCurrent(address account) external returns (uint);\\n function borrowBalanceStored(address account) public view returns (uint);\\n function exchangeRateCurrent() public returns (uint);\\n function exchangeRateStored() public view returns (uint);\\n function getCash() external view returns (uint);\\n function accrueInterest() public returns (uint);\\n function seize(address liquidator, address borrower, uint seizeTokens) external returns (uint);\\n\\n\\n /*** Admin Functions ***/\\n\\n function _setPendingAdmin(address payable newPendingAdmin) external returns (uint);\\n function _acceptAdmin() external returns (uint);\\n function _setComptroller(ComptrollerInterface newComptroller) public returns (uint);\\n function _setReserveFactor(uint newReserveFactorMantissa) external returns (uint);\\n function _reduceReserves(uint reduceAmount) external returns (uint);\\n function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint);\\n}\\n\\ncontract CErc20Storage {\\n /**\\n * @notice Underlying asset for this CToken\\n */\\n address public underlying;\\n}\\n\\ncontract CErc20Interface is CErc20Storage {\\n\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n function redeem(uint redeemTokens) external returns (uint);\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n function borrow(uint borrowAmount) external returns (uint);\\n function repayBorrow(uint repayAmount) external returns (uint);\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n function liquidateBorrow(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) external returns (uint);\\n function sweepToken(EIP20NonStandardInterface token) external;\\n\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ncontract CDelegationStorage {\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n}\\n\\ncontract CDelegatorInterface is CDelegationStorage {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(address implementation_, bool allowResign, bytes memory becomeImplementationData) public;\\n}\\n\\ncontract CDelegateInterface is CDelegationStorage {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) public;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() public;\\n}\\n\",\"keccak256\":\"0x963bbf60b4c0b76900b3fcb2db8c8be634934b37b4113f1055e57a308197d21a\"},\"contracts/CarefulMath.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Careful Math\\n * @author Compound\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c = a * b;\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n return (MathError.NO_ERROR, a - b);\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c = a + b;\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\",\"keccak256\":\"0x0647348f27e41d22555d99eebd217dee02a4d737df6accd7cce5347a7487c7de\"},\"contracts/ComptrollerInterface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\ncontract ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n bool public constant isComptroller = true;\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata cTokens) external returns (uint[] memory);\\n function exitMarket(address cToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address cToken, address minter, uint mintAmount) external returns (uint);\\n function mintVerify(address cToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address cToken, address redeemer, uint redeemTokens) external returns (uint);\\n function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address cToken, address borrower, uint borrowAmount) external returns (uint);\\n function borrowVerify(address cToken, address borrower, uint borrowAmount) external;\\n\\n function repayBorrowAllowed(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount) external returns (uint);\\n function repayBorrowVerify(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex) external;\\n\\n function liquidateBorrowAllowed(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount) external returns (uint);\\n function liquidateBorrowVerify(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens) external;\\n\\n function seizeAllowed(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external returns (uint);\\n function seizeVerify(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external;\\n\\n function transferAllowed(address cToken, address src, address dst, uint transferTokens) external returns (uint);\\n function transferVerify(address cToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n uint repayAmount) external view returns (uint, uint);\\n}\\n\",\"keccak256\":\"0xede7670d2dd7b25d0187aecd2c28b7b5ca7d7c1bdac144fbedecf5d4bdd92a6b\"},\"contracts/ComptrollerStorage.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.sol\\\";\\nimport \\\"./PriceOracle.sol\\\";\\n\\ncontract UnitrollerAdminStorage {\\n /**\\n * @notice Administrator for this contract\\n */\\n address public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address public pendingAdmin;\\n\\n /**\\n * @notice Active brains of Unitroller\\n */\\n address public comptrollerImplementation;\\n\\n /**\\n * @notice Pending brains of Unitroller\\n */\\n address public pendingComptrollerImplementation;\\n}\\n\\ncontract ComptrollerV1Storage is UnitrollerAdminStorage {\\n\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n PriceOracle public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives\\n */\\n uint public liquidationIncentiveMantissa;\\n\\n /**\\n * @notice Max number of assets a single account can participate in (borrow or use as collateral)\\n */\\n uint public maxAssets;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\\n */\\n mapping(address => CToken[]) public accountAssets;\\n\\n}\\n\\ncontract ComptrollerV2Storage is ComptrollerV1Storage {\\n struct Market {\\n /// @notice Whether or not this market is listed\\n bool isListed;\\n\\n /**\\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\\n * For instance, 0.9 to allow borrowing 90% of collateral value.\\n * Must be between 0 and 1, and stored as a mantissa.\\n */\\n uint collateralFactorMantissa;\\n\\n /// @notice Per-market mapping of \\\"accounts in this asset\\\"\\n mapping(address => bool) accountMembership;\\n\\n /// @notice Whether or not this market receives COMP\\n bool isComped;\\n }\\n\\n /**\\n * @notice Official mapping of cTokens -> Market metadata\\n * @dev Used e.g. to determine if a market is supported\\n */\\n mapping(address => Market) public markets;\\n\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n * Actions which allow users to remove their own assets cannot be paused.\\n * Liquidation / seizing / transfer can only be paused globally, not by market.\\n */\\n address public pauseGuardian;\\n bool public _mintGuardianPaused;\\n bool public _borrowGuardianPaused;\\n bool public transferGuardianPaused;\\n bool public seizeGuardianPaused;\\n mapping(address => bool) public mintGuardianPaused;\\n mapping(address => bool) public borrowGuardianPaused;\\n}\\n\\ncontract ComptrollerV3Storage is ComptrollerV2Storage {\\n struct CompMarketState {\\n /// @notice The market's last updated compBorrowIndex or compSupplyIndex\\n uint224 index;\\n\\n /// @notice The block number the index was last updated at\\n uint32 block;\\n }\\n\\n /// @notice A list of all markets\\n CToken[] public allMarkets;\\n\\n /// @notice The rate at which the flywheel distributes COMP, per block\\n uint public compRate;\\n\\n /// @notice The portion of compRate that each market currently receives\\n mapping(address => uint) public compSpeeds;\\n\\n /// @notice The COMP market supply state for each market\\n mapping(address => CompMarketState) public compSupplyState;\\n\\n /// @notice The COMP market borrow state for each market\\n mapping(address => CompMarketState) public compBorrowState;\\n\\n /// @notice The COMP borrow index for each market for each supplier as of the last time they accrued COMP\\n mapping(address => mapping(address => uint)) public compSupplierIndex;\\n\\n /// @notice The COMP borrow index for each market for each borrower as of the last time they accrued COMP\\n mapping(address => mapping(address => uint)) public compBorrowerIndex;\\n\\n /// @notice The COMP accrued but not yet transferred to each user\\n mapping(address => uint) public compAccrued;\\n}\\n\\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\\n // @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\\n address public borrowCapGuardian;\\n\\n // @notice Borrow caps enforced by borrowAllowed for each cToken address. Defaults to zero which corresponds to unlimited borrowing.\\n mapping(address => uint) public borrowCaps;\\n}\\n\\ncontract ComptrollerV5Storage is ComptrollerV4Storage {\\n /// @notice The portion of COMP that each contributor receives per block\\n mapping(address => uint) public compContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's COMP rewards have been allocated\\n mapping(address => uint) public lastContributorBlock;\\n}\\n\",\"keccak256\":\"0x5db970485549f493618b5e36bfd4d799d4f8701a136bf71ed6e0117e1ed8c254\"},\"contracts/EIP20Interface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title ERC 20 Token Standard Interface\\n * https://eips.ethereum.org/EIPS/eip-20\\n */\\ninterface EIP20Interface {\\n function name() external view returns (string memory);\\n function symbol() external view returns (string memory);\\n function decimals() external view returns (uint8);\\n\\n /**\\n * @notice Get the total number of tokens in circulation\\n * @return The supply of tokens\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @notice Gets the balance of the specified address\\n * @param owner The address from which the balance will be retrieved\\n * @return The balance\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transfer(address dst, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferFrom(address src, address dst, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (-1 means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (-1 means infinite)\\n */\\n function allowance(address owner, address spender) external view returns (uint256 remaining);\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n}\\n\",\"keccak256\":\"0xfd8ed2eac6d0b4d9ee6b32628ba68bae17544b66f190a5f7ce0c6ad024579dc8\"},\"contracts/EIP20NonStandardInterface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title EIP20NonStandardInterface\\n * @dev Version of ERC20 with no return values for `transfer` and `transferFrom`\\n * See https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\\n */\\ninterface EIP20NonStandardInterface {\\n\\n /**\\n * @notice Get the total number of tokens in circulation\\n * @return The supply of tokens\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @notice Gets the balance of the specified address\\n * @param owner The address from which the balance will be retrieved\\n * @return The balance\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n ///\\n /// !!!!!!!!!!!!!!\\n /// !!! NOTICE !!! `transfer` does not return a value, in violation of the ERC-20 specification\\n /// !!!!!!!!!!!!!!\\n ///\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n */\\n function transfer(address dst, uint256 amount) external;\\n\\n ///\\n /// !!!!!!!!!!!!!!\\n /// !!! NOTICE !!! `transferFrom` does not return a value, in violation of the ERC-20 specification\\n /// !!!!!!!!!!!!!!\\n ///\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n */\\n function transferFrom(address src, address dst, uint256 amount) external;\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent\\n */\\n function allowance(address owner, address spender) external view returns (uint256 remaining);\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n}\\n\",\"keccak256\":\"0x9719f12e4b80b51147ac195553a198cf8b0c516e7e4d04fc324a23ed15cbafb2\"},\"contracts/ErrorReporter.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\ncontract ComptrollerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\",\"keccak256\":\"0x5179afb1071c0fd555e5c1f1d2565f72dbe1740cc3dd02f6e52037f150afc5c9\"},\"contracts/Exponential.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CarefulMath.sol\\\";\\nimport \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @dev Legacy contract for compatibility reasons with existing contracts that still use MathError\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: rational}));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({mantissa: result}));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({mantissa: result}));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: scaledMantissa}));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: descaledMantissa}));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) pure internal returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({mantissa: 0}));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({mantissa: product}));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) pure internal returns (MathError, Exp memory) {\\n return mulExp(Exp({mantissa: a}), Exp({mantissa: b}));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) pure internal returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6ff054d65a0289dbb43c9f437d6909f9cf1207c9b8f984b3cb8e97a9de76a434\"},\"contracts/ExponentialNoError.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\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 Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) pure internal returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) pure internal returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) pure internal returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) pure internal returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) pure internal returns (uint224) {\\n require(n < 2**224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) pure internal returns (uint32) {\\n require(n < 2**32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: add_(a.mantissa, b.mantissa)});\\n }\\n\\n function add_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: add_(a.mantissa, b.mantissa)});\\n }\\n\\n function add_(uint a, uint b) pure internal returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: sub_(a.mantissa, b.mantissa)});\\n }\\n\\n function sub_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: sub_(a.mantissa, b.mantissa)});\\n }\\n\\n function sub_(uint a, uint b) pure internal returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: mul_(a.mantissa, b.mantissa) / expScale});\\n }\\n\\n function mul_(Exp memory a, uint b) pure internal returns (Exp memory) {\\n return Exp({mantissa: mul_(a.mantissa, b)});\\n }\\n\\n function mul_(uint a, Exp memory b) pure internal returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: mul_(a.mantissa, b.mantissa) / doubleScale});\\n }\\n\\n function mul_(Double memory a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: mul_(a.mantissa, b)});\\n }\\n\\n function mul_(uint a, Double memory b) pure internal returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) pure internal returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) pure internal 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) pure internal returns (Exp memory) {\\n return Exp({mantissa: div_(mul_(a.mantissa, expScale), b.mantissa)});\\n }\\n\\n function div_(Exp memory a, uint b) pure internal returns (Exp memory) {\\n return Exp({mantissa: div_(a.mantissa, b)});\\n }\\n\\n function div_(uint a, Exp memory b) pure internal returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa)});\\n }\\n\\n function div_(Double memory a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(a.mantissa, b)});\\n }\\n\\n function div_(uint a, Double memory b) pure internal returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) pure internal returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(mul_(a, doubleScale), b)});\\n }\\n}\\n\",\"keccak256\":\"0x7cb184b7cee71a5e707053dfba7eebbd46f11974004028100510ccce19b6694d\"},\"contracts/InterestRateModel.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Compound's InterestRateModel Interface\\n * @author Compound\\n */\\ncontract InterestRateModel {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint cash, uint borrows, uint reserves) external view returns (uint);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) external view returns (uint);\\n\\n}\\n\",\"keccak256\":\"0x929282d73c79e6d700ebe79f9fafc1e414b3848acff5a56d6740afd1dc908678\"},\"contracts/PriceOracle.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.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 cToken asset\\n * @param cToken The cToken to get the underlying price of\\n * @return The underlying asset price mantissa (scaled by 1e18).\\n * Zero means the price is unavailable.\\n */\\n function getUnderlyingPrice(CToken cToken) external view returns (uint);\\n}\\n\",\"keccak256\":\"0xe79ebc23bba508eb2479e7b3340abf566da1ab62131f106aee1aac3dc53816ef\"}},\"version\":1}" + }, + "contracts/ComptrollerStorage.sol:UnitrollerAdminStorage": { + "abi": "[{\"constant\":true,\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}]", + "bin": "608060405234801561001057600080fd5b5060f08061001f6000396000f3fe6080604052348015600f57600080fd5b506004361060465760003560e01c80632678224714604b578063bb82aa5e14606d578063dcfbc0c7146073578063f851a440146079575b600080fd5b6051607f565b604080516001600160a01b039092168252519081900360200190f35b6051608e565b6051609d565b605160ac565b6001546001600160a01b031681565b6002546001600160a01b031681565b6003546001600160a01b031681565b6000546001600160a01b03168156fea265627a7a723158206295f2dec7fc6817f638801337f7b41f3f76351a90e9e14f3bf0e69e12f69ea564736f6c63430005100032", + "metadata": "{\"compiler\":{\"version\":\"0.5.16+commit.9c3226ce\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"constant\":true,\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"methods\":{}},\"userdoc\":{\"methods\":{}}},\"settings\":{\"compilationTarget\":{\"contracts/ComptrollerStorage.sol\":\"UnitrollerAdminStorage\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/CToken.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./CTokenInterfaces.sol\\\";\\nimport \\\"./ErrorReporter.sol\\\";\\nimport \\\"./Exponential.sol\\\";\\nimport \\\"./EIP20Interface.sol\\\";\\nimport \\\"./InterestRateModel.sol\\\";\\n\\n/**\\n * @title Compound's CToken Contract\\n * @notice Abstract base for CTokens\\n * @author Compound\\n */\\ncontract CToken is CTokenInterface, Exponential, TokenErrorReporter {\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_) public {\\n require(msg.sender == admin, \\\"only admin may initialize the market\\\");\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = getBlockNumber();\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Transfer `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = uint(-1);\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srcTokensNew;\\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, srcTokensNew) = 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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srcTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != uint(-1)) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n // unused function\\n // comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transfer(address dst, uint256 amount) external nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferFrom(address src, address dst, uint256 amount) external nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (-1 means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool) {\\n address src = msg.sender;\\n transferAllowances[src][spender] = amount;\\n emit Approval(src, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (-1 means infinite)\\n */\\n function allowance(address owner, address spender) external view returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external returns (uint) {\\n Exp memory exchangeRate = Exp({mantissa: exchangeRateCurrent()});\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n require(mErr == MathError.NO_ERROR, \\\"balance could not be calculated\\\");\\n return balance;\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view returns (uint, uint, uint, uint) {\\n uint cTokenBalance = accountTokens[account];\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), cTokenBalance, borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @dev Function to simply retrieve block number\\n * This exists mainly for inheriting test contracts to stub this result.\\n */\\n function getBlockNumber() internal view returns (uint) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this cToken\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view returns (uint) {\\n return interestRateModel.getBorrowRate(getCashPrior(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this cToken\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view returns (uint) {\\n return interestRateModel.getSupplyRate(getCashPrior(), totalBorrows, totalReserves, reserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n require(err == MathError.NO_ERROR, \\\"borrowBalanceStored: borrowBalanceStoredInternal failed\\\");\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return (error code, the calculated balance or 0 if error code is non-zero)\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the CToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n require(err == MathError.NO_ERROR, \\\"exchangeRateStored: exchangeRateStoredInternal failed\\\");\\n return result;\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the CToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return (error code, calculated exchange rate scaled by 1e18)\\n */\\n function exchangeRateStoredInternal() internal view returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows - totalReserves) / totalSupply\\n */\\n uint totalCash = getCashPrior();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Get cash balance of this cToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage.\\n */\\n function accrueInterest() public returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = getBlockNumber();\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = getCashPrior();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n require(mathErr == MathError.NO_ERROR, \\\"could not calculate block delta\\\");\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({mantissa: borrowRateMantissa}), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(Exp({mantissa: reserveFactorMantissa}), interestAccumulated, reservesPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives cTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n struct MintLocalVars {\\n Error err;\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives cTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, 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's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the cToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of cTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.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 cTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED\\\");\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\\");\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender redeems cTokens in exchange for the underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemTokens The number of cTokens to redeem into underlying\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemInternal(uint redeemTokens) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(msg.sender, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems cTokens in exchange for a specified amount of underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemAmount The amount of underlying to receive from redeeming cTokens\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemUnderlyingInternal(uint redeemAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(msg.sender, 0, redeemAmount);\\n }\\n\\n struct RedeemLocalVars {\\n Error err;\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n /**\\n * @notice User redeems cTokens in exchange for the underlying asset\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param redeemTokensIn The number of cTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming cTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemFresh(address payable redeemer, uint redeemTokensIn, uint redeemAmountIn) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr));\\n }\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(Exp({mantissa: vars.exchangeRateMantissa}), redeemTokensIn);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(redeemAmountIn, Exp({mantissa: vars.exchangeRateMantissa}));\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REDEEM_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDEEM_FRESHNESS_CHECK);\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDEEM_TRANSFER_OUT_NOT_POSSIBLE);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We invoke doTransferOut for the redeemer and the redeemAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(redeemer, vars.redeemAmount);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n /* We call the defense hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender borrows assets from the protocol to their own address\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function borrowInternal(uint borrowAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(msg.sender, borrowAmount);\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n /**\\n * @notice Users borrow assets from the protocol to their own address\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function borrowFresh(address payable borrower, uint borrowAmount) internal returns (uint) {\\n /* Fail if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.BORROW_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.BORROW_FRESHNESS_CHECK);\\n }\\n\\n /* Fail gracefully if protocol has insufficient underlying cash */\\n if (getCashPrior() < borrowAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.BORROW_CASH_NOT_AVAILABLE);\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We invoke doTransferOut for the borrower and the borrowAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(borrower, borrowAmount);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to borrower\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer the account paying off the borrow\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount the amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED\\\");\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED\\\");\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this cToken to be liquidated\\n * @param cTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) 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 = cTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, cTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this cToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param cTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowFresh(address liquidator, address borrower, uint repayAmount, CTokenInterface cTokenCollateral) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(address(this), address(cTokenCollateral), liquidator, borrower, repayAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify cTokenCollateral market's block number equals current block number */\\n if (cTokenCollateral.accrualBlockNumber() != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = -1 */\\n if (repayAmount == uint(-1)) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & 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(cTokenCollateral), actualRepayAmount);\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(cTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(cTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = cTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(cTokenCollateral), seizeTokens);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.liquidateBorrowVerify(address(this), address(cTokenCollateral), liquidator, borrower, actualRepayAmount, seizeTokens);\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another cToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed cToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of cTokens to seize\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function seize(address liquidator, address borrower, uint seizeTokens) external nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n struct SeizeInternalLocalVars {\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n uint liquidatorSeizeTokens;\\n uint protocolSeizeTokens;\\n uint protocolSeizeAmount;\\n uint exchangeRateMantissa;\\n uint totalReservesNew;\\n uint totalSupplyNew;\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another CToken.\\n * Its absolutely critical to use msg.sender as the seizer cToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed cToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of cTokens to seize\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function seizeInternal(address seizerToken, address liquidator, address borrower, uint seizeTokens) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n SeizeInternalLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (vars.mathErr, vars.borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(vars.mathErr));\\n }\\n\\n vars.protocolSeizeTokens = mul_(seizeTokens, Exp({mantissa: protocolSeizeShareMantissa}));\\n vars.liquidatorSeizeTokens = sub_(seizeTokens, vars.protocolSeizeTokens);\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n require(vars.mathErr == MathError.NO_ERROR, \\\"exchange rate math error\\\");\\n\\n vars.protocolSeizeAmount = mul_ScalarTruncate(Exp({mantissa: vars.exchangeRateMantissa}), vars.protocolSeizeTokens);\\n\\n vars.totalReservesNew = add_(totalReserves, vars.protocolSeizeAmount);\\n vars.totalSupplyNew = sub_(totalSupply, vars.protocolSeizeTokens);\\n\\n (vars.mathErr, vars.liquidatorTokensNew) = addUInt(accountTokens[liquidator], vars.liquidatorSeizeTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(vars.mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n totalReserves = vars.totalReservesNew;\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[borrower] = vars.borrowerTokensNew;\\n accountTokens[liquidator] = vars.liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, vars.liquidatorSeizeTokens);\\n emit Transfer(borrower, address(this), vars.protocolSeizeTokens);\\n emit ReservesAdded(address(this), vars.protocolSeizeAmount, vars.totalReservesNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n\\n /*** Admin Functions ***/\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPendingAdmin(address payable newPendingAdmin) external returns (uint) {\\n // Check caller = admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\\n }\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptAdmin() external returns (uint) {\\n // Check caller is pendingAdmin and pendingAdmin \\u2260 address(0)\\n if (msg.sender != pendingAdmin || msg.sender == address(0)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = address(0);\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setComptroller(ComptrollerInterface newComptroller) public returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_COMPTROLLER_OWNER_CHECK);\\n }\\n\\n ComptrollerInterface oldComptroller = comptroller;\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(oldComptroller, newComptroller);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh\\n * @dev Admin function to accrue interest and set a new reserve factor\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setReserveFactor(uint newReserveFactorMantissa) external nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\\n * @dev Admin function to set a new reserve factor\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_RESERVE_FACTOR_ADMIN_CHECK);\\n }\\n\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring from msg.sender\\n * @param addAmount Amount of addition to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to admin\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _reduceReserves(uint reduceAmount) external nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to admin\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _reduceReservesFresh(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's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n totalReservesNew = totalReserves - reduceAmount;\\n // We checked reduceAmount <= totalReserves above, so this should never revert.\\n require(totalReservesNew <= 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't be sure if side effects occurred.\\n doTransferOut(admin, reduceAmount);\\n\\n emit ReservesReduced(admin, reduceAmount, totalReservesNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Admin function to accrue interest and update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel);\\n }\\n\\n /**\\n * @notice updates the interest rate model (*requires fresh interest accrual)\\n * @dev Admin function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal returns (uint) {\\n\\n // Used to store old model for use in the event that is emitted on success\\n InterestRateModel oldInterestRateModel;\\n\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_INTEREST_RATE_MODEL_OWNER_CHECK);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Track the market's current interest rate model\\n oldInterestRateModel = interestRateModel;\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view returns (uint);\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure tather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal;\\n\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n}\\n\",\"keccak256\":\"0x436ec2e309682995f8a82dfdd9e8f75928599c10a9a680dddbee6c275014008d\"},\"contracts/CTokenInterfaces.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./InterestRateModel.sol\\\";\\nimport \\\"./EIP20NonStandardInterface.sol\\\";\\n\\ncontract CTokenStorage {\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-cToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModel public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first CTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping (address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping (address => mapping (address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Share of seized collateral that is added to reserves\\n */\\n uint public constant protocolSeizeShareMantissa = 2.8e16; //2.8%\\n\\n}\\n\\ncontract CTokenInterface is CTokenStorage {\\n /**\\n * @notice Indicator that this is a CToken contract (for inspection)\\n */\\n bool public constant isCToken = true;\\n\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(address liquidator, address borrower, uint repayAmount, address cTokenCollateral, uint seizeTokens);\\n\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin is updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(InterestRateModel oldInterestRateModel, InterestRateModel newInterestRateModel);\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address admin, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Failure event\\n */\\n event Failure(uint error, uint info, uint detail);\\n\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external returns (bool);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function approve(address spender, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function balanceOfUnderlying(address owner) external returns (uint);\\n function getAccountSnapshot(address account) external view returns (uint, uint, uint, uint);\\n function borrowRatePerBlock() external view returns (uint);\\n function supplyRatePerBlock() external view returns (uint);\\n function totalBorrowsCurrent() external returns (uint);\\n function borrowBalanceCurrent(address account) external returns (uint);\\n function borrowBalanceStored(address account) public view returns (uint);\\n function exchangeRateCurrent() public returns (uint);\\n function exchangeRateStored() public view returns (uint);\\n function getCash() external view returns (uint);\\n function accrueInterest() public returns (uint);\\n function seize(address liquidator, address borrower, uint seizeTokens) external returns (uint);\\n\\n\\n /*** Admin Functions ***/\\n\\n function _setPendingAdmin(address payable newPendingAdmin) external returns (uint);\\n function _acceptAdmin() external returns (uint);\\n function _setComptroller(ComptrollerInterface newComptroller) public returns (uint);\\n function _setReserveFactor(uint newReserveFactorMantissa) external returns (uint);\\n function _reduceReserves(uint reduceAmount) external returns (uint);\\n function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint);\\n}\\n\\ncontract CErc20Storage {\\n /**\\n * @notice Underlying asset for this CToken\\n */\\n address public underlying;\\n}\\n\\ncontract CErc20Interface is CErc20Storage {\\n\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n function redeem(uint redeemTokens) external returns (uint);\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n function borrow(uint borrowAmount) external returns (uint);\\n function repayBorrow(uint repayAmount) external returns (uint);\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n function liquidateBorrow(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) external returns (uint);\\n function sweepToken(EIP20NonStandardInterface token) external;\\n\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ncontract CDelegationStorage {\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n}\\n\\ncontract CDelegatorInterface is CDelegationStorage {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(address implementation_, bool allowResign, bytes memory becomeImplementationData) public;\\n}\\n\\ncontract CDelegateInterface is CDelegationStorage {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) public;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() public;\\n}\\n\",\"keccak256\":\"0x963bbf60b4c0b76900b3fcb2db8c8be634934b37b4113f1055e57a308197d21a\"},\"contracts/CarefulMath.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Careful Math\\n * @author Compound\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c = a * b;\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n return (MathError.NO_ERROR, a - b);\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c = a + b;\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\",\"keccak256\":\"0x0647348f27e41d22555d99eebd217dee02a4d737df6accd7cce5347a7487c7de\"},\"contracts/ComptrollerInterface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\ncontract ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n bool public constant isComptroller = true;\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata cTokens) external returns (uint[] memory);\\n function exitMarket(address cToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address cToken, address minter, uint mintAmount) external returns (uint);\\n function mintVerify(address cToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address cToken, address redeemer, uint redeemTokens) external returns (uint);\\n function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address cToken, address borrower, uint borrowAmount) external returns (uint);\\n function borrowVerify(address cToken, address borrower, uint borrowAmount) external;\\n\\n function repayBorrowAllowed(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount) external returns (uint);\\n function repayBorrowVerify(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex) external;\\n\\n function liquidateBorrowAllowed(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount) external returns (uint);\\n function liquidateBorrowVerify(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens) external;\\n\\n function seizeAllowed(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external returns (uint);\\n function seizeVerify(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external;\\n\\n function transferAllowed(address cToken, address src, address dst, uint transferTokens) external returns (uint);\\n function transferVerify(address cToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n uint repayAmount) external view returns (uint, uint);\\n}\\n\",\"keccak256\":\"0xede7670d2dd7b25d0187aecd2c28b7b5ca7d7c1bdac144fbedecf5d4bdd92a6b\"},\"contracts/ComptrollerStorage.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.sol\\\";\\nimport \\\"./PriceOracle.sol\\\";\\n\\ncontract UnitrollerAdminStorage {\\n /**\\n * @notice Administrator for this contract\\n */\\n address public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address public pendingAdmin;\\n\\n /**\\n * @notice Active brains of Unitroller\\n */\\n address public comptrollerImplementation;\\n\\n /**\\n * @notice Pending brains of Unitroller\\n */\\n address public pendingComptrollerImplementation;\\n}\\n\\ncontract ComptrollerV1Storage is UnitrollerAdminStorage {\\n\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n PriceOracle public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives\\n */\\n uint public liquidationIncentiveMantissa;\\n\\n /**\\n * @notice Max number of assets a single account can participate in (borrow or use as collateral)\\n */\\n uint public maxAssets;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\\n */\\n mapping(address => CToken[]) public accountAssets;\\n\\n}\\n\\ncontract ComptrollerV2Storage is ComptrollerV1Storage {\\n struct Market {\\n /// @notice Whether or not this market is listed\\n bool isListed;\\n\\n /**\\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\\n * For instance, 0.9 to allow borrowing 90% of collateral value.\\n * Must be between 0 and 1, and stored as a mantissa.\\n */\\n uint collateralFactorMantissa;\\n\\n /// @notice Per-market mapping of \\\"accounts in this asset\\\"\\n mapping(address => bool) accountMembership;\\n\\n /// @notice Whether or not this market receives COMP\\n bool isComped;\\n }\\n\\n /**\\n * @notice Official mapping of cTokens -> Market metadata\\n * @dev Used e.g. to determine if a market is supported\\n */\\n mapping(address => Market) public markets;\\n\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n * Actions which allow users to remove their own assets cannot be paused.\\n * Liquidation / seizing / transfer can only be paused globally, not by market.\\n */\\n address public pauseGuardian;\\n bool public _mintGuardianPaused;\\n bool public _borrowGuardianPaused;\\n bool public transferGuardianPaused;\\n bool public seizeGuardianPaused;\\n mapping(address => bool) public mintGuardianPaused;\\n mapping(address => bool) public borrowGuardianPaused;\\n}\\n\\ncontract ComptrollerV3Storage is ComptrollerV2Storage {\\n struct CompMarketState {\\n /// @notice The market's last updated compBorrowIndex or compSupplyIndex\\n uint224 index;\\n\\n /// @notice The block number the index was last updated at\\n uint32 block;\\n }\\n\\n /// @notice A list of all markets\\n CToken[] public allMarkets;\\n\\n /// @notice The rate at which the flywheel distributes COMP, per block\\n uint public compRate;\\n\\n /// @notice The portion of compRate that each market currently receives\\n mapping(address => uint) public compSpeeds;\\n\\n /// @notice The COMP market supply state for each market\\n mapping(address => CompMarketState) public compSupplyState;\\n\\n /// @notice The COMP market borrow state for each market\\n mapping(address => CompMarketState) public compBorrowState;\\n\\n /// @notice The COMP borrow index for each market for each supplier as of the last time they accrued COMP\\n mapping(address => mapping(address => uint)) public compSupplierIndex;\\n\\n /// @notice The COMP borrow index for each market for each borrower as of the last time they accrued COMP\\n mapping(address => mapping(address => uint)) public compBorrowerIndex;\\n\\n /// @notice The COMP accrued but not yet transferred to each user\\n mapping(address => uint) public compAccrued;\\n}\\n\\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\\n // @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\\n address public borrowCapGuardian;\\n\\n // @notice Borrow caps enforced by borrowAllowed for each cToken address. Defaults to zero which corresponds to unlimited borrowing.\\n mapping(address => uint) public borrowCaps;\\n}\\n\\ncontract ComptrollerV5Storage is ComptrollerV4Storage {\\n /// @notice The portion of COMP that each contributor receives per block\\n mapping(address => uint) public compContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's COMP rewards have been allocated\\n mapping(address => uint) public lastContributorBlock;\\n}\\n\",\"keccak256\":\"0x5db970485549f493618b5e36bfd4d799d4f8701a136bf71ed6e0117e1ed8c254\"},\"contracts/EIP20Interface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title ERC 20 Token Standard Interface\\n * https://eips.ethereum.org/EIPS/eip-20\\n */\\ninterface EIP20Interface {\\n function name() external view returns (string memory);\\n function symbol() external view returns (string memory);\\n function decimals() external view returns (uint8);\\n\\n /**\\n * @notice Get the total number of tokens in circulation\\n * @return The supply of tokens\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @notice Gets the balance of the specified address\\n * @param owner The address from which the balance will be retrieved\\n * @return The balance\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transfer(address dst, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferFrom(address src, address dst, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (-1 means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (-1 means infinite)\\n */\\n function allowance(address owner, address spender) external view returns (uint256 remaining);\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n}\\n\",\"keccak256\":\"0xfd8ed2eac6d0b4d9ee6b32628ba68bae17544b66f190a5f7ce0c6ad024579dc8\"},\"contracts/EIP20NonStandardInterface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title EIP20NonStandardInterface\\n * @dev Version of ERC20 with no return values for `transfer` and `transferFrom`\\n * See https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\\n */\\ninterface EIP20NonStandardInterface {\\n\\n /**\\n * @notice Get the total number of tokens in circulation\\n * @return The supply of tokens\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @notice Gets the balance of the specified address\\n * @param owner The address from which the balance will be retrieved\\n * @return The balance\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n ///\\n /// !!!!!!!!!!!!!!\\n /// !!! NOTICE !!! `transfer` does not return a value, in violation of the ERC-20 specification\\n /// !!!!!!!!!!!!!!\\n ///\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n */\\n function transfer(address dst, uint256 amount) external;\\n\\n ///\\n /// !!!!!!!!!!!!!!\\n /// !!! NOTICE !!! `transferFrom` does not return a value, in violation of the ERC-20 specification\\n /// !!!!!!!!!!!!!!\\n ///\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n */\\n function transferFrom(address src, address dst, uint256 amount) external;\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent\\n */\\n function allowance(address owner, address spender) external view returns (uint256 remaining);\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n}\\n\",\"keccak256\":\"0x9719f12e4b80b51147ac195553a198cf8b0c516e7e4d04fc324a23ed15cbafb2\"},\"contracts/ErrorReporter.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\ncontract ComptrollerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\",\"keccak256\":\"0x5179afb1071c0fd555e5c1f1d2565f72dbe1740cc3dd02f6e52037f150afc5c9\"},\"contracts/Exponential.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CarefulMath.sol\\\";\\nimport \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @dev Legacy contract for compatibility reasons with existing contracts that still use MathError\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: rational}));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({mantissa: result}));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({mantissa: result}));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: scaledMantissa}));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: descaledMantissa}));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) pure internal returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({mantissa: 0}));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({mantissa: product}));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) pure internal returns (MathError, Exp memory) {\\n return mulExp(Exp({mantissa: a}), Exp({mantissa: b}));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) pure internal returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6ff054d65a0289dbb43c9f437d6909f9cf1207c9b8f984b3cb8e97a9de76a434\"},\"contracts/ExponentialNoError.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\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 Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) pure internal returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) pure internal returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) pure internal returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) pure internal returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) pure internal returns (uint224) {\\n require(n < 2**224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) pure internal returns (uint32) {\\n require(n < 2**32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: add_(a.mantissa, b.mantissa)});\\n }\\n\\n function add_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: add_(a.mantissa, b.mantissa)});\\n }\\n\\n function add_(uint a, uint b) pure internal returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: sub_(a.mantissa, b.mantissa)});\\n }\\n\\n function sub_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: sub_(a.mantissa, b.mantissa)});\\n }\\n\\n function sub_(uint a, uint b) pure internal returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: mul_(a.mantissa, b.mantissa) / expScale});\\n }\\n\\n function mul_(Exp memory a, uint b) pure internal returns (Exp memory) {\\n return Exp({mantissa: mul_(a.mantissa, b)});\\n }\\n\\n function mul_(uint a, Exp memory b) pure internal returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: mul_(a.mantissa, b.mantissa) / doubleScale});\\n }\\n\\n function mul_(Double memory a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: mul_(a.mantissa, b)});\\n }\\n\\n function mul_(uint a, Double memory b) pure internal returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) pure internal returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) pure internal 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) pure internal returns (Exp memory) {\\n return Exp({mantissa: div_(mul_(a.mantissa, expScale), b.mantissa)});\\n }\\n\\n function div_(Exp memory a, uint b) pure internal returns (Exp memory) {\\n return Exp({mantissa: div_(a.mantissa, b)});\\n }\\n\\n function div_(uint a, Exp memory b) pure internal returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa)});\\n }\\n\\n function div_(Double memory a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(a.mantissa, b)});\\n }\\n\\n function div_(uint a, Double memory b) pure internal returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) pure internal returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(mul_(a, doubleScale), b)});\\n }\\n}\\n\",\"keccak256\":\"0x7cb184b7cee71a5e707053dfba7eebbd46f11974004028100510ccce19b6694d\"},\"contracts/InterestRateModel.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Compound's InterestRateModel Interface\\n * @author Compound\\n */\\ncontract InterestRateModel {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint cash, uint borrows, uint reserves) external view returns (uint);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) external view returns (uint);\\n\\n}\\n\",\"keccak256\":\"0x929282d73c79e6d700ebe79f9fafc1e414b3848acff5a56d6740afd1dc908678\"},\"contracts/PriceOracle.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.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 cToken asset\\n * @param cToken The cToken to get the underlying price of\\n * @return The underlying asset price mantissa (scaled by 1e18).\\n * Zero means the price is unavailable.\\n */\\n function getUnderlyingPrice(CToken cToken) external view returns (uint);\\n}\\n\",\"keccak256\":\"0xe79ebc23bba508eb2479e7b3340abf566da1ab62131f106aee1aac3dc53816ef\"}},\"version\":1}" + }, + "contracts/LegacyInterestRateModel.sol:LegacyInterestRateModel": { + "abi": "[{\"constant\":true,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"cash\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserves\",\"type\":\"uint256\"}],\"name\":\"getBorrowRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"cash\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"getSupplyRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"isInterestRateModel\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}]", + "bin": "", + "metadata": "{\"compiler\":{\"version\":\"0.5.16+commit.9c3226ce\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"constant\":true,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"cash\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserves\",\"type\":\"uint256\"}],\"name\":\"getBorrowRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"cash\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"getSupplyRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"isInterestRateModel\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Compound (modified by Arr00)\",\"methods\":{\"getBorrowRate(uint256,uint256,uint256)\":{\"params\":{\"borrows\":\"The total amount of borrows the market has outstanding\",\"cash\":\"The total amount of cash the market has\",\"reserves\":\"The total amount of reserves the market has\"},\"return\":\"error code (0 = no error), The borrow rate per block (as a percentage, and scaled by 1e18)\"},\"getSupplyRate(uint256,uint256,uint256,uint256)\":{\"params\":{\"borrows\":\"The total amount of borrows the market has outstanding\",\"cash\":\"The total amount of cash the market has\",\"reserveFactorMantissa\":\"The current reserve factor the market has\",\"reserves\":\"The total amount of reserves the market has\"},\"return\":\"The supply rate per block (as a percentage, and scaled by 1e18)\"}},\"title\":\"Compound's Legacy InterestRateModel Interface\"},\"userdoc\":{\"methods\":{\"getBorrowRate(uint256,uint256,uint256)\":{\"notice\":\"Calculates the current borrow interest rate per block\"},\"getSupplyRate(uint256,uint256,uint256,uint256)\":{\"notice\":\"Calculates the current supply interest rate per block\"}}}},\"settings\":{\"compilationTarget\":{\"contracts/LegacyInterestRateModel.sol\":\"LegacyInterestRateModel\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/LegacyInterestRateModel.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Compound's Legacy InterestRateModel Interface\\n * @author Compound (modified by Arr00)\\n */\\ncontract LegacyInterestRateModel {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @return error code (0 = no error), 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,uint);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) external view returns (uint);\\n\\n}\\n\",\"keccak256\":\"0x161a2e17aa46c4a2fbd4438f732f22825fddd71330a46200093b16f81b7d4732\"}},\"version\":1}" + }, + "contracts/LegacyJumpRateModelV2.sol:LegacyJumpRateModelV2": { + "abi": "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"baseRatePerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"multiplierPerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"jumpMultiplierPerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"kink_\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"owner_\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"baseRatePerBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"multiplierPerBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"jumpMultiplierPerBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"kink\",\"type\":\"uint256\"}],\"name\":\"NewInterestParams\",\"type\":\"event\"},{\"constant\":true,\"inputs\":[],\"name\":\"baseRatePerBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"blocksPerYear\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"cash\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserves\",\"type\":\"uint256\"}],\"name\":\"getBorrowRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"cash\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"getSupplyRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"isInterestRateModel\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"jumpMultiplierPerBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"kink\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"multiplierPerBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"baseRatePerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"multiplierPerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"jumpMultiplierPerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"kink_\",\"type\":\"uint256\"}],\"name\":\"updateJumpRateModel\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"cash\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserves\",\"type\":\"uint256\"}],\"name\":\"utilizationRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"pure\",\"type\":\"function\"}]", + "bin": "608060405234801561001057600080fd5b50604051610a8a380380610a8a833981810160405260a081101561003357600080fd5b508051602082015160408301516060840151608090940151600080546001600160a01b0319166001600160a01b03831617905592939192909190848484848461007e8585858561008d565b505050505050505050506102bc565b6100a7622014808561017060201b6105e41790919060201c565b6002556100f66100c562201480836101c1602090811b61058b17901c565b6100e4670de0b6b3a7640000866101c160201b61058b1790919060201c565b61017060201b6105e41790919060201c565b6001556101118262201480610170602090811b6105e417901c565b60038190556004829055600254600154604080519283526020830191909152818101929092526060810183905290517f6960ab234c7ef4b0c9197100f5393cfcde7c453ac910a27bd2000aa1dd4c068d9181900360800190a150505050565b60006101b883836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525061021a60201b60201c565b90505b92915050565b6000826101d0575060006101bb565b828202828482816101dd57fe5b04146101b85760405162461bcd60e51b8152600401808060200182810382526021815260200180610a696021913960400191505060405180910390fd5b600081836102a65760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561026b578181015183820152602001610253565b50505050905090810190601f1680156102985780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385816102b257fe5b0495945050505050565b61079e806102cb6000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c80638da5cb5b116100715780638da5cb5b14610180578063a385fb96146101a4578063b8168816146101ac578063b9f9850a146101db578063f14039de146101e3578063fd2da339146101eb576100a9565b806315f24053146100ae5780632037f3e7146100f05780632191f92a146101215780636e71e2d81461013d5780638726bb8914610178575b600080fd5b6100d7600480360360608110156100c457600080fd5b50803590602081013590604001356101f3565b6040805192835260208301919091528051918290030190f35b61011f6004803603608081101561010657600080fd5b508035906020810135906040810135906060013561020f565b005b61012961026a565b604080519115158252519081900360200190f35b6101666004803603606081101561015357600080fd5b508035906020810135906040013561026f565b60408051918252519081900360200190f35b6101666102cf565b6101886102d5565b604080516001600160a01b039092168252519081900360200190f35b6101666102e4565b610166600480360360808110156101c257600080fd5b50803590602081013590604081013590606001356102eb565b61016661036a565b610166610370565b610166610376565b600080600061020386868661037c565b90969095509350505050565b6000546001600160a01b031633146102585760405162461bcd60e51b81526004018080602001828103825260268152602001806107446026913960400191505060405180910390fd5b61026484848484610445565b50505050565b600181565b60008261027e575060006102c8565b6102c56102a183610295878763ffffffff6104e616565b9063ffffffff61054916565b6102b985670de0b6b3a764000063ffffffff61058b16565b9063ffffffff6105e416565b90505b9392505050565b60015481565b6000546001600160a01b031681565b6220148081565b600080610306670de0b6b3a76400008463ffffffff61054916565b9050600061031587878761037c565b90506000610335670de0b6b3a76400006102b9848663ffffffff61058b16565b905061035e670de0b6b3a76400006102b9836103528c8c8c61026f565b9063ffffffff61058b16565b98975050505050505050565b60035481565b60025481565b60045481565b60008061038a85858561026f565b905060045481116103d0576103c86002546103bc670de0b6b3a76400006102b96001548661058b90919063ffffffff16565b9063ffffffff6104e616565b9150506102c8565b60006103fb6002546103bc670de0b6b3a76400006102b960015460045461058b90919063ffffffff16565b905060006104146004548461054990919063ffffffff16565b905061043b826103bc670de0b6b3a76400006102b96003548661058b90919063ffffffff16565b93505050506102c8565b610458846220148063ffffffff6105e416565b6002556104716102a1622014808363ffffffff61058b16565b600155610487826220148063ffffffff6105e416565b60038190556004829055600254600154604080519283526020830191909152818101929092526060810183905290517f6960ab234c7ef4b0c9197100f5393cfcde7c453ac910a27bd2000aa1dd4c068d9181900360800190a150505050565b600082820183811015610540576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b90505b92915050565b600061054083836040518060400160405280601f81526020017f536166654d6174683a207375627472616374696f6e20756e646572666c6f7700815250610626565b60008261059a57506000610543565b828202828482816105a757fe5b04146105405760405162461bcd60e51b81526004018080602001828103825260218152602001806107236021913960400191505060405180910390fd5b600061054083836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506106bd565b600081848411156106b55760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561067a578181015183820152602001610662565b50505050905090810190601f1680156106a75780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6000818361070c5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561067a578181015183820152602001610662565b50600083858161071857fe5b049594505050505056fe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f776f6e6c7920746865206f776e6572206d61792063616c6c20746869732066756e6374696f6e2ea265627a7a723158202a65ab318cfcb6ea8705b52bd314ac966fb421eca72b8e687dd2dd29d584a6e964736f6c63430005100032536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77", + "metadata": "{\"compiler\":{\"version\":\"0.5.16+commit.9c3226ce\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"baseRatePerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"multiplierPerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"jumpMultiplierPerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"kink_\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"owner_\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"baseRatePerBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"multiplierPerBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"jumpMultiplierPerBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"kink\",\"type\":\"uint256\"}],\"name\":\"NewInterestParams\",\"type\":\"event\"},{\"constant\":true,\"inputs\":[],\"name\":\"baseRatePerBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"blocksPerYear\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"cash\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserves\",\"type\":\"uint256\"}],\"name\":\"getBorrowRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"cash\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"getSupplyRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"isInterestRateModel\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"jumpMultiplierPerBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"kink\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"multiplierPerBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"baseRatePerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"multiplierPerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"jumpMultiplierPerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"kink_\",\"type\":\"uint256\"}],\"name\":\"updateJumpRateModel\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"cash\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserves\",\"type\":\"uint256\"}],\"name\":\"utilizationRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Arr00\",\"methods\":{\"getBorrowRate(uint256,uint256,uint256)\":{\"params\":{\"borrows\":\"The amount of borrows in the market\",\"cash\":\"The amount of cash in the market\",\"reserves\":\"The amount of reserves in the market\"},\"return\":\"(Error, The borrow rate percentage per block as a mantissa (scaled by 1e18))\"},\"getSupplyRate(uint256,uint256,uint256,uint256)\":{\"params\":{\"borrows\":\"The amount of borrows in the market\",\"cash\":\"The amount of cash in the market\",\"reserveFactorMantissa\":\"The current reserve factor for the market\",\"reserves\":\"The amount of reserves in the market\"},\"return\":\"The supply rate percentage per block as a mantissa (scaled by 1e18)\"},\"updateJumpRateModel(uint256,uint256,uint256,uint256)\":{\"params\":{\"baseRatePerYear\":\"The approximate target base APR, as a mantissa (scaled by 1e18)\",\"jumpMultiplierPerYear\":\"The multiplierPerBlock after hitting a specified utilization point\",\"kink_\":\"The utilization point at which the jump multiplier is applied\",\"multiplierPerYear\":\"The rate of increase in interest rate wrt utilization (scaled by 1e18)\"}},\"utilizationRate(uint256,uint256,uint256)\":{\"params\":{\"borrows\":\"The amount of borrows in the market\",\"cash\":\"The amount of cash in the market\",\"reserves\":\"The amount of reserves in the market (currently unused)\"},\"return\":\"The utilization rate as a mantissa between [0, 1e18]\"}},\"title\":\"Compound's JumpRateModel Contract V2 for legacy cTokens\"},\"userdoc\":{\"methods\":{\"getBorrowRate(uint256,uint256,uint256)\":{\"notice\":\"Calculates the current borrow rate per block, with the error code expected by the market\"},\"getSupplyRate(uint256,uint256,uint256,uint256)\":{\"notice\":\"Calculates the current supply rate per block\"},\"updateJumpRateModel(uint256,uint256,uint256,uint256)\":{\"notice\":\"Update the parameters of the interest rate model (only callable by owner, i.e. Timelock)\"},\"utilizationRate(uint256,uint256,uint256)\":{\"notice\":\"Calculates the utilization rate of the market: `borrows / (cash + borrows - reserves)`\"}},\"notice\":\"Supports only legacy cTokens\"}},\"settings\":{\"compilationTarget\":{\"contracts/LegacyJumpRateModelV2.sol\":\"LegacyJumpRateModelV2\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/BaseJumpRateModelV2.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./SafeMath.sol\\\";\\n\\n/**\\n * @title Logic for Compound's JumpRateModel Contract V2.\\n * @author Compound (modified by Dharma Labs, refactored by Arr00)\\n * @notice Version 2 modifies Version 1 by enabling updateable parameters.\\n */\\ncontract BaseJumpRateModelV2 {\\n using SafeMath for uint;\\n\\n event NewInterestParams(uint baseRatePerBlock, uint multiplierPerBlock, uint jumpMultiplierPerBlock, uint kink);\\n\\n /**\\n * @notice The address of the owner, i.e. the Timelock contract, which can update parameters directly\\n */\\n address public owner;\\n\\n /**\\n * @notice The approximate number of blocks per year that is assumed by the interest rate model\\n */\\n uint public constant blocksPerYear = 2102400;\\n\\n /**\\n * @notice The multiplier of utilization rate that gives the slope of the interest rate\\n */\\n uint public multiplierPerBlock;\\n\\n /**\\n * @notice The base interest rate which is the y-intercept when utilization rate is 0\\n */\\n uint public baseRatePerBlock;\\n\\n /**\\n * @notice The multiplierPerBlock after hitting a specified utilization point\\n */\\n uint public jumpMultiplierPerBlock;\\n\\n /**\\n * @notice The utilization point at which the jump multiplier is applied\\n */\\n uint public kink;\\n\\n /**\\n * @notice Construct an interest rate model\\n * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by 1e18)\\n * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by 1e18)\\n * @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point\\n * @param kink_ The utilization point at which the jump multiplier is applied\\n * @param owner_ The address of the owner, i.e. the Timelock contract (which has the ability to update parameters directly)\\n */\\n constructor(uint baseRatePerYear, uint multiplierPerYear, uint jumpMultiplierPerYear, uint kink_, address owner_) internal {\\n owner = owner_;\\n\\n updateJumpRateModelInternal(baseRatePerYear, multiplierPerYear, jumpMultiplierPerYear, kink_);\\n }\\n\\n /**\\n * @notice Update the parameters of the interest rate model (only callable by owner, i.e. Timelock)\\n * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by 1e18)\\n * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by 1e18)\\n * @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point\\n * @param kink_ The utilization point at which the jump multiplier is applied\\n */\\n function updateJumpRateModel(uint baseRatePerYear, uint multiplierPerYear, uint jumpMultiplierPerYear, uint kink_) external {\\n require(msg.sender == owner, \\\"only the owner may call this function.\\\");\\n\\n updateJumpRateModelInternal(baseRatePerYear, multiplierPerYear, jumpMultiplierPerYear, kink_);\\n }\\n\\n /**\\n * @notice Calculates the utilization rate of the market: `borrows / (cash + borrows - reserves)`\\n * @param cash The amount of cash in the market\\n * @param borrows The amount of borrows in the market\\n * @param reserves The amount of reserves in the market (currently unused)\\n * @return The utilization rate as a mantissa between [0, 1e18]\\n */\\n function utilizationRate(uint cash, uint borrows, uint reserves) public pure returns (uint) {\\n // Utilization rate is 0 when there are no borrows\\n if (borrows == 0) {\\n return 0;\\n }\\n\\n return borrows.mul(1e18).div(cash.add(borrows).sub(reserves));\\n }\\n\\n /**\\n * @notice Calculates the current borrow rate per block, with the error code expected by the market\\n * @param cash The amount of cash in the market\\n * @param borrows The amount of borrows in the market\\n * @param reserves The amount of reserves in the market\\n * @return The borrow rate percentage per block as a mantissa (scaled by 1e18)\\n */\\n function getBorrowRateInternal(uint cash, uint borrows, uint reserves) internal view returns (uint) {\\n uint util = utilizationRate(cash, borrows, reserves);\\n\\n if (util <= kink) {\\n return util.mul(multiplierPerBlock).div(1e18).add(baseRatePerBlock);\\n } else {\\n uint normalRate = kink.mul(multiplierPerBlock).div(1e18).add(baseRatePerBlock);\\n uint excessUtil = util.sub(kink);\\n return excessUtil.mul(jumpMultiplierPerBlock).div(1e18).add(normalRate);\\n }\\n }\\n\\n /**\\n * @notice Calculates the current supply rate per block\\n * @param cash The amount of cash in the market\\n * @param borrows The amount of borrows in the market\\n * @param reserves The amount of reserves in the market\\n * @param reserveFactorMantissa The current reserve factor for the market\\n * @return The supply rate percentage per block as a mantissa (scaled by 1e18)\\n */\\n function getSupplyRate(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) public view returns (uint) {\\n uint oneMinusReserveFactor = uint(1e18).sub(reserveFactorMantissa);\\n uint borrowRate = getBorrowRateInternal(cash, borrows, reserves);\\n uint rateToPool = borrowRate.mul(oneMinusReserveFactor).div(1e18);\\n return utilizationRate(cash, borrows, reserves).mul(rateToPool).div(1e18);\\n }\\n\\n /**\\n * @notice Internal function to update the parameters of the interest rate model\\n * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by 1e18)\\n * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by 1e18)\\n * @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point\\n * @param kink_ The utilization point at which the jump multiplier is applied\\n */\\n function updateJumpRateModelInternal(uint baseRatePerYear, uint multiplierPerYear, uint jumpMultiplierPerYear, uint kink_) internal {\\n baseRatePerBlock = baseRatePerYear.div(blocksPerYear);\\n multiplierPerBlock = (multiplierPerYear.mul(1e18)).div(blocksPerYear.mul(kink_));\\n jumpMultiplierPerBlock = jumpMultiplierPerYear.div(blocksPerYear);\\n kink = kink_;\\n\\n emit NewInterestParams(baseRatePerBlock, multiplierPerBlock, jumpMultiplierPerBlock, kink);\\n }\\n}\\n\",\"keccak256\":\"0xd6bf974b9a7f0d26cf04cac3dabefe81b14cdcf5b99743fc9711086c889a30de\"},\"contracts/LegacyInterestRateModel.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Compound's Legacy InterestRateModel Interface\\n * @author Compound (modified by Arr00)\\n */\\ncontract LegacyInterestRateModel {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @return error code (0 = no error), 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,uint);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) external view returns (uint);\\n\\n}\\n\",\"keccak256\":\"0x161a2e17aa46c4a2fbd4438f732f22825fddd71330a46200093b16f81b7d4732\"},\"contracts/LegacyJumpRateModelV2.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./BaseJumpRateModelV2.sol\\\";\\nimport \\\"./LegacyInterestRateModel.sol\\\";\\n\\n\\n/**\\n * @title Compound's JumpRateModel Contract V2 for legacy cTokens\\n * @author Arr00\\n * @notice Supports only legacy cTokens\\n */\\ncontract LegacyJumpRateModelV2 is LegacyInterestRateModel, BaseJumpRateModelV2 {\\n\\n\\t/**\\n * @notice Calculates the current borrow rate per block, with the error code expected by the market\\n * @param cash The amount of cash in the market\\n * @param borrows The amount of borrows in the market\\n * @param reserves The amount of reserves in the market\\n * @return (Error, The borrow rate percentage per block as a mantissa (scaled by 1e18))\\n */\\n function getBorrowRate(uint cash, uint borrows, uint reserves) external view returns (uint, uint) {\\n return (0,getBorrowRateInternal(cash, borrows, reserves));\\n }\\n \\n constructor(uint baseRatePerYear, uint multiplierPerYear, uint jumpMultiplierPerYear, uint kink_, address owner_) \\n \\tBaseJumpRateModelV2(baseRatePerYear,multiplierPerYear,jumpMultiplierPerYear,kink_,owner_) public {}\\n}\\n\",\"keccak256\":\"0x0fac34a6e6066ea6edc157f9632f4dff0a72c3e9c8f76b4c6b14eb988fd6ac52\"},\"contracts/SafeMath.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n// From https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/math/Math.sol\\n// Subject to the MIT license.\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n /**\\n * @dev Returns the addition of two unsigned integers, reverting on overflow.\\n *\\n * Counterpart to Solidity's `+` 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 >= 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's `+` 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 >= a, errorMessage);\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting on underflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` 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's `-` operator.\\n *\\n * Requirements:\\n * - Subtraction cannot underflow.\\n */\\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b <= a, errorMessage);\\n uint256 c = a - b;\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, reverting on overflow.\\n *\\n * Counterpart to Solidity's `*` 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 'a' not being zero, but the\\n // benefit is lost if 'b' 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's `*` operator.\\n *\\n * Requirements:\\n * - Multiplication cannot overflow.\\n */\\n function mul(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n // benefit is lost if 'b' is also tested.\\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n if (a == 0) {\\n return 0;\\n }\\n\\n uint256 c = a * b;\\n require(c / a == b, errorMessage);\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers.\\n * Reverts on division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n return div(a, b, \\\"SafeMath: division by zero\\\");\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers.\\n * Reverts with custom message on division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n // Solidity only automatically asserts when dividing by 0\\n require(b > 0, errorMessage);\\n uint256 c = a / b;\\n // assert(a == b * c + a % b); // There is no case in which this doesn't hold\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * Reverts when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n return mod(a, b, \\\"SafeMath: modulo by zero\\\");\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * Reverts with custom message when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b != 0, errorMessage);\\n return a % b;\\n }\\n}\\n\",\"keccak256\":\"0x6653e37ff57a02b7b7f20199bb0fd5685756ced19a67f53328b42c9d2167ffd2\"}},\"version\":1}" + }, + "tests/Contracts/ComptrollerScenarioG1.sol:ComptrollerScenarioG1": { + "abi": "[{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketEntered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketExited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"MarketListed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCloseFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCloseFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCollateralFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCollateralFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldLiquidationIncentiveMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"NewLiquidationIncentive\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMaxAssets\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMaxAssets\",\"type\":\"uint256\"}],\"name\":\"NewMaxAssets\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"oldPriceOracle\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"newPriceOracle\",\"type\":\"address\"}],\"name\":\"NewPriceOracle\",\"type\":\"event\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract Unitroller\",\"name\":\"unitroller\",\"type\":\"address\"},{\"internalType\":\"contract PriceOracle\",\"name\":\"_oracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_closeFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_maxAssets\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"reinitializing\",\"type\":\"bool\"}],\"name\":\"_become\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCloseFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCollateralFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"_setLiquidationIncentive\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newMaxAssets\",\"type\":\"uint256\"}],\"name\":\"_setMaxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"newOracle\",\"type\":\"address\"}],\"name\":\"_setPriceOracle\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"_supportMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"blockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"checkMembership\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"enterMarkets\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenAddress\",\"type\":\"address\"}],\"name\":\"exitMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blocks\",\"type\":\"uint256\"}],\"name\":\"fastForward\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAssetsIn\",\"outputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenModify\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"getHypotheticalAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"isComptroller\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateCalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"liquidationIncentiveMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"markets\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"membershipLength\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"mintAmount\",\"type\":\"uint256\"}],\"name\":\"mintAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"mintAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"mintTokens\",\"type\":\"uint256\"}],\"name\":\"mintVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"repayBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowerIndex\",\"type\":\"uint256\"}],\"name\":\"repayBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"}],\"name\":\"setBlockNumber\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"unlist\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + "bin": "608060405234801561001057600080fd5b50600080546001600160a01b03191633179055612e6b806100326000396000f3fe608060405234801561001057600080fd5b50600436106102735760003560e01c80638e8f294b11610151578063d02f7351116100c3578063e4028eee11610087578063e4028eee146109fd578063e875544614610a29578063eabe7d9114610a31578063ede4edd014610a67578063f851a44014610a8d578063fccbe7f614610a9557610273565b8063d02f735114610930578063d9226ced14610976578063da3d454c14610993578063dce15449146109c9578063dcfbc0c7146109f557610273565b8063abfceffc11610115578063abfceffc1461075e578063bb82aa5e146107d4578063bdcdc258146107dc578063bde3672d14610818578063c29982381461083e578063c488847b146108e157610273565b80638e8f294b146106a4578063929fe9a1146106e557806394b2294b14610713578063a76b3fda1461071b578063a8c3c8501461074157610273565b80634ef4c3e1116101ea5780635c778605116101ae5780635c778605146105785780635ec88c79146105ae5780635fc7e71e146105d45780636a56947e1461061a5780636d35bf91146106565780637dc0d1d01461069c57610273565b80634ef4c3e1146104bb5780634fd42e17146104f157806351dff9891461050e57806355ee1fe11461054a57806357e871e71461057057610273565b806332000e001161023c57806332000e001461036757806341c728b9146103ab57806347ef3b3b146103e75780634ada90af146104335780634bca0d8c1461043b5780634e79238f1461046157610273565b80627e3dd2146102785780631ededc911461029457806324008a62146102d85780632678224714610326578063317b0b771461034a575b600080fd5b610280610ab2565b604080519115158252519081900360200190f35b6102d6600480360360a08110156102aa57600080fd5b506001600160a01b03813581169160208101358216916040820135169060608101359060800135610ab7565b005b610314600480360360808110156102ee57600080fd5b506001600160a01b03813581169160208101358216916040820135169060600135610abe565b60408051918252519081900360200190f35b61032e610af4565b604080516001600160a01b039092168252519081900360200190f35b6103146004803603602081101561036057600080fd5b5035610b03565b6102d6600480360360a081101561037d57600080fd5b506001600160a01b038135811691602081013590911690604081013590606081013590608001351515610c11565b6102d6600480360360808110156103c157600080fd5b506001600160a01b03813581169160208101359091169060408101359060600135610c1e565b6102d6600480360360c08110156103fd57600080fd5b506001600160a01b0381358116916020810135821691604082013581169160608101359091169060808101359060a00135610c24565b610314610c2c565b6103146004803603602081101561045157600080fd5b50356001600160a01b0316610c32565b61049d6004803603608081101561047757600080fd5b506001600160a01b03813581169160208101359091169060408101359060600135610c4d565b60408051938452602084019290925282820152519081900360600190f35b610314600480360360608110156104d157600080fd5b506001600160a01b03813581169160208101359091169060400135610c87565b6103146004803603602081101561050757600080fd5b5035610cbe565b6102d66004803603608081101561052457600080fd5b506001600160a01b03813581169160208101359091169060408101359060600135610dad565b6103146004803603602081101561056057600080fd5b50356001600160a01b0316610e01565b610314610e83565b6102d66004803603606081101561058e57600080fd5b506001600160a01b03813581169160208101359091169060400135610e89565b61049d600480360360208110156105c457600080fd5b50356001600160a01b0316610e8e565b610314600480360360a08110156105ea57600080fd5b506001600160a01b0381358116916020810135821691604082013581169160608101359091169060800135610ec3565b6102d66004803603608081101561063057600080fd5b506001600160a01b03813581169160208101358216916040820135169060600135610c1e565b6102d6600480360360a081101561066c57600080fd5b506001600160a01b0381358116916020810135821691604082013581169160608101359091169060800135610ab7565b61032e61104a565b6106ca600480360360208110156106ba57600080fd5b50356001600160a01b0316611059565b60408051921515835260208301919091528051918290030190f35b610280600480360360408110156106fb57600080fd5b506001600160a01b0381358116916020013516611078565b6103146110ac565b6103146004803603602081101561073157600080fd5b50356001600160a01b03166110b2565b6102d66004803603602081101561075757600080fd5b50356111e1565b6107846004803603602081101561077457600080fd5b50356001600160a01b03166111e6565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156107c05781810151838201526020016107a8565b505050509050019250505060405180910390f35b61032e61126f565b610314600480360360808110156107f257600080fd5b506001600160a01b0381358116916020810135821691604082013516906060013561127e565b6102d66004803603602081101561082e57600080fd5b50356001600160a01b031661128b565b6107846004803603602081101561085457600080fd5b81019060208101813564010000000081111561086f57600080fd5b82018360208201111561088157600080fd5b803590602001918460208302840111640100000000831117156108a357600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295506112ac945050505050565b610917600480360360608110156108f757600080fd5b506001600160a01b03813581169160208101359091169060400135611450565b6040805192835260208301919091528051918290030190f35b610314600480360360a081101561094657600080fd5b506001600160a01b03813581169160208101358216916040820135811691606081013590911690608001356116c5565b6103146004803603602081101561098c57600080fd5b5035611808565b610314600480360360608110156109a957600080fd5b506001600160a01b0381358116916020810135909116906040013561186c565b61032e600480360360408110156109df57600080fd5b506001600160a01b0381351690602001356119a0565b61032e6119d5565b61031460048036036040811015610a1357600080fd5b506001600160a01b0381351690602001356119e4565b610314611b94565b61031460048036036060811015610a4757600080fd5b506001600160a01b03813581169160208101359091169060400135611b9a565b61031460048036036020811015610a7d57600080fd5b50356001600160a01b0316611ba7565b61032e611eba565b61031460048036036020811015610aab57600080fd5b5035611ec9565b600181565b5050505050565b6001600160a01b03841660009081526009602052604081205460ff16610ae657506009610aec565b60005b90505b949350505050565b6001546001600160a01b031681565b6000610b0d611ed8565b610b2457610b1d60016004611f23565b9050610c0c565b610b2c612d2b565b506040805160208101909152828152610b43612d2b565b50604080516020810190915266b1a2bc2ec500008152610b638282611f89565b15610b7c57610b73600580611f23565b92505050610c0c565b610b84612d2b565b506040805160208101909152670c7d713b49da00008152610ba58184611f91565b15610bbf57610bb5600580611f23565b9350505050610c0c565b6005805490869055604080518281526020810188905281517f3b9670cf975d26958e754b57098eaa2ac914d8d2a31b83257997b9f346110fd9929181900390910190a160005b9450505050505b919050565b610ab78585858585611f98565b50505050565b505050505050565b60065481565b6001600160a01b031660009081526008602052604090205490565b600080600080600080610c628a8a8a8a61242f565b925092509250826011811115610c7457fe5b95509093509150505b9450945094915050565b6001600160a01b03831660009081526009602052604081205460ff16610cb15760095b9050610cb7565b60005b90505b9392505050565b6000610cc8611ed8565b610cd857610b1d6001600b611f23565b610ce0612d2b565b506040805160208101909152828152610cf7612d2b565b506040805160208101909152670de0b6b3a76400008152610d188282611f91565b15610d2957610b736007600c611f23565b610d31612d2b565b5060408051602081019091526714d1120d7b1600008152610d528184611f91565b15610d6357610bb56007600c611f23565b6006805490869055604080518281526020810188905281517faeba5a6c40a8ac138134bff1aaa65debf25971188a58804bad717f82f0ec1316929181900390910190a16000610c05565b80158015610dbb5750600082115b15610c1e576040805162461bcd60e51b815260206004820152601160248201527072656465656d546f6b656e73207a65726f60781b604482015290519081900360640190fd5b6000610e0b611ed8565b610e1b57610b1d60016010611f23565b600480546001600160a01b038481166001600160a01b0319831681179093556040805191909216808252602082019390935281517fd52b2b9b7e9ee655fcb95d2e5b9e0c9f69e7ef2b8e9d2d0ea78402d576d22e22929181900390910190a160009392505050565b600a5481565b505050565b600080600080600080610ea587600080600061242f565b925092509250826011811115610eb757fe5b97919650945092505050565b6001600160a01b03851660009081526009602052604081205460ff161580610f0457506001600160a01b03851660009081526009602052604090205460ff16155b15610f135760095b9050611041565b600080610f1f8561284a565b91935090915060009050826011811115610f3557fe5b14610f4f57816011811115610f4657fe5b92505050611041565b80610f5b576003610f46565b6000886001600160a01b03166395dd9193876040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015610fb357600080fd5b505afa158015610fc7573d6000803e3d6000fd5b505050506040513d6020811015610fdd57600080fd5b5051604080516020810190915260055481529091506000908190611001908461286a565b9092509050600082600381111561101457fe5b1461102857600b5b95505050505050611041565b8087111561103757601161101c565b6000955050505050505b95945050505050565b6004546001600160a01b031681565b6009602052600090815260409020805460019091015460ff9091169082565b6001600160a01b038082166000908152600960209081526040808320938616835260029093019052205460ff165b92915050565b60075481565b600080546001600160a01b031633146110d157610b1d60016012611f23565b6001600160a01b03821660009081526009602052604090205460ff16156110fe57610b1d600a6011611f23565b816001600160a01b031663fe9c44ae6040518163ffffffff1660e01b815260040160206040518083038186803b15801561113757600080fd5b505afa15801561114b573d6000803e3d6000fd5b505050506040513d602081101561116157600080fd5b50506040805180820182526001808252600060208084018281526001600160a01b03881680845260098352928690209451855460ff1916901515178555519390920192909255825191825291517fcf583bb0c569eb967f806b11601c4cb93c10310485c67add5f8362c2f212321f929181900390910190a1600092915050565b600a55565b60608060086000846001600160a01b03166001600160a01b0316815260200190815260200160002080548060200260200160405190810160405280929190818152602001828054801561126257602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611244575b5093979650505050505050565b6002546001600160a01b031681565b6000610ae98585846128be565b6001600160a01b03166000908152600960205260409020805460ff19169055565b60606000825190506060816040519080825280602002602001820160405280156112e0578160200160208202803883390190505b50905060005b828110156114485760008582815181106112fc57fe5b6020908102919091018101516001600160a01b03811660009081526009909252604090912080549192509060ff166113505760095b84848151811061133d57fe5b6020026020010181815250505050611440565b33600090815260028201602052604090205460ff16151560011415611376576000611331565b6007543360009081526008602052604090205410611395576010611331565b3360008181526002830160209081526040808320805460ff19166001908117909155600883528184208054918201815584529282902090920180546001600160a01b0387166001600160a01b0319909116811790915582519081529081019290925280517f3ab23ab0d51cccc0c3085aec51f99228625aa1a922b3a8ca89a26b0f2027a1a59281900390910190a1600084848151811061143157fe5b60200260200101818152505050505b6001016112e6565b509392505050565b600480546040805163fc57d4df60e01b81526001600160a01b038781169482019490945290516000938493849391169163fc57d4df91602480820192602092909190829003018186803b1580156114a657600080fd5b505afa1580156114ba573d6000803e3d6000fd5b505050506040513d60208110156114d057600080fd5b5051600480546040805163fc57d4df60e01b81526001600160a01b038a8116948201949094529051939450600093929091169163fc57d4df91602480820192602092909190829003018186803b15801561152957600080fd5b505afa15801561153d573d6000803e3d6000fd5b505050506040513d602081101561155357600080fd5b50519050811580611562575080155b1561157757600d9350600092506116bd915050565b6000866001600160a01b031663182df0f56040518163ffffffff1660e01b815260040160206040518083038186803b1580156115b257600080fd5b505afa1580156115c6573d6000803e3d6000fd5b505050506040513d60208110156115dc57600080fd5b5051905060006115ea612d2b565b6115f2612d2b565b6115fa612d2b565b60006116086006548961292d565b94509050600081600381111561161a57fe5b1461163657600b5b9950600098506116bd975050505050505050565b611640878761292d565b93509050600081600381111561165257fe5b1461165e57600b611622565b6116688484612968565b92509050600081600381111561167a57fe5b1461168657600b611622565b611690828c61286a565b9550905060008160038111156116a257fe5b146116ae57600b611622565b60009950939750505050505050505b935093915050565b6001600160a01b03851660009081526009602052604081205460ff16158061170657506001600160a01b03851660009081526009602052604090205460ff16155b15611712576009610f0c565b846001600160a01b0316635fe3b5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561174b57600080fd5b505afa15801561175f573d6000803e3d6000fd5b505050506040513d602081101561177557600080fd5b505160408051635fe3b56760e01b815290516001600160a01b0392831692891691635fe3b567916004808301926020929190829003018186803b1580156117bb57600080fd5b505afa1580156117cf573d6000803e3d6000fd5b505050506040513d60208110156117e557600080fd5b50516001600160a01b0316146117fc576002610f0c565b60009695505050505050565b6000611812611ed8565b61182257610b1d6001600d611f23565b6007805490839055604080518281526020810185905281517f7093cf1eb653f749c3ff531d6df7f92764536a7fa0d13530cd26e070780c32ea929181900390910190a16000610cb7565b6001600160a01b03831660009081526009602052604081205460ff16611893576009610caa565b6001600160a01b038085166000908152600960209081526040808320938716835260029093019052205460ff166118cb576008610caa565b600480546040805163fc57d4df60e01b81526001600160a01b03888116948201949094529051929091169163fc57d4df91602480820192602092909190829003018186803b15801561191c57600080fd5b505afa158015611930573d6000803e3d6000fd5b505050506040513d602081101561194657600080fd5b505161195357600d610caa565b600080611963858760008761242f565b9193509091506000905082601181111561197957fe5b146119935781601181111561198a57fe5b92505050610cb7565b80156117fc57600461198a565b600860205281600052604060002081815481106119b957fe5b6000918252602090912001546001600160a01b03169150829050565b6003546001600160a01b031681565b600080546001600160a01b03163314611a0a57611a0360016006611f23565b90506110a6565b6001600160a01b0383166000908152600960205260409020805460ff16611a3f57611a3760096007611f23565b9150506110a6565b611a47612d2b565b506040805160208101909152838152611a5e612d2b565b506040805160208101909152670c7d713b49da00008152611a7f8183611f91565b15611a9a57611a9060066008611f23565b93505050506110a6565b8415801590611b235750600480546040805163fc57d4df60e01b81526001600160a01b038a8116948201949094529051929091169163fc57d4df91602480820192602092909190829003018186803b158015611af557600080fd5b505afa158015611b09573d6000803e3d6000fd5b505050506040513d6020811015611b1f57600080fd5b5051155b15611b3457611a90600d6009611f23565b60018301805490869055604080516001600160a01b03891681526020810183905280820188905290517f70483e6592cd5182d45ac970e05bc62cdcc90e9d8ef2c2dbe686cf383bcd7fc59181900360600190a16000979650505050505050565b60055481565b6000610cb48484846128be565b6000808290506000806000836001600160a01b031663c37f68e2336040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060806040518083038186803b158015611c0857600080fd5b505afa158015611c1c573d6000803e3d6000fd5b505050506040513d6080811015611c3257600080fd5b508051602082015160409092015190945090925090508215611c855760405162461bcd60e51b8152600401808060200182810382526025815260200180612deb6025913960400191505060405180910390fd5b8015611ca257611c97600c6002611f23565b945050505050610c0c565b6000611caf8733856128be565b90508015611cd057611cc4600e600383612980565b95505050505050610c0c565b6001600160a01b0385166000908152600960209081526040808320338452600281019092529091205460ff16611d0f5760009650505050505050610c0c565b3360009081526002820160209081526040808320805460ff191690556008825291829020805483518184028101840190945280845260609392830182828015611d8157602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611d63575b5050835193945083925060009150505b82811015611dd657896001600160a01b0316848281518110611daf57fe5b60200260200101516001600160a01b03161415611dce57809150611dd6565b600101611d91565b50818110611de057fe5b336000908152600860205260409020805481906000198101908110611e0157fe5b9060005260206000200160009054906101000a90046001600160a01b0316818381548110611e2b57fe5b600091825260209091200180546001600160a01b0319166001600160a01b03929092169190911790558054611e64826000198301612d3e565b50604080516001600160a01b038c16815233602082015281517fe699a64c18b07ac5b7301aa273f36a2287239eb9501d81950672794afba29a0d929181900390910190a160009c9b505050505050505050505050565b6000546001600160a01b031681565b600a8054820190819055919050565b60025460009081906001600160a01b031633148015611f0157506000546001600160a01b031632145b6000549091506001600160a01b031633148080611f1b5750815b925050505b90565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0836011811115611f5257fe5b836013811115611f5e57fe5b604080519283526020830191909152600082820152519081900360600190a1826011811115610cb757fe5b519051111590565b5190511090565b846001600160a01b031663f851a4406040518163ffffffff1660e01b815260040160206040518083038186803b158015611fd157600080fd5b505afa158015611fe5573d6000803e3d6000fd5b505050506040513d6020811015611ffb57600080fd5b50516001600160a01b031633146120435760405162461bcd60e51b8152600401808060200182810382526027815260200180612e106027913960400191505060405180910390fd5b6000856001600160a01b031663c1e803346040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561208057600080fd5b505af1158015612094573d6000803e3d6000fd5b505050506040513d60208110156120aa57600080fd5b5051905080156120f9576040805162461bcd60e51b815260206004820152601560248201527418da185b99d9481b9bdd08185d5d1a1bdc9a5e9959605a1b604482015290519081900360640190fd5b81610c245760008690506000816001600160a01b03166355ee1fe1886040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b03168152602001915050602060405180830381600087803b15801561215d57600080fd5b505af1158015612171573d6000803e3d6000fd5b505050506040513d602081101561218757600080fd5b5051905080156121d7576040805162461bcd60e51b815260206004820152601660248201527539b2ba10383934b1b29037b930b1b6329032b93937b960511b604482015290519081900360640190fd5b816001600160a01b031663317b0b77876040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b15801561221d57600080fd5b505af1158015612231573d6000803e3d6000fd5b505050506040513d602081101561224757600080fd5b505190508015612297576040805162461bcd60e51b815260206004820152601660248201527539b2ba1031b637b9b2903330b1ba37b91032b93937b960511b604482015290519081900360640190fd5b816001600160a01b031663d9226ced866040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b1580156122dd57600080fd5b505af11580156122f1573d6000803e3d6000fd5b505050506040513d602081101561230757600080fd5b505190508015612356576040805162461bcd60e51b815260206004820152601560248201527439b2ba1036b0bc1030b9b9b9b2ba399032b93937b960591b604482015290519081900360640190fd5b816001600160a01b0316634fd42e17670de0b6b3a76400006040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b1580156123a457600080fd5b505af11580156123b8573d6000803e3d6000fd5b505050506040513d60208110156123ce57600080fd5b505190508015612425576040805162461bcd60e51b815260206004820152601f60248201527f736574206c69717569646174696f6e20696e63656e74697665206572726f7200604482015290519081900360640190fd5b5050505050505050565b600080600061243c612d62565b6001600160a01b0388166000908152600860209081526040808320805482518185028101850190935280835284936060939291908301828280156124a957602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161248b575b50939450600093505050505b81518110156128055760008282815181106124cc57fe5b60200260200101519050806001600160a01b031663c37f68e28e6040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060806040518083038186803b15801561252c57600080fd5b505afa158015612540573d6000803e3d6000fd5b505050506040513d608081101561255657600080fd5b508051602082015160408084015160609485015160808c0152938a0193909352918801919091529450841561259c5750600f975060009650869550610c7d945050505050565b60408051602080820183526001600160a01b0380851660008181526009845285902060010154845260c08b01939093528351808301855260808b0151815260e08b015260048054855163fc57d4df60e01b815291820194909452935192169263fc57d4df9260248083019392829003018186803b15801561261c57600080fd5b505afa158015612630573d6000803e3d6000fd5b505050506040513d602081101561264657600080fd5b505160a0870181905261266a5750600d975060009650869550610c7d945050505050565b604080516020810190915260a08701518152610100870181905260c087015160e0880151612697926129e6565b610120880152935060008460038111156126ad57fe5b146126c95750600b975060009650869550610c7d945050505050565b6126e186610120015187604001518860000151612a3e565b8752935060008460038111156126f357fe5b1461270f5750600b975060009650869550610c7d945050505050565b61272786610100015187606001518860200151612a3e565b60208801529350600084600381111561273c57fe5b146127585750600b975060009650869550610c7d945050505050565b8b6001600160a01b0316816001600160a01b031614156127fc576127868661012001518c8860200151612a3e565b60208801529350600084600381111561279b57fe5b146127b75750600b975060009650869550610c7d945050505050565b6127cb8661010001518b8860200151612a3e565b6020880152935060008460038111156127e057fe5b146127fc5750600b975060009650869550610c7d945050505050565b506001016124b5565b5060208401518451111561282c575050506020810151905160009450039150829050610c7d565b5050815160209092015160009550859450919091039150610c7d9050565b600080600061285d84600080600061242f565b9250925092509193909250565b6000806000612877612d2b565b6128818686612a8b565b9092509050600082600381111561289457fe5b146128a557509150600090506128b7565b60006128b082612af3565b9350935050505b9250929050565b6001600160a01b03831660009081526009602052604081205460ff166128e5576009610caa565b6001600160a01b038085166000908152600960209081526040808320938716835260029093019052205460ff1661291d576000610caa565b600080611963858786600061242f565b6000612937612d2b565b61295d604051806020016040528086815250604051806020016040528086815250612b02565b915091509250929050565b6000612972612d2b565b8351835161295d9190612beb565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa08460118111156129af57fe5b8460138111156129bb57fe5b604080519283526020830191909152818101859052519081900360600190a1836011811115610cb457fe5b60006129f0612d2b565b60006129fa612d2b565b612a048787612b02565b90925090506000826003811115612a1757fe5b14612a265790925090506116bd565b612a308186612b02565b935093505050935093915050565b6000806000612a4b612d2b565b612a558787612a8b565b90925090506000826003811115612a6857fe5b14612a7957509150600090506116bd565b612a30612a8582612af3565b86612c9b565b6000612a95612d2b565b600080612aa6866000015186612cc1565b90925090506000826003811115612ab957fe5b14612ad8575060408051602081019091526000815290925090506128b7565b60408051602081019091529081526000969095509350505050565b51670de0b6b3a7640000900490565b6000612b0c612d2b565b600080612b2186600001518660000151612cc1565b90925090506000826003811115612b3457fe5b14612b53575060408051602081019091526000815290925090506128b7565b600080612b686706f05b59d3b2000084612c9b565b90925090506000826003811115612b7b57fe5b14612b9d575060408051602081019091526000815290945092506128b7915050565b600080612bb283670de0b6b3a7640000612d00565b90925090506000826003811115612bc557fe5b14612bcc57fe5b604080516020810190915290815260009a909950975050505050505050565b6000612bf5612d2b565b600080612c0a86670de0b6b3a7640000612cc1565b90925090506000826003811115612c1d57fe5b14612c3c575060408051602081019091526000815290925090506128b7565b600080612c498388612d00565b90925090506000826003811115612c5c57fe5b14612c7e575060408051602081019091526000815290945092506128b7915050565b604080516020810190915290815260009890975095505050505050565b600080838301848110612cb3576000925090506128b7565b5060029150600090506128b7565b60008083612cd4575060009050806128b7565b83830283858281612ce157fe5b0414612cf5575060029150600090506128b7565b6000925090506128b7565b60008082612d1457506001905060006128b7565b6000838581612d1f57fe5b04915091509250929050565b6040518060200160405280600081525090565b815481835581811115610e8957600083815260209020610e89918101908301612dcc565b604051806101400160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001612da0612d2b565b8152602001612dad612d2b565b8152602001612dba612d2b565b8152602001612dc7612d2b565b905290565b611f2091905b80821115612de65760008155600101612dd2565b509056fe657869744d61726b65743a206765744163636f756e74536e617073686f74206661696c65646f6e6c7920756e6974726f6c6c65722061646d696e2063616e206368616e676520627261696e73a265627a7a72315820fe3088249d9cb7eb089b26e2016f22e44ed0b2d18f60cd91d57caffa098fc66164736f6c63430005100032", + "metadata": "{\"compiler\":{\"version\":\"0.5.16+commit.9c3226ce\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketEntered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketExited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"MarketListed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCloseFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCloseFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCollateralFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCollateralFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldLiquidationIncentiveMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"NewLiquidationIncentive\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMaxAssets\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMaxAssets\",\"type\":\"uint256\"}],\"name\":\"NewMaxAssets\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"oldPriceOracle\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"newPriceOracle\",\"type\":\"address\"}],\"name\":\"NewPriceOracle\",\"type\":\"event\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract Unitroller\",\"name\":\"unitroller\",\"type\":\"address\"},{\"internalType\":\"contract PriceOracle\",\"name\":\"_oracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_closeFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_maxAssets\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"reinitializing\",\"type\":\"bool\"}],\"name\":\"_become\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCloseFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCollateralFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"_setLiquidationIncentive\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newMaxAssets\",\"type\":\"uint256\"}],\"name\":\"_setMaxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"newOracle\",\"type\":\"address\"}],\"name\":\"_setPriceOracle\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"_supportMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"blockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"checkMembership\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"enterMarkets\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenAddress\",\"type\":\"address\"}],\"name\":\"exitMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blocks\",\"type\":\"uint256\"}],\"name\":\"fastForward\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAssetsIn\",\"outputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenModify\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"getHypotheticalAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"isComptroller\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateCalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"liquidationIncentiveMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"markets\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"membershipLength\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"mintAmount\",\"type\":\"uint256\"}],\"name\":\"mintAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"mintAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"mintTokens\",\"type\":\"uint256\"}],\"name\":\"mintVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"repayBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowerIndex\",\"type\":\"uint256\"}],\"name\":\"repayBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"}],\"name\":\"setBlockNumber\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"unlist\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"methods\":{\"_setCloseFactor(uint256)\":{\"details\":\"Admin function to set closeFactor\",\"params\":{\"newCloseFactorMantissa\":\"New close factor, scaled by 1e18\"},\"return\":\"uint 0=success, otherwise a failure. (See ErrorReporter for details)\"},\"_setCollateralFactor(address,uint256)\":{\"details\":\"Admin function to set per-market collateralFactor\",\"params\":{\"cToken\":\"The market to set the factor on\",\"newCollateralFactorMantissa\":\"The new collateral factor, scaled by 1e18\"},\"return\":\"uint 0=success, otherwise a failure. (See ErrorReporter for details)\"},\"_setLiquidationIncentive(uint256)\":{\"details\":\"Admin function to set liquidationIncentive\",\"params\":{\"newLiquidationIncentiveMantissa\":\"New liquidationIncentive scaled by 1e18\"},\"return\":\"uint 0=success, otherwise a failure. (See ErrorReporter for details)\"},\"_setMaxAssets(uint256)\":{\"details\":\"Admin function to set maxAssets\",\"params\":{\"newMaxAssets\":\"New max assets\"},\"return\":\"uint 0=success, otherwise a failure. (See ErrorReporter for details)\"},\"_setPriceOracle(address)\":{\"details\":\"Admin function to set a new price oracle\",\"return\":\"uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\"},\"_supportMarket(address)\":{\"details\":\"Admin function to set isListed and add support for the market\",\"params\":{\"cToken\":\"The address of the market (token) to list\"},\"return\":\"uint 0=success, otherwise a failure. (See enum Error for details)\"},\"borrowAllowed(address,address,uint256)\":{\"params\":{\"borrowAmount\":\"The amount of underlying the account would borrow\",\"borrower\":\"The account which would borrow the asset\",\"cToken\":\"The market to verify the borrow against\"},\"return\":\"0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"borrowVerify(address,address,uint256)\":{\"params\":{\"borrowAmount\":\"The amount of the underlying asset requested to borrow\",\"borrower\":\"The address borrowing the underlying\",\"cToken\":\"Asset whose underlying is being borrowed\"}},\"checkMembership(address,address)\":{\"params\":{\"account\":\"The address of the account to check\",\"cToken\":\"The cToken to check\"},\"return\":\"True if the account is in the asset, otherwise false.\"},\"enterMarkets(address[])\":{\"params\":{\"cTokens\":\"The list of addresses of the cToken markets to be enabled\"},\"return\":\"Success indicator for whether each corresponding market was entered\"},\"exitMarket(address)\":{\"details\":\"Sender must not have an outstanding borrow balance in the asset, or be providing neccessary collateral for an outstanding borrow.\",\"params\":{\"cTokenAddress\":\"The address of the asset to be removed\"},\"return\":\"Whether or not the account successfully exited the market\"},\"getAccountLiquidity(address)\":{\"return\":\"(possible error code (semi-opaque), account liquidity in excess of collateral requirements, account shortfall below collateral requirements)\"},\"getAssetsIn(address)\":{\"params\":{\"account\":\"The address of the account to pull assets for\"},\"return\":\"A dynamic list with the assets the account has entered\"},\"liquidateBorrowAllowed(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"repayAmount\":\"The amount of underlying being repaid\"}},\"liquidateBorrowVerify(address,address,address,address,uint256,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"repayAmount\":\"The amount of underlying being repaid\"}},\"liquidateCalculateSeizeTokens(address,address,uint256)\":{\"details\":\"Used in liquidation (called in cToken.liquidateBorrowFresh)\",\"params\":{\"cTokenBorrowed\":\"The address of the borrowed cToken\",\"cTokenCollateral\":\"The address of the collateral cToken\",\"repayAmount\":\"The amount of cTokenBorrowed underlying to convert into cTokenCollateral tokens\"},\"return\":\"(errorCode, number of cTokenCollateral tokens to be seized in a liquidation)\"},\"mintAllowed(address,address,uint256)\":{\"params\":{\"cToken\":\"The market to verify the mint against\",\"mintAmount\":\"The amount of underlying being supplied to the market in exchange for tokens\",\"minter\":\"The account which would get the minted tokens\"},\"return\":\"0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"mintVerify(address,address,uint256,uint256)\":{\"params\":{\"cToken\":\"Asset being minted\",\"mintAmount\":\"The amount of the underlying asset being minted\",\"mintTokens\":\"The number of tokens being minted\",\"minter\":\"The address minting the tokens\"}},\"redeemAllowed(address,address,uint256)\":{\"params\":{\"cToken\":\"The market to verify the redeem against\",\"redeemTokens\":\"The number of cTokens to exchange for the underlying asset in the market\",\"redeemer\":\"The account which would redeem the tokens\"},\"return\":\"0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"redeemVerify(address,address,uint256,uint256)\":{\"params\":{\"cToken\":\"Asset being redeemed\",\"redeemAmount\":\"The amount of the underlying asset being redeemed\",\"redeemTokens\":\"The number of tokens being redeemed\",\"redeemer\":\"The address redeeming the tokens\"}},\"repayBorrowAllowed(address,address,address,uint256)\":{\"params\":{\"borrower\":\"The account which would borrowed the asset\",\"cToken\":\"The market to verify the repay against\",\"payer\":\"The account which would repay the asset\",\"repayAmount\":\"The amount of the underlying asset the account would repay\"},\"return\":\"0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"repayBorrowVerify(address,address,address,uint256,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"cToken\":\"Asset being repaid\",\"payer\":\"The address repaying the borrow\",\"repayAmount\":\"The amount of underlying being repaid\"}},\"seizeAllowed(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"seizeTokens\":\"The number of collateral tokens to seize\"}},\"seizeVerify(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"seizeTokens\":\"The number of collateral tokens to seize\"}},\"transferAllowed(address,address,address,uint256)\":{\"params\":{\"cToken\":\"The market to verify the transfer against\",\"dst\":\"The account which receives the tokens\",\"src\":\"The account which sources the tokens\",\"transferTokens\":\"The number of cTokens to transfer\"},\"return\":\"0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"transferVerify(address,address,address,uint256)\":{\"params\":{\"cToken\":\"Asset being transferred\",\"dst\":\"The account which receives the tokens\",\"src\":\"The account which sources the tokens\",\"transferTokens\":\"The number of cTokens to transfer\"}}}},\"userdoc\":{\"methods\":{\"_setCloseFactor(uint256)\":{\"notice\":\"Sets the closeFactor used when liquidating borrows\"},\"_setCollateralFactor(address,uint256)\":{\"notice\":\"Sets the collateralFactor for a market\"},\"_setLiquidationIncentive(uint256)\":{\"notice\":\"Sets liquidationIncentive\"},\"_setMaxAssets(uint256)\":{\"notice\":\"Sets maxAssets which controls how many markets can be entered\"},\"_setPriceOracle(address)\":{\"notice\":\"Sets a new price oracle for the comptroller\"},\"_supportMarket(address)\":{\"notice\":\"Add the market to the markets mapping and set it as listed\"},\"borrowAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to borrow the underlying asset of the given market\"},\"borrowVerify(address,address,uint256)\":{\"notice\":\"Validates borrow and reverts on rejection. May emit logs.\"},\"checkMembership(address,address)\":{\"notice\":\"Returns whether the given account is entered in the given asset\"},\"enterMarkets(address[])\":{\"notice\":\"Add assets to be included in account liquidity calculation\"},\"exitMarket(address)\":{\"notice\":\"Removes asset from sender's account liquidity calculation\"},\"getAccountLiquidity(address)\":{\"notice\":\"Determine the current account liquidity wrt collateral requirements\"},\"getAssetsIn(address)\":{\"notice\":\"Returns the assets an account has entered\"},\"liquidateBorrowAllowed(address,address,address,address,uint256)\":{\"notice\":\"Checks if the liquidation should be allowed to occur\"},\"liquidateBorrowVerify(address,address,address,address,uint256,uint256)\":{\"notice\":\"Validates liquidateBorrow and reverts on rejection. May emit logs.\"},\"liquidateCalculateSeizeTokens(address,address,uint256)\":{\"notice\":\"Calculate number of tokens of collateral asset to seize given an underlying amount\"},\"mintAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to mint tokens in the given market\"},\"mintVerify(address,address,uint256,uint256)\":{\"notice\":\"Validates mint and reverts on rejection. May emit logs.\"},\"redeemAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to redeem tokens in the given market\"},\"redeemVerify(address,address,uint256,uint256)\":{\"notice\":\"Validates redeem and reverts on rejection. May emit logs.\"},\"repayBorrowAllowed(address,address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to repay a borrow in the given market\"},\"repayBorrowVerify(address,address,address,uint256,uint256)\":{\"notice\":\"Validates repayBorrow and reverts on rejection. May emit logs.\"},\"seizeAllowed(address,address,address,address,uint256)\":{\"notice\":\"Checks if the seizing of assets should be allowed to occur\"},\"seizeVerify(address,address,address,address,uint256)\":{\"notice\":\"Validates seize and reverts on rejection. May emit logs.\"},\"transferAllowed(address,address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to transfer tokens in the given market\"},\"transferVerify(address,address,address,uint256)\":{\"notice\":\"Validates transfer and reverts on rejection. May emit logs.\"}}}},\"settings\":{\"compilationTarget\":{\"tests/Contracts/ComptrollerScenarioG1.sol\":\"ComptrollerScenarioG1\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/CToken.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./CTokenInterfaces.sol\\\";\\nimport \\\"./ErrorReporter.sol\\\";\\nimport \\\"./Exponential.sol\\\";\\nimport \\\"./EIP20Interface.sol\\\";\\nimport \\\"./InterestRateModel.sol\\\";\\n\\n/**\\n * @title Compound's CToken Contract\\n * @notice Abstract base for CTokens\\n * @author Compound\\n */\\ncontract CToken is CTokenInterface, Exponential, TokenErrorReporter {\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_) public {\\n require(msg.sender == admin, \\\"only admin may initialize the market\\\");\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = getBlockNumber();\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Transfer `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = uint(-1);\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srcTokensNew;\\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, srcTokensNew) = 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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srcTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != uint(-1)) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n // unused function\\n // comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transfer(address dst, uint256 amount) external nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferFrom(address src, address dst, uint256 amount) external nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (-1 means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool) {\\n address src = msg.sender;\\n transferAllowances[src][spender] = amount;\\n emit Approval(src, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (-1 means infinite)\\n */\\n function allowance(address owner, address spender) external view returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external returns (uint) {\\n Exp memory exchangeRate = Exp({mantissa: exchangeRateCurrent()});\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n require(mErr == MathError.NO_ERROR, \\\"balance could not be calculated\\\");\\n return balance;\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view returns (uint, uint, uint, uint) {\\n uint cTokenBalance = accountTokens[account];\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), cTokenBalance, borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @dev Function to simply retrieve block number\\n * This exists mainly for inheriting test contracts to stub this result.\\n */\\n function getBlockNumber() internal view returns (uint) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this cToken\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view returns (uint) {\\n return interestRateModel.getBorrowRate(getCashPrior(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this cToken\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view returns (uint) {\\n return interestRateModel.getSupplyRate(getCashPrior(), totalBorrows, totalReserves, reserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n require(err == MathError.NO_ERROR, \\\"borrowBalanceStored: borrowBalanceStoredInternal failed\\\");\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return (error code, the calculated balance or 0 if error code is non-zero)\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the CToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n require(err == MathError.NO_ERROR, \\\"exchangeRateStored: exchangeRateStoredInternal failed\\\");\\n return result;\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the CToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return (error code, calculated exchange rate scaled by 1e18)\\n */\\n function exchangeRateStoredInternal() internal view returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows - totalReserves) / totalSupply\\n */\\n uint totalCash = getCashPrior();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Get cash balance of this cToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage.\\n */\\n function accrueInterest() public returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = getBlockNumber();\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = getCashPrior();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n require(mathErr == MathError.NO_ERROR, \\\"could not calculate block delta\\\");\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({mantissa: borrowRateMantissa}), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(Exp({mantissa: reserveFactorMantissa}), interestAccumulated, reservesPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives cTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n struct MintLocalVars {\\n Error err;\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives cTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, 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's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the cToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of cTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.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 cTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED\\\");\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\\");\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender redeems cTokens in exchange for the underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemTokens The number of cTokens to redeem into underlying\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemInternal(uint redeemTokens) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(msg.sender, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems cTokens in exchange for a specified amount of underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemAmount The amount of underlying to receive from redeeming cTokens\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemUnderlyingInternal(uint redeemAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(msg.sender, 0, redeemAmount);\\n }\\n\\n struct RedeemLocalVars {\\n Error err;\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n /**\\n * @notice User redeems cTokens in exchange for the underlying asset\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param redeemTokensIn The number of cTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming cTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemFresh(address payable redeemer, uint redeemTokensIn, uint redeemAmountIn) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr));\\n }\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(Exp({mantissa: vars.exchangeRateMantissa}), redeemTokensIn);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(redeemAmountIn, Exp({mantissa: vars.exchangeRateMantissa}));\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REDEEM_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDEEM_FRESHNESS_CHECK);\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDEEM_TRANSFER_OUT_NOT_POSSIBLE);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We invoke doTransferOut for the redeemer and the redeemAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(redeemer, vars.redeemAmount);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n /* We call the defense hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender borrows assets from the protocol to their own address\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function borrowInternal(uint borrowAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(msg.sender, borrowAmount);\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n /**\\n * @notice Users borrow assets from the protocol to their own address\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function borrowFresh(address payable borrower, uint borrowAmount) internal returns (uint) {\\n /* Fail if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.BORROW_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.BORROW_FRESHNESS_CHECK);\\n }\\n\\n /* Fail gracefully if protocol has insufficient underlying cash */\\n if (getCashPrior() < borrowAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.BORROW_CASH_NOT_AVAILABLE);\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We invoke doTransferOut for the borrower and the borrowAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(borrower, borrowAmount);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to borrower\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer the account paying off the borrow\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount the amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED\\\");\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED\\\");\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this cToken to be liquidated\\n * @param cTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) 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 = cTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, cTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this cToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param cTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowFresh(address liquidator, address borrower, uint repayAmount, CTokenInterface cTokenCollateral) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(address(this), address(cTokenCollateral), liquidator, borrower, repayAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify cTokenCollateral market's block number equals current block number */\\n if (cTokenCollateral.accrualBlockNumber() != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = -1 */\\n if (repayAmount == uint(-1)) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & 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(cTokenCollateral), actualRepayAmount);\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(cTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(cTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = cTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(cTokenCollateral), seizeTokens);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.liquidateBorrowVerify(address(this), address(cTokenCollateral), liquidator, borrower, actualRepayAmount, seizeTokens);\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another cToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed cToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of cTokens to seize\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function seize(address liquidator, address borrower, uint seizeTokens) external nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n struct SeizeInternalLocalVars {\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n uint liquidatorSeizeTokens;\\n uint protocolSeizeTokens;\\n uint protocolSeizeAmount;\\n uint exchangeRateMantissa;\\n uint totalReservesNew;\\n uint totalSupplyNew;\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another CToken.\\n * Its absolutely critical to use msg.sender as the seizer cToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed cToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of cTokens to seize\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function seizeInternal(address seizerToken, address liquidator, address borrower, uint seizeTokens) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n SeizeInternalLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (vars.mathErr, vars.borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(vars.mathErr));\\n }\\n\\n vars.protocolSeizeTokens = mul_(seizeTokens, Exp({mantissa: protocolSeizeShareMantissa}));\\n vars.liquidatorSeizeTokens = sub_(seizeTokens, vars.protocolSeizeTokens);\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n require(vars.mathErr == MathError.NO_ERROR, \\\"exchange rate math error\\\");\\n\\n vars.protocolSeizeAmount = mul_ScalarTruncate(Exp({mantissa: vars.exchangeRateMantissa}), vars.protocolSeizeTokens);\\n\\n vars.totalReservesNew = add_(totalReserves, vars.protocolSeizeAmount);\\n vars.totalSupplyNew = sub_(totalSupply, vars.protocolSeizeTokens);\\n\\n (vars.mathErr, vars.liquidatorTokensNew) = addUInt(accountTokens[liquidator], vars.liquidatorSeizeTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(vars.mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n totalReserves = vars.totalReservesNew;\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[borrower] = vars.borrowerTokensNew;\\n accountTokens[liquidator] = vars.liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, vars.liquidatorSeizeTokens);\\n emit Transfer(borrower, address(this), vars.protocolSeizeTokens);\\n emit ReservesAdded(address(this), vars.protocolSeizeAmount, vars.totalReservesNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n\\n /*** Admin Functions ***/\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPendingAdmin(address payable newPendingAdmin) external returns (uint) {\\n // Check caller = admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\\n }\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptAdmin() external returns (uint) {\\n // Check caller is pendingAdmin and pendingAdmin \\u2260 address(0)\\n if (msg.sender != pendingAdmin || msg.sender == address(0)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = address(0);\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setComptroller(ComptrollerInterface newComptroller) public returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_COMPTROLLER_OWNER_CHECK);\\n }\\n\\n ComptrollerInterface oldComptroller = comptroller;\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(oldComptroller, newComptroller);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh\\n * @dev Admin function to accrue interest and set a new reserve factor\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setReserveFactor(uint newReserveFactorMantissa) external nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\\n * @dev Admin function to set a new reserve factor\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_RESERVE_FACTOR_ADMIN_CHECK);\\n }\\n\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring from msg.sender\\n * @param addAmount Amount of addition to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to admin\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _reduceReserves(uint reduceAmount) external nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to admin\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _reduceReservesFresh(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's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n totalReservesNew = totalReserves - reduceAmount;\\n // We checked reduceAmount <= totalReserves above, so this should never revert.\\n require(totalReservesNew <= 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't be sure if side effects occurred.\\n doTransferOut(admin, reduceAmount);\\n\\n emit ReservesReduced(admin, reduceAmount, totalReservesNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Admin function to accrue interest and update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel);\\n }\\n\\n /**\\n * @notice updates the interest rate model (*requires fresh interest accrual)\\n * @dev Admin function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal returns (uint) {\\n\\n // Used to store old model for use in the event that is emitted on success\\n InterestRateModel oldInterestRateModel;\\n\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_INTEREST_RATE_MODEL_OWNER_CHECK);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Track the market's current interest rate model\\n oldInterestRateModel = interestRateModel;\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view returns (uint);\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure tather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal;\\n\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n}\\n\",\"keccak256\":\"0x436ec2e309682995f8a82dfdd9e8f75928599c10a9a680dddbee6c275014008d\"},\"contracts/CTokenInterfaces.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./InterestRateModel.sol\\\";\\nimport \\\"./EIP20NonStandardInterface.sol\\\";\\n\\ncontract CTokenStorage {\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-cToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModel public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first CTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping (address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping (address => mapping (address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Share of seized collateral that is added to reserves\\n */\\n uint public constant protocolSeizeShareMantissa = 2.8e16; //2.8%\\n\\n}\\n\\ncontract CTokenInterface is CTokenStorage {\\n /**\\n * @notice Indicator that this is a CToken contract (for inspection)\\n */\\n bool public constant isCToken = true;\\n\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(address liquidator, address borrower, uint repayAmount, address cTokenCollateral, uint seizeTokens);\\n\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin is updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(InterestRateModel oldInterestRateModel, InterestRateModel newInterestRateModel);\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address admin, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Failure event\\n */\\n event Failure(uint error, uint info, uint detail);\\n\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external returns (bool);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function approve(address spender, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function balanceOfUnderlying(address owner) external returns (uint);\\n function getAccountSnapshot(address account) external view returns (uint, uint, uint, uint);\\n function borrowRatePerBlock() external view returns (uint);\\n function supplyRatePerBlock() external view returns (uint);\\n function totalBorrowsCurrent() external returns (uint);\\n function borrowBalanceCurrent(address account) external returns (uint);\\n function borrowBalanceStored(address account) public view returns (uint);\\n function exchangeRateCurrent() public returns (uint);\\n function exchangeRateStored() public view returns (uint);\\n function getCash() external view returns (uint);\\n function accrueInterest() public returns (uint);\\n function seize(address liquidator, address borrower, uint seizeTokens) external returns (uint);\\n\\n\\n /*** Admin Functions ***/\\n\\n function _setPendingAdmin(address payable newPendingAdmin) external returns (uint);\\n function _acceptAdmin() external returns (uint);\\n function _setComptroller(ComptrollerInterface newComptroller) public returns (uint);\\n function _setReserveFactor(uint newReserveFactorMantissa) external returns (uint);\\n function _reduceReserves(uint reduceAmount) external returns (uint);\\n function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint);\\n}\\n\\ncontract CErc20Storage {\\n /**\\n * @notice Underlying asset for this CToken\\n */\\n address public underlying;\\n}\\n\\ncontract CErc20Interface is CErc20Storage {\\n\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n function redeem(uint redeemTokens) external returns (uint);\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n function borrow(uint borrowAmount) external returns (uint);\\n function repayBorrow(uint repayAmount) external returns (uint);\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n function liquidateBorrow(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) external returns (uint);\\n function sweepToken(EIP20NonStandardInterface token) external;\\n\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ncontract CDelegationStorage {\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n}\\n\\ncontract CDelegatorInterface is CDelegationStorage {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(address implementation_, bool allowResign, bytes memory becomeImplementationData) public;\\n}\\n\\ncontract CDelegateInterface is CDelegationStorage {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) public;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() public;\\n}\\n\",\"keccak256\":\"0x963bbf60b4c0b76900b3fcb2db8c8be634934b37b4113f1055e57a308197d21a\"},\"contracts/CarefulMath.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Careful Math\\n * @author Compound\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c = a * b;\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n return (MathError.NO_ERROR, a - b);\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c = a + b;\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\",\"keccak256\":\"0x0647348f27e41d22555d99eebd217dee02a4d737df6accd7cce5347a7487c7de\"},\"contracts/ComptrollerG1.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.sol\\\";\\nimport \\\"./ErrorReporter.sol\\\";\\nimport \\\"./Exponential.sol\\\";\\nimport \\\"./PriceOracle.sol\\\";\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./ComptrollerStorage.sol\\\";\\nimport \\\"./Unitroller.sol\\\";\\n\\n/**\\n * @title Compound's Comptroller Contract\\n * @author Compound\\n * @dev This was the first version of the Comptroller brains.\\n * We keep it so our tests can continue to do the real-life behavior of upgrading from this logic forward.\\n */\\ncontract ComptrollerG1 is ComptrollerV1Storage, ComptrollerInterface, ComptrollerErrorReporter, Exponential {\\n struct Market {\\n /**\\n * @notice Whether or not this market is listed\\n */\\n bool isListed;\\n\\n /**\\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\\n * For instance, 0.9 to allow borrowing 90% of collateral value.\\n * Must be between 0 and 1, and stored as a mantissa.\\n */\\n uint collateralFactorMantissa;\\n\\n /**\\n * @notice Per-market mapping of \\\"accounts in this asset\\\"\\n */\\n mapping(address => bool) accountMembership;\\n }\\n\\n /**\\n * @notice Official mapping of cTokens -> Market metadata\\n * @dev Used e.g. to determine if a market is supported\\n */\\n mapping(address => Market) public markets;\\n\\n /**\\n * @notice Emitted when an admin supports a market\\n */\\n event MarketListed(CToken cToken);\\n\\n /**\\n * @notice Emitted when an account enters a market\\n */\\n event MarketEntered(CToken cToken, address account);\\n\\n /**\\n * @notice Emitted when an account exits a market\\n */\\n event MarketExited(CToken cToken, address account);\\n\\n /**\\n * @notice Emitted when close factor is changed by admin\\n */\\n event NewCloseFactor(uint oldCloseFactorMantissa, uint newCloseFactorMantissa);\\n\\n /**\\n * @notice Emitted when a collateral factor is changed by admin\\n */\\n event NewCollateralFactor(CToken cToken, uint oldCollateralFactorMantissa, uint newCollateralFactorMantissa);\\n\\n /**\\n * @notice Emitted when liquidation incentive is changed by admin\\n */\\n event NewLiquidationIncentive(uint oldLiquidationIncentiveMantissa, uint newLiquidationIncentiveMantissa);\\n\\n /**\\n * @notice Emitted when maxAssets is changed by admin\\n */\\n event NewMaxAssets(uint oldMaxAssets, uint newMaxAssets);\\n\\n /**\\n * @notice Emitted when price oracle is changed\\n */\\n event NewPriceOracle(PriceOracle oldPriceOracle, PriceOracle newPriceOracle);\\n\\n // closeFactorMantissa must be strictly greater than this value\\n uint constant closeFactorMinMantissa = 5e16; // 0.05\\n\\n // closeFactorMantissa must not exceed this value\\n uint constant closeFactorMaxMantissa = 9e17; // 0.9\\n\\n // No collateralFactorMantissa may exceed this value\\n uint constant collateralFactorMaxMantissa = 9e17; // 0.9\\n\\n // liquidationIncentiveMantissa must be no less than this value\\n uint constant liquidationIncentiveMinMantissa = mantissaOne;\\n\\n // liquidationIncentiveMantissa must be no greater than this value\\n uint constant liquidationIncentiveMaxMantissa = 15e17; // 1.5\\n\\n constructor() public {\\n admin = msg.sender;\\n }\\n\\n /*** Assets You Are In ***/\\n\\n /**\\n * @notice Returns the assets an account has entered\\n * @param account The address of the account to pull assets for\\n * @return A dynamic list with the assets the account has entered\\n */\\n function getAssetsIn(address account) external view returns (CToken[] memory) {\\n CToken[] memory assetsIn = accountAssets[account];\\n\\n return assetsIn;\\n }\\n\\n /**\\n * @notice Returns whether the given account is entered in the given asset\\n * @param account The address of the account to check\\n * @param cToken The cToken to check\\n * @return True if the account is in the asset, otherwise false.\\n */\\n function checkMembership(address account, CToken cToken) external view returns (bool) {\\n return markets[address(cToken)].accountMembership[account];\\n }\\n\\n /**\\n * @notice Add assets to be included in account liquidity calculation\\n * @param cTokens The list of addresses of the cToken markets to be enabled\\n * @return Success indicator for whether each corresponding market was entered\\n */\\n function enterMarkets(address[] memory cTokens) public returns (uint[] memory) {\\n uint len = cTokens.length;\\n\\n uint[] memory results = new uint[](len);\\n for (uint i = 0; i < len; i++) {\\n CToken cToken = CToken(cTokens[i]);\\n Market storage marketToJoin = markets[address(cToken)];\\n\\n if (!marketToJoin.isListed) {\\n // if market is not listed, cannot join move along\\n results[i] = uint(Error.MARKET_NOT_LISTED);\\n continue;\\n }\\n\\n if (marketToJoin.accountMembership[msg.sender] == true) {\\n // if already joined, move along\\n results[i] = uint(Error.NO_ERROR);\\n continue;\\n }\\n\\n if (accountAssets[msg.sender].length >= maxAssets) {\\n // if no space, cannot join, move along\\n results[i] = uint(Error.TOO_MANY_ASSETS);\\n continue;\\n }\\n\\n // survived the gauntlet, add to list\\n // NOTE: we store these somewhat redundantly as a significant optimization\\n // this avoids having to iterate through the list for the most common use cases\\n // that is, only when we need to perform liquidity checks\\n // and not whenever we want to check if an account is in a particular market\\n marketToJoin.accountMembership[msg.sender] = true;\\n accountAssets[msg.sender].push(cToken);\\n\\n emit MarketEntered(cToken, msg.sender);\\n\\n results[i] = uint(Error.NO_ERROR);\\n }\\n\\n return results;\\n }\\n\\n /**\\n * @notice Removes asset from sender's account liquidity calculation\\n * @dev Sender must not have an outstanding borrow balance in the asset,\\n * or be providing neccessary collateral for an outstanding borrow.\\n * @param cTokenAddress The address of the asset to be removed\\n * @return Whether or not the account successfully exited the market\\n */\\n function exitMarket(address cTokenAddress) external returns (uint) {\\n CToken cToken = CToken(cTokenAddress);\\n /* Get sender tokensHeld and amountOwed underlying from the cToken */\\n (uint oErr, uint tokensHeld, uint amountOwed, ) = cToken.getAccountSnapshot(msg.sender);\\n require(oErr == 0, \\\"exitMarket: getAccountSnapshot failed\\\"); // semi-opaque error code\\n\\n /* Fail if the sender has a borrow balance */\\n if (amountOwed != 0) {\\n return fail(Error.NONZERO_BORROW_BALANCE, FailureInfo.EXIT_MARKET_BALANCE_OWED);\\n }\\n\\n /* Fail if the sender is not permitted to redeem all of their tokens */\\n uint allowed = redeemAllowedInternal(cTokenAddress, msg.sender, tokensHeld);\\n if (allowed != 0) {\\n return failOpaque(Error.REJECTION, FailureInfo.EXIT_MARKET_REJECTION, allowed);\\n }\\n\\n Market storage marketToExit = markets[address(cToken)];\\n\\n /* Return true if the sender is not already \\u2018in\\u2019 the market */\\n if (!marketToExit.accountMembership[msg.sender]) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Set cToken account membership to false */\\n delete marketToExit.accountMembership[msg.sender];\\n\\n /* Delete cToken from the account\\u2019s list of assets */\\n // load into memory for faster iteration\\n CToken[] memory userAssetList = accountAssets[msg.sender];\\n uint len = userAssetList.length;\\n uint assetIndex = len;\\n for (uint i = 0; i < len; i++) {\\n if (userAssetList[i] == cToken) {\\n assetIndex = i;\\n break;\\n }\\n }\\n\\n // We *must* have found the asset in the list or our redundant data structure is broken\\n assert(assetIndex < len);\\n\\n // copy last item in list to location of item to be removed, reduce length by 1\\n CToken[] storage storedList = accountAssets[msg.sender];\\n storedList[assetIndex] = storedList[storedList.length - 1];\\n storedList.length--;\\n\\n emit MarketExited(cToken, 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 cToken The market to verify the mint against\\n * @param minter The account which would get the minted tokens\\n * @param mintAmount The amount of underlying being supplied to the market in exchange for tokens\\n * @return 0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function mintAllowed(address cToken, address minter, uint mintAmount) external returns (uint) {\\n minter; // currently unused\\n mintAmount; // currently unused\\n\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n // *may include Policy Hook-type checks\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates mint and reverts on rejection. May emit logs.\\n * @param cToken Asset being minted\\n * @param minter The address minting the tokens\\n * @param mintAmount The amount of the underlying asset being minted\\n * @param mintTokens The number of tokens being minted\\n */\\n function mintVerify(address cToken, address minter, uint mintAmount, uint mintTokens) external {\\n cToken; // currently unused\\n minter; // currently unused\\n mintAmount; // currently unused\\n mintTokens; // currently unused\\n\\n if (false) {\\n maxAssets = maxAssets; // not pure\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to redeem tokens in the given market\\n * @param cToken The market to verify the redeem against\\n * @param redeemer The account which would redeem the tokens\\n * @param redeemTokens The number of cTokens to exchange for the underlying asset in the market\\n * @return 0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function redeemAllowed(address cToken, address redeemer, uint redeemTokens) external returns (uint) {\\n return redeemAllowedInternal(cToken, redeemer, redeemTokens);\\n }\\n\\n function redeemAllowedInternal(address cToken, address redeemer, uint redeemTokens) internal view returns (uint) {\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n // *may include Policy Hook-type checks\\n\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!markets[cToken].accountMembership[redeemer]) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n (Error err, , uint shortfall) = getHypotheticalAccountLiquidityInternal(redeemer, CToken(cToken), redeemTokens, 0);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n if (shortfall > 0) {\\n return uint(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates redeem and reverts on rejection. May emit logs.\\n * @param cToken Asset being redeemed\\n * @param redeemer The address redeeming the tokens\\n * @param redeemAmount The amount of the underlying asset being redeemed\\n * @param redeemTokens The number of tokens being redeemed\\n */\\n function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) external {\\n cToken; // currently unused\\n redeemer; // currently unused\\n redeemAmount; // currently unused\\n redeemTokens; // currently unused\\n\\n // Require tokens is zero or amount is also zero\\n if (redeemTokens == 0 && redeemAmount > 0) {\\n revert(\\\"redeemTokens zero\\\");\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to borrow the underlying asset of the given market\\n * @param cToken The market to verify the borrow against\\n * @param borrower The account which would borrow the asset\\n * @param borrowAmount The amount of underlying the account would borrow\\n * @return 0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function borrowAllowed(address cToken, address borrower, uint borrowAmount) external returns (uint) {\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n // *may include Policy Hook-type checks\\n\\n if (!markets[cToken].accountMembership[borrower]) {\\n return uint(Error.MARKET_NOT_ENTERED);\\n }\\n\\n if (oracle.getUnderlyingPrice(CToken(cToken)) == 0) {\\n return uint(Error.PRICE_ERROR);\\n }\\n\\n (Error err, , uint shortfall) = getHypotheticalAccountLiquidityInternal(borrower, CToken(cToken), 0, borrowAmount);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n if (shortfall > 0) {\\n return uint(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates borrow and reverts on rejection. May emit logs.\\n * @param cToken Asset whose underlying is being borrowed\\n * @param borrower The address borrowing the underlying\\n * @param borrowAmount The amount of the underlying asset requested to borrow\\n */\\n function borrowVerify(address cToken, address borrower, uint borrowAmount) external {\\n cToken; // currently unused\\n borrower; // currently unused\\n borrowAmount; // currently unused\\n\\n if (false) {\\n maxAssets = maxAssets; // not pure\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to repay a borrow in the given market\\n * @param cToken The market to verify the repay against\\n * @param payer The account which would repay the asset\\n * @param borrower The account which would borrowed the asset\\n * @param repayAmount The amount of the underlying asset the account would repay\\n * @return 0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function repayBorrowAllowed(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount) external returns (uint) {\\n payer; // currently unused\\n borrower; // currently unused\\n repayAmount; // currently unused\\n\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n // *may include Policy Hook-type checks\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates repayBorrow and reverts on rejection. May emit logs.\\n * @param cToken Asset being repaid\\n * @param payer The address repaying the borrow\\n * @param borrower The address of the borrower\\n * @param repayAmount The amount of underlying being repaid\\n */\\n function repayBorrowVerify(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex) external {\\n cToken; // currently unused\\n payer; // currently unused\\n borrower; // currently unused\\n repayAmount; // currently unused\\n borrowerIndex; // currently unused\\n\\n if (false) {\\n maxAssets = maxAssets; // not pure\\n }\\n }\\n\\n /**\\n * @notice Checks if the liquidation should be allowed to occur\\n * @param cTokenBorrowed Asset which was borrowed by the borrower\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param repayAmount The amount of underlying being repaid\\n */\\n function liquidateBorrowAllowed(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount) external returns (uint) {\\n liquidator; // currently unused\\n borrower; // currently unused\\n repayAmount; // currently unused\\n\\n if (!markets[cTokenBorrowed].isListed || !markets[cTokenCollateral].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n // *may include Policy Hook-type checks\\n\\n /* The borrower must have shortfall in order to be liquidatable */\\n (Error err, , uint shortfall) = getAccountLiquidityInternal(borrower);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n if (shortfall == 0) {\\n return uint(Error.INSUFFICIENT_SHORTFALL);\\n }\\n\\n /* The liquidator may not repay more than what is allowed by the closeFactor */\\n uint borrowBalance = CToken(cTokenBorrowed).borrowBalanceStored(borrower);\\n (MathError mathErr, uint maxClose) = mulScalarTruncate(Exp({mantissa: closeFactorMantissa}), borrowBalance);\\n if (mathErr != MathError.NO_ERROR) {\\n return uint(Error.MATH_ERROR);\\n }\\n if (repayAmount > 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 cTokenBorrowed Asset which was borrowed by the borrower\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param repayAmount The amount of underlying being repaid\\n */\\n function liquidateBorrowVerify(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens) external {\\n cTokenBorrowed; // currently unused\\n cTokenCollateral; // currently unused\\n liquidator; // currently unused\\n borrower; // currently unused\\n repayAmount; // currently unused\\n seizeTokens; // currently unused\\n\\n if (false) {\\n maxAssets = maxAssets; // not pure\\n }\\n }\\n\\n /**\\n * @notice Checks if the seizing of assets should be allowed to occur\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param cTokenBorrowed Asset which was borrowed by the borrower\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param seizeTokens The number of collateral tokens to seize\\n */\\n function seizeAllowed(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external returns (uint) {\\n liquidator; // currently unused\\n borrower; // currently unused\\n seizeTokens; // currently unused\\n\\n if (!markets[cTokenCollateral].isListed || !markets[cTokenBorrowed].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n if (CToken(cTokenCollateral).comptroller() != CToken(cTokenBorrowed).comptroller()) {\\n return uint(Error.COMPTROLLER_MISMATCH);\\n }\\n\\n // *may include Policy Hook-type checks\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates seize and reverts on rejection. May emit logs.\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param cTokenBorrowed Asset which was borrowed by the borrower\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param seizeTokens The number of collateral tokens to seize\\n */\\n function seizeVerify(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external {\\n cTokenCollateral; // currently unused\\n cTokenBorrowed; // currently unused\\n liquidator; // currently unused\\n borrower; // currently unused\\n seizeTokens; // currently unused\\n\\n if (false) {\\n maxAssets = maxAssets; // not pure\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to transfer tokens in the given market\\n * @param cToken The market to verify the transfer against\\n * @param src The account which sources the tokens\\n * @param dst The account which receives the tokens\\n * @param transferTokens The number of cTokens to transfer\\n * @return 0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function transferAllowed(address cToken, address src, address dst, uint transferTokens) external returns (uint) {\\n cToken; // currently unused\\n src; // currently unused\\n dst; // currently unused\\n transferTokens; // currently unused\\n\\n // *may include Policy Hook-type checks\\n\\n // Currently the only consideration is whether or not\\n // the src is allowed to redeem this many tokens\\n return redeemAllowedInternal(cToken, src, transferTokens);\\n }\\n\\n /**\\n * @notice Validates transfer and reverts on rejection. May emit logs.\\n * @param cToken Asset being transferred\\n * @param src The account which sources the tokens\\n * @param dst The account which receives the tokens\\n * @param transferTokens The number of cTokens to transfer\\n */\\n function transferVerify(address cToken, address src, address dst, uint transferTokens) external {\\n cToken; // currently unused\\n src; // currently unused\\n dst; // currently unused\\n transferTokens; // currently unused\\n\\n if (false) {\\n maxAssets = maxAssets; // not pure\\n }\\n }\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n /**\\n * @dev Local vars for avoiding stack-depth limits in calculating account liquidity.\\n * Note that `cTokenBalance` is the number of cTokens the account owns in the market,\\n * whereas `borrowBalance` is the amount of underlying that the account has borrowed.\\n */\\n struct AccountLiquidityLocalVars {\\n uint sumCollateral;\\n uint sumBorrowPlusEffects;\\n uint cTokenBalance;\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n uint oraclePriceMantissa;\\n Exp collateralFactor;\\n Exp exchangeRate;\\n Exp oraclePrice;\\n Exp tokensToEther;\\n }\\n\\n /**\\n * @notice Determine the current account liquidity wrt collateral requirements\\n * @return (possible error code (semi-opaque),\\n account liquidity in excess of collateral requirements,\\n * account shortfall below collateral requirements)\\n */\\n function getAccountLiquidity(address account) public view returns (uint, uint, uint) {\\n (Error err, uint liquidity, uint shortfall) = getHypotheticalAccountLiquidityInternal(account, CToken(0), 0, 0);\\n\\n return (uint(err), liquidity, shortfall);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity wrt collateral requirements\\n * @return (possible error code,\\n account liquidity in excess of collateral requirements,\\n * account shortfall below collateral requirements)\\n */\\n function getAccountLiquidityInternal(address account) internal view returns (Error, uint, uint) {\\n return getHypotheticalAccountLiquidityInternal(account, CToken(0), 0, 0);\\n }\\n\\n /**\\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\\n * @param cTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @dev Note that we calculate the exchangeRateStored for each collateral cToken using stored data,\\n * without calculating accumulated interest.\\n * @return (possible error code,\\n hypothetical account liquidity in excess of collateral requirements,\\n * hypothetical account shortfall below collateral requirements)\\n */\\n function getHypotheticalAccountLiquidityInternal(\\n address account,\\n CToken cTokenModify,\\n uint redeemTokens,\\n uint borrowAmount) internal view returns (Error, uint, uint) {\\n\\n AccountLiquidityLocalVars memory vars; // Holds all our calculation results\\n uint oErr;\\n MathError mErr;\\n\\n // For each asset the account is in\\n CToken[] memory assets = accountAssets[account];\\n for (uint i = 0; i < assets.length; i++) {\\n CToken asset = assets[i];\\n\\n // Read the balances and exchange rate from the cToken\\n (oErr, vars.cTokenBalance, vars.borrowBalance, vars.exchangeRateMantissa) = asset.getAccountSnapshot(account);\\n if (oErr != 0) { // semi-opaque error code, we assume NO_ERROR == 0 is invariant between upgrades\\n return (Error.SNAPSHOT_ERROR, 0, 0);\\n }\\n vars.collateralFactor = Exp({mantissa: markets[address(asset)].collateralFactorMantissa});\\n vars.exchangeRate = Exp({mantissa: vars.exchangeRateMantissa});\\n\\n // Get the normalized price of the asset\\n vars.oraclePriceMantissa = oracle.getUnderlyingPrice(asset);\\n if (vars.oraclePriceMantissa == 0) {\\n return (Error.PRICE_ERROR, 0, 0);\\n }\\n vars.oraclePrice = Exp({mantissa: vars.oraclePriceMantissa});\\n\\n // Pre-compute a conversion factor from tokens -> ether (normalized price value)\\n (mErr, vars.tokensToEther) = mulExp3(vars.collateralFactor, vars.exchangeRate, vars.oraclePrice);\\n if (mErr != MathError.NO_ERROR) {\\n return (Error.MATH_ERROR, 0, 0);\\n }\\n\\n // sumCollateral += tokensToEther * cTokenBalance\\n (mErr, vars.sumCollateral) = mulScalarTruncateAddUInt(vars.tokensToEther, vars.cTokenBalance, 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 cTokenModify\\n if (asset == cTokenModify) {\\n // redeem effect\\n // sumBorrowPlusEffects += tokensToEther * redeemTokens\\n (mErr, vars.sumBorrowPlusEffects) = mulScalarTruncateAddUInt(vars.tokensToEther, redeemTokens, vars.sumBorrowPlusEffects);\\n if (mErr != MathError.NO_ERROR) {\\n return (Error.MATH_ERROR, 0, 0);\\n }\\n\\n // borrow effect\\n // sumBorrowPlusEffects += oraclePrice * borrowAmount\\n (mErr, vars.sumBorrowPlusEffects) = mulScalarTruncateAddUInt(vars.oraclePrice, borrowAmount, vars.sumBorrowPlusEffects);\\n if (mErr != MathError.NO_ERROR) {\\n return (Error.MATH_ERROR, 0, 0);\\n }\\n }\\n }\\n\\n // These are safe, as the underflow condition is checked first\\n if (vars.sumCollateral > vars.sumBorrowPlusEffects) {\\n return (Error.NO_ERROR, vars.sumCollateral - vars.sumBorrowPlusEffects, 0);\\n } else {\\n return (Error.NO_ERROR, 0, vars.sumBorrowPlusEffects - vars.sumCollateral);\\n }\\n }\\n\\n /**\\n * @notice Calculate number of tokens of collateral asset to seize given an underlying amount\\n * @dev Used in liquidation (called in cToken.liquidateBorrowFresh)\\n * @param cTokenBorrowed The address of the borrowed cToken\\n * @param cTokenCollateral The address of the collateral cToken\\n * @param repayAmount The amount of cTokenBorrowed underlying to convert into cTokenCollateral tokens\\n * @return (errorCode, number of cTokenCollateral tokens to be seized in a liquidation)\\n */\\n function liquidateCalculateSeizeTokens(address cTokenBorrowed, address cTokenCollateral, uint repayAmount) external view returns (uint, uint) {\\n /* Read oracle prices for borrowed and collateral markets */\\n uint priceBorrowedMantissa = oracle.getUnderlyingPrice(CToken(cTokenBorrowed));\\n uint priceCollateralMantissa = oracle.getUnderlyingPrice(CToken(cTokenCollateral));\\n if (priceBorrowedMantissa == 0 || priceCollateralMantissa == 0) {\\n return (uint(Error.PRICE_ERROR), 0);\\n }\\n\\n /*\\n * Get the exchange rate and calculate the number of collateral tokens to seize:\\n * seizeAmount = repayAmount * liquidationIncentive * priceBorrowed / priceCollateral\\n * seizeTokens = seizeAmount / exchangeRate\\n * = repayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate)\\n */\\n uint exchangeRateMantissa = CToken(cTokenCollateral).exchangeRateStored(); // Note: reverts on error\\n uint seizeTokens;\\n Exp memory numerator;\\n Exp memory denominator;\\n Exp memory ratio;\\n MathError mathErr;\\n\\n (mathErr, numerator) = mulExp(liquidationIncentiveMantissa, priceBorrowedMantissa);\\n if (mathErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0);\\n }\\n\\n (mathErr, denominator) = mulExp(priceCollateralMantissa, exchangeRateMantissa);\\n if (mathErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0);\\n }\\n\\n (mathErr, ratio) = divExp(numerator, denominator);\\n if (mathErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0);\\n }\\n\\n (mathErr, seizeTokens) = mulScalarTruncate(ratio, repayAmount);\\n if (mathErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0);\\n }\\n\\n return (uint(Error.NO_ERROR), seizeTokens);\\n }\\n\\n /*** Admin Functions ***/\\n\\n /**\\n * @notice Sets a new price oracle for the comptroller\\n * @dev Admin function to set a new price oracle\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPriceOracle(PriceOracle newOracle) public returns (uint) {\\n // Check caller is admin OR currently initialzing as new unitroller implementation\\n if (!adminOrInitializing()) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PRICE_ORACLE_OWNER_CHECK);\\n }\\n\\n // Track the old oracle for the comptroller\\n PriceOracle oldOracle = oracle;\\n\\n // Ensure invoke newOracle.isPriceOracle() returns true\\n // require(newOracle.isPriceOracle(), \\\"oracle method isPriceOracle returned false\\\");\\n\\n // Set comptroller's oracle to newOracle\\n oracle = newOracle;\\n\\n // Emit NewPriceOracle(oldOracle, newOracle)\\n emit NewPriceOracle(oldOracle, newOracle);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets the closeFactor used when liquidating borrows\\n * @dev Admin function to set closeFactor\\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\\n * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function _setCloseFactor(uint newCloseFactorMantissa) external returns (uint256) {\\n // Check caller is admin OR currently initialzing as new unitroller implementation\\n if (!adminOrInitializing()) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_CLOSE_FACTOR_OWNER_CHECK);\\n }\\n\\n Exp memory newCloseFactorExp = Exp({mantissa: newCloseFactorMantissa});\\n Exp memory lowLimit = Exp({mantissa: closeFactorMinMantissa});\\n if (lessThanOrEqualExp(newCloseFactorExp, lowLimit)) {\\n return fail(Error.INVALID_CLOSE_FACTOR, FailureInfo.SET_CLOSE_FACTOR_VALIDATION);\\n }\\n\\n Exp memory highLimit = Exp({mantissa: closeFactorMaxMantissa});\\n if (lessThanExp(highLimit, newCloseFactorExp)) {\\n return fail(Error.INVALID_CLOSE_FACTOR, FailureInfo.SET_CLOSE_FACTOR_VALIDATION);\\n }\\n\\n uint oldCloseFactorMantissa = closeFactorMantissa;\\n closeFactorMantissa = newCloseFactorMantissa;\\n emit NewCloseFactor(oldCloseFactorMantissa, closeFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets the collateralFactor for a market\\n * @dev Admin function to set per-market collateralFactor\\n * @param cToken The market to set the factor on\\n * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18\\n * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function _setCollateralFactor(CToken cToken, uint newCollateralFactorMantissa) external returns (uint256) {\\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(cToken)];\\n if (!market.isListed) {\\n return fail(Error.MARKET_NOT_LISTED, FailureInfo.SET_COLLATERAL_FACTOR_NO_EXISTS);\\n }\\n\\n Exp memory newCollateralFactorExp = Exp({mantissa: newCollateralFactorMantissa});\\n\\n // Check collateral factor <= 0.9\\n Exp memory highLimit = Exp({mantissa: collateralFactorMaxMantissa});\\n if (lessThanExp(highLimit, newCollateralFactorExp)) {\\n return fail(Error.INVALID_COLLATERAL_FACTOR, FailureInfo.SET_COLLATERAL_FACTOR_VALIDATION);\\n }\\n\\n // If collateral factor != 0, fail if price == 0\\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(cToken) == 0) {\\n return fail(Error.PRICE_ERROR, FailureInfo.SET_COLLATERAL_FACTOR_WITHOUT_PRICE);\\n }\\n\\n // Set market's collateral factor to new collateral factor, remember old value\\n uint oldCollateralFactorMantissa = market.collateralFactorMantissa;\\n market.collateralFactorMantissa = newCollateralFactorMantissa;\\n\\n // Emit event with asset, old collateral factor, and new collateral factor\\n emit NewCollateralFactor(cToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets maxAssets which controls how many markets can be entered\\n * @dev Admin function to set maxAssets\\n * @param newMaxAssets New max assets\\n * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function _setMaxAssets(uint newMaxAssets) external returns (uint) {\\n // Check caller is admin OR currently initialzing as new unitroller implementation\\n if (!adminOrInitializing()) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_MAX_ASSETS_OWNER_CHECK);\\n }\\n\\n uint oldMaxAssets = maxAssets;\\n maxAssets = newMaxAssets;\\n emit NewMaxAssets(oldMaxAssets, newMaxAssets);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets liquidationIncentive\\n * @dev Admin function to set liquidationIncentive\\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\\n * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function _setLiquidationIncentive(uint newLiquidationIncentiveMantissa) external returns (uint) {\\n // Check caller is admin OR currently initialzing as new unitroller implementation\\n if (!adminOrInitializing()) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_LIQUIDATION_INCENTIVE_OWNER_CHECK);\\n }\\n\\n // Check de-scaled 1 <= newLiquidationDiscount <= 1.5\\n Exp memory newLiquidationIncentive = Exp({mantissa: newLiquidationIncentiveMantissa});\\n Exp memory minLiquidationIncentive = Exp({mantissa: liquidationIncentiveMinMantissa});\\n if (lessThanExp(newLiquidationIncentive, minLiquidationIncentive)) {\\n return fail(Error.INVALID_LIQUIDATION_INCENTIVE, FailureInfo.SET_LIQUIDATION_INCENTIVE_VALIDATION);\\n }\\n\\n Exp memory maxLiquidationIncentive = Exp({mantissa: liquidationIncentiveMaxMantissa});\\n if (lessThanExp(maxLiquidationIncentive, newLiquidationIncentive)) {\\n return fail(Error.INVALID_LIQUIDATION_INCENTIVE, FailureInfo.SET_LIQUIDATION_INCENTIVE_VALIDATION);\\n }\\n\\n // Save current value for use in log\\n uint oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa;\\n\\n // Set liquidation incentive to new incentive\\n liquidationIncentiveMantissa = newLiquidationIncentiveMantissa;\\n\\n // Emit event with old incentive, new incentive\\n emit NewLiquidationIncentive(oldLiquidationIncentiveMantissa, newLiquidationIncentiveMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Add the market to the markets mapping and set it as listed\\n * @dev Admin function to set isListed and add support for the market\\n * @param cToken The address of the market (token) to list\\n * @return uint 0=success, otherwise a failure. (See enum Error for details)\\n */\\n function _supportMarket(CToken cToken) external returns (uint) {\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SUPPORT_MARKET_OWNER_CHECK);\\n }\\n\\n if (markets[address(cToken)].isListed) {\\n return fail(Error.MARKET_ALREADY_LISTED, FailureInfo.SUPPORT_MARKET_EXISTS);\\n }\\n\\n cToken.isCToken(); // Sanity check to make sure its really a CToken\\n\\n markets[address(cToken)] = Market({isListed: true, collateralFactorMantissa: 0});\\n emit MarketListed(cToken);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n function _become(Unitroller unitroller, PriceOracle _oracle, uint _closeFactorMantissa, uint _maxAssets, bool reinitializing) public {\\n require(msg.sender == unitroller.admin(), \\\"only unitroller admin can change brains\\\");\\n uint changeStatus = unitroller._acceptImplementation();\\n\\n require(changeStatus == 0, \\\"change not authorized\\\");\\n\\n if (!reinitializing) {\\n ComptrollerG1 freshBrainedComptroller = ComptrollerG1(address(unitroller));\\n\\n // Ensure invoke _setPriceOracle() = 0\\n uint err = freshBrainedComptroller._setPriceOracle(_oracle);\\n require (err == uint(Error.NO_ERROR), \\\"set price oracle error\\\");\\n\\n // Ensure invoke _setCloseFactor() = 0\\n err = freshBrainedComptroller._setCloseFactor(_closeFactorMantissa);\\n require (err == uint(Error.NO_ERROR), \\\"set close factor error\\\");\\n\\n // Ensure invoke _setMaxAssets() = 0\\n err = freshBrainedComptroller._setMaxAssets(_maxAssets);\\n require (err == uint(Error.NO_ERROR), \\\"set max asssets error\\\");\\n\\n // Ensure invoke _setLiquidationIncentive(liquidationIncentiveMinMantissa) = 0\\n err = freshBrainedComptroller._setLiquidationIncentive(liquidationIncentiveMinMantissa);\\n require (err == uint(Error.NO_ERROR), \\\"set liquidation incentive error\\\");\\n }\\n }\\n\\n /**\\n * @dev Check that caller is admin or this contract is initializing itself as\\n * the new implementation.\\n * There should be no way to satisfy msg.sender == comptrollerImplementaiton\\n * without tx.origin also being admin, but both are included for extra safety\\n */\\n function adminOrInitializing() internal view returns (bool) {\\n bool initializing = (\\n msg.sender == comptrollerImplementation\\n &&\\n //solium-disable-next-line security/no-tx-origin\\n tx.origin == admin\\n );\\n bool isAdmin = msg.sender == admin;\\n return isAdmin || initializing;\\n }\\n}\",\"keccak256\":\"0xe1515e04e6d62f384be5f47a334c558ddd98a0b96cfd64b7a3d012775412d91e\"},\"contracts/ComptrollerInterface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\ncontract ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n bool public constant isComptroller = true;\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata cTokens) external returns (uint[] memory);\\n function exitMarket(address cToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address cToken, address minter, uint mintAmount) external returns (uint);\\n function mintVerify(address cToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address cToken, address redeemer, uint redeemTokens) external returns (uint);\\n function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address cToken, address borrower, uint borrowAmount) external returns (uint);\\n function borrowVerify(address cToken, address borrower, uint borrowAmount) external;\\n\\n function repayBorrowAllowed(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount) external returns (uint);\\n function repayBorrowVerify(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex) external;\\n\\n function liquidateBorrowAllowed(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount) external returns (uint);\\n function liquidateBorrowVerify(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens) external;\\n\\n function seizeAllowed(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external returns (uint);\\n function seizeVerify(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external;\\n\\n function transferAllowed(address cToken, address src, address dst, uint transferTokens) external returns (uint);\\n function transferVerify(address cToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n uint repayAmount) external view returns (uint, uint);\\n}\\n\",\"keccak256\":\"0xede7670d2dd7b25d0187aecd2c28b7b5ca7d7c1bdac144fbedecf5d4bdd92a6b\"},\"contracts/ComptrollerStorage.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.sol\\\";\\nimport \\\"./PriceOracle.sol\\\";\\n\\ncontract UnitrollerAdminStorage {\\n /**\\n * @notice Administrator for this contract\\n */\\n address public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address public pendingAdmin;\\n\\n /**\\n * @notice Active brains of Unitroller\\n */\\n address public comptrollerImplementation;\\n\\n /**\\n * @notice Pending brains of Unitroller\\n */\\n address public pendingComptrollerImplementation;\\n}\\n\\ncontract ComptrollerV1Storage is UnitrollerAdminStorage {\\n\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n PriceOracle public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives\\n */\\n uint public liquidationIncentiveMantissa;\\n\\n /**\\n * @notice Max number of assets a single account can participate in (borrow or use as collateral)\\n */\\n uint public maxAssets;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\\n */\\n mapping(address => CToken[]) public accountAssets;\\n\\n}\\n\\ncontract ComptrollerV2Storage is ComptrollerV1Storage {\\n struct Market {\\n /// @notice Whether or not this market is listed\\n bool isListed;\\n\\n /**\\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\\n * For instance, 0.9 to allow borrowing 90% of collateral value.\\n * Must be between 0 and 1, and stored as a mantissa.\\n */\\n uint collateralFactorMantissa;\\n\\n /// @notice Per-market mapping of \\\"accounts in this asset\\\"\\n mapping(address => bool) accountMembership;\\n\\n /// @notice Whether or not this market receives COMP\\n bool isComped;\\n }\\n\\n /**\\n * @notice Official mapping of cTokens -> Market metadata\\n * @dev Used e.g. to determine if a market is supported\\n */\\n mapping(address => Market) public markets;\\n\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n * Actions which allow users to remove their own assets cannot be paused.\\n * Liquidation / seizing / transfer can only be paused globally, not by market.\\n */\\n address public pauseGuardian;\\n bool public _mintGuardianPaused;\\n bool public _borrowGuardianPaused;\\n bool public transferGuardianPaused;\\n bool public seizeGuardianPaused;\\n mapping(address => bool) public mintGuardianPaused;\\n mapping(address => bool) public borrowGuardianPaused;\\n}\\n\\ncontract ComptrollerV3Storage is ComptrollerV2Storage {\\n struct CompMarketState {\\n /// @notice The market's last updated compBorrowIndex or compSupplyIndex\\n uint224 index;\\n\\n /// @notice The block number the index was last updated at\\n uint32 block;\\n }\\n\\n /// @notice A list of all markets\\n CToken[] public allMarkets;\\n\\n /// @notice The rate at which the flywheel distributes COMP, per block\\n uint public compRate;\\n\\n /// @notice The portion of compRate that each market currently receives\\n mapping(address => uint) public compSpeeds;\\n\\n /// @notice The COMP market supply state for each market\\n mapping(address => CompMarketState) public compSupplyState;\\n\\n /// @notice The COMP market borrow state for each market\\n mapping(address => CompMarketState) public compBorrowState;\\n\\n /// @notice The COMP borrow index for each market for each supplier as of the last time they accrued COMP\\n mapping(address => mapping(address => uint)) public compSupplierIndex;\\n\\n /// @notice The COMP borrow index for each market for each borrower as of the last time they accrued COMP\\n mapping(address => mapping(address => uint)) public compBorrowerIndex;\\n\\n /// @notice The COMP accrued but not yet transferred to each user\\n mapping(address => uint) public compAccrued;\\n}\\n\\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\\n // @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\\n address public borrowCapGuardian;\\n\\n // @notice Borrow caps enforced by borrowAllowed for each cToken address. Defaults to zero which corresponds to unlimited borrowing.\\n mapping(address => uint) public borrowCaps;\\n}\\n\\ncontract ComptrollerV5Storage is ComptrollerV4Storage {\\n /// @notice The portion of COMP that each contributor receives per block\\n mapping(address => uint) public compContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's COMP rewards have been allocated\\n mapping(address => uint) public lastContributorBlock;\\n}\\n\",\"keccak256\":\"0x5db970485549f493618b5e36bfd4d799d4f8701a136bf71ed6e0117e1ed8c254\"},\"contracts/EIP20Interface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title ERC 20 Token Standard Interface\\n * https://eips.ethereum.org/EIPS/eip-20\\n */\\ninterface EIP20Interface {\\n function name() external view returns (string memory);\\n function symbol() external view returns (string memory);\\n function decimals() external view returns (uint8);\\n\\n /**\\n * @notice Get the total number of tokens in circulation\\n * @return The supply of tokens\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @notice Gets the balance of the specified address\\n * @param owner The address from which the balance will be retrieved\\n * @return The balance\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transfer(address dst, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferFrom(address src, address dst, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (-1 means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (-1 means infinite)\\n */\\n function allowance(address owner, address spender) external view returns (uint256 remaining);\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n}\\n\",\"keccak256\":\"0xfd8ed2eac6d0b4d9ee6b32628ba68bae17544b66f190a5f7ce0c6ad024579dc8\"},\"contracts/EIP20NonStandardInterface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title EIP20NonStandardInterface\\n * @dev Version of ERC20 with no return values for `transfer` and `transferFrom`\\n * See https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\\n */\\ninterface EIP20NonStandardInterface {\\n\\n /**\\n * @notice Get the total number of tokens in circulation\\n * @return The supply of tokens\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @notice Gets the balance of the specified address\\n * @param owner The address from which the balance will be retrieved\\n * @return The balance\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n ///\\n /// !!!!!!!!!!!!!!\\n /// !!! NOTICE !!! `transfer` does not return a value, in violation of the ERC-20 specification\\n /// !!!!!!!!!!!!!!\\n ///\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n */\\n function transfer(address dst, uint256 amount) external;\\n\\n ///\\n /// !!!!!!!!!!!!!!\\n /// !!! NOTICE !!! `transferFrom` does not return a value, in violation of the ERC-20 specification\\n /// !!!!!!!!!!!!!!\\n ///\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n */\\n function transferFrom(address src, address dst, uint256 amount) external;\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent\\n */\\n function allowance(address owner, address spender) external view returns (uint256 remaining);\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n}\\n\",\"keccak256\":\"0x9719f12e4b80b51147ac195553a198cf8b0c516e7e4d04fc324a23ed15cbafb2\"},\"contracts/ErrorReporter.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\ncontract ComptrollerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\",\"keccak256\":\"0x5179afb1071c0fd555e5c1f1d2565f72dbe1740cc3dd02f6e52037f150afc5c9\"},\"contracts/Exponential.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CarefulMath.sol\\\";\\nimport \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @dev Legacy contract for compatibility reasons with existing contracts that still use MathError\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: rational}));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({mantissa: result}));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({mantissa: result}));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: scaledMantissa}));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: descaledMantissa}));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) pure internal returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({mantissa: 0}));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({mantissa: product}));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) pure internal returns (MathError, Exp memory) {\\n return mulExp(Exp({mantissa: a}), Exp({mantissa: b}));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) pure internal returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6ff054d65a0289dbb43c9f437d6909f9cf1207c9b8f984b3cb8e97a9de76a434\"},\"contracts/ExponentialNoError.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\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 Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) pure internal returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) pure internal returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) pure internal returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) pure internal returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) pure internal returns (uint224) {\\n require(n < 2**224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) pure internal returns (uint32) {\\n require(n < 2**32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: add_(a.mantissa, b.mantissa)});\\n }\\n\\n function add_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: add_(a.mantissa, b.mantissa)});\\n }\\n\\n function add_(uint a, uint b) pure internal returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: sub_(a.mantissa, b.mantissa)});\\n }\\n\\n function sub_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: sub_(a.mantissa, b.mantissa)});\\n }\\n\\n function sub_(uint a, uint b) pure internal returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: mul_(a.mantissa, b.mantissa) / expScale});\\n }\\n\\n function mul_(Exp memory a, uint b) pure internal returns (Exp memory) {\\n return Exp({mantissa: mul_(a.mantissa, b)});\\n }\\n\\n function mul_(uint a, Exp memory b) pure internal returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: mul_(a.mantissa, b.mantissa) / doubleScale});\\n }\\n\\n function mul_(Double memory a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: mul_(a.mantissa, b)});\\n }\\n\\n function mul_(uint a, Double memory b) pure internal returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) pure internal returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) pure internal 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) pure internal returns (Exp memory) {\\n return Exp({mantissa: div_(mul_(a.mantissa, expScale), b.mantissa)});\\n }\\n\\n function div_(Exp memory a, uint b) pure internal returns (Exp memory) {\\n return Exp({mantissa: div_(a.mantissa, b)});\\n }\\n\\n function div_(uint a, Exp memory b) pure internal returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa)});\\n }\\n\\n function div_(Double memory a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(a.mantissa, b)});\\n }\\n\\n function div_(uint a, Double memory b) pure internal returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) pure internal returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(mul_(a, doubleScale), b)});\\n }\\n}\\n\",\"keccak256\":\"0x7cb184b7cee71a5e707053dfba7eebbd46f11974004028100510ccce19b6694d\"},\"contracts/InterestRateModel.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Compound's InterestRateModel Interface\\n * @author Compound\\n */\\ncontract InterestRateModel {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint cash, uint borrows, uint reserves) external view returns (uint);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) external view returns (uint);\\n\\n}\\n\",\"keccak256\":\"0x929282d73c79e6d700ebe79f9fafc1e414b3848acff5a56d6740afd1dc908678\"},\"contracts/PriceOracle.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.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 cToken asset\\n * @param cToken The cToken to get the underlying price of\\n * @return The underlying asset price mantissa (scaled by 1e18).\\n * Zero means the price is unavailable.\\n */\\n function getUnderlyingPrice(CToken cToken) external view returns (uint);\\n}\\n\",\"keccak256\":\"0xe79ebc23bba508eb2479e7b3340abf566da1ab62131f106aee1aac3dc53816ef\"},\"contracts/Unitroller.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ErrorReporter.sol\\\";\\nimport \\\"./ComptrollerStorage.sol\\\";\\n/**\\n * @title ComptrollerCore\\n * @dev Storage for the comptroller is at this address, while execution is delegated to the `comptrollerImplementation`.\\n * CTokens should reference this contract as their comptroller.\\n */\\ncontract Unitroller is UnitrollerAdminStorage, ComptrollerErrorReporter {\\n\\n /**\\n * @notice Emitted when pendingComptrollerImplementation is changed\\n */\\n event NewPendingImplementation(address oldPendingImplementation, address newPendingImplementation);\\n\\n /**\\n * @notice Emitted when pendingComptrollerImplementation is accepted, which means comptroller implementation is updated\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Emitted when pendingAdmin is accepted, which means admin is updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n constructor() public {\\n // Set admin to caller\\n admin = msg.sender;\\n }\\n\\n /*** Admin Functions ***/\\n function _setPendingImplementation(address newPendingImplementation) public returns (uint) {\\n\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_IMPLEMENTATION_OWNER_CHECK);\\n }\\n\\n address oldPendingImplementation = pendingComptrollerImplementation;\\n\\n pendingComptrollerImplementation = newPendingImplementation;\\n\\n emit NewPendingImplementation(oldPendingImplementation, pendingComptrollerImplementation);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts new implementation of comptroller. msg.sender must be pendingImplementation\\n * @dev Admin function for new implementation to accept it's role as implementation\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptImplementation() public returns (uint) {\\n // Check caller is pendingImplementation and pendingImplementation \\u2260 address(0)\\n if (msg.sender != pendingComptrollerImplementation || pendingComptrollerImplementation == address(0)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldImplementation = comptrollerImplementation;\\n address oldPendingImplementation = pendingComptrollerImplementation;\\n\\n comptrollerImplementation = pendingComptrollerImplementation;\\n\\n pendingComptrollerImplementation = address(0);\\n\\n emit NewImplementation(oldImplementation, comptrollerImplementation);\\n emit NewPendingImplementation(oldPendingImplementation, pendingComptrollerImplementation);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPendingAdmin(address newPendingAdmin) public returns (uint) {\\n // Check caller = admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\\n }\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptAdmin() public returns (uint) {\\n // Check caller is pendingAdmin and pendingAdmin \\u2260 address(0)\\n if (msg.sender != pendingAdmin || msg.sender == address(0)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = address(0);\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return 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 () payable external {\\n // delegate all other functions to current implementation\\n (bool success, ) = comptrollerImplementation.delegatecall(msg.data);\\n\\n assembly {\\n let free_mem_ptr := mload(0x40)\\n returndatacopy(free_mem_ptr, 0, returndatasize)\\n\\n switch success\\n case 0 { revert(free_mem_ptr, returndatasize) }\\n default { return(free_mem_ptr, returndatasize) }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x51f81451eab9d5c4849507e724f2b2c53e41f54e5359fdbeae89432a727c16df\"},\"tests/Contracts/ComptrollerScenarioG1.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"../../contracts/ComptrollerG1.sol\\\";\\nimport \\\"../../contracts/PriceOracle.sol\\\";\\n\\n// XXX we should delete G1 everything...\\n// requires fork/deploy bytecode tests\\n\\ncontract ComptrollerScenarioG1 is ComptrollerG1 {\\n uint public blockNumber;\\n\\n constructor() ComptrollerG1() public {}\\n\\n function membershipLength(CToken cToken) public view returns (uint) {\\n return accountAssets[address(cToken)].length;\\n }\\n\\n function fastForward(uint blocks) public returns (uint) {\\n blockNumber += blocks;\\n\\n return blockNumber;\\n }\\n\\n function setBlockNumber(uint number) public {\\n blockNumber = number;\\n }\\n\\n function _become(\\n Unitroller unitroller,\\n PriceOracle _oracle,\\n uint _closeFactorMantissa,\\n uint _maxAssets,\\n bool reinitializing) public {\\n super._become(unitroller, _oracle, _closeFactorMantissa, _maxAssets, reinitializing);\\n }\\n\\n function getHypotheticalAccountLiquidity(\\n address account,\\n address cTokenModify,\\n uint redeemTokens,\\n uint borrowAmount) public view returns (uint, uint, uint) {\\n (Error err, uint liquidity, uint shortfall) =\\n super.getHypotheticalAccountLiquidityInternal(account, CToken(cTokenModify), redeemTokens, borrowAmount);\\n return (uint(err), liquidity, shortfall);\\n }\\n\\n function unlist(CToken cToken) public {\\n markets[address(cToken)].isListed = false;\\n }\\n}\\n\",\"keccak256\":\"0x1a2cc15699951e30a9190a7d36bff2ea4282f309e24a05aa1eabe4fa2330bbb3\"}},\"version\":1}" + }, + "tests/Contracts/ComptrollerScenarioG2.sol:ComptrollerScenarioG2": { + "abi": "[{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"action\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"pauseState\",\"type\":\"bool\"}],\"name\":\"ActionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"action\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"pauseState\",\"type\":\"bool\"}],\"name\":\"ActionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketEntered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketExited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"MarketListed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCloseFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCloseFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCollateralFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCollateralFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldLiquidationIncentiveMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"NewLiquidationIncentive\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMaxAssets\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMaxAssets\",\"type\":\"uint256\"}],\"name\":\"NewMaxAssets\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldPauseGuardian\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"NewPauseGuardian\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"oldPriceOracle\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"newPriceOracle\",\"type\":\"address\"}],\"name\":\"NewPriceOracle\",\"type\":\"event\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract Unitroller\",\"name\":\"unitroller\",\"type\":\"address\"}],\"name\":\"_become\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setBorrowPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCloseFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCollateralFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"_setLiquidationIncentive\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newMaxAssets\",\"type\":\"uint256\"}],\"name\":\"_setMaxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setMintPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"_setPauseGuardian\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"newOracle\",\"type\":\"address\"}],\"name\":\"_setPriceOracle\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setSeizePaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setTransferPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"_supportMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"blockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"checkMembership\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"enterMarkets\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenAddress\",\"type\":\"address\"}],\"name\":\"exitMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blocks\",\"type\":\"uint256\"}],\"name\":\"fastForward\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAssetsIn\",\"outputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenModify\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"getHypotheticalAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"isComptroller\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateCalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"liquidationIncentiveMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"markets\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isComped\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"mintAmount\",\"type\":\"uint256\"}],\"name\":\"mintAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualMintAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"mintTokens\",\"type\":\"uint256\"}],\"name\":\"mintVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"repayBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowerIndex\",\"type\":\"uint256\"}],\"name\":\"repayBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"seizeGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"}],\"name\":\"setBlockNumber\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"transferGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + "bin": "608060405234801561001057600080fd5b50600080546001600160a01b031916331790556135df806100326000396000f3fe608060405234801561001057600080fd5b506004361061035c5760003560e01c8063731f0c2b116101d3578063c299823811610104578063e4028eee116100a2578063eabe7d911161007c578063eabe7d9114610bf3578063ede4edd014610c29578063f851a44014610c4f578063fccbe7f614610c575761035c565b8063e4028eee14610bb7578063e6653f3d14610be3578063e875544614610beb5761035c565b8063d9226ced116100de578063d9226ced14610b30578063da3d454c14610b4d578063dce1544914610b83578063dcfbc0c714610baf5761035c565b8063c2998238146109f8578063c488847b14610a9b578063d02f735114610aea5761035c565b806394b2294b11610171578063abfceffc1161014b578063abfceffc14610936578063ac0b0bb7146109ac578063bb82aa5e146109b4578063bdcdc258146109bc5761035c565b806394b2294b146108eb578063a76b3fda146108f3578063a8c3c850146109195761035c565b806387f76303116101ad57806387f763031461084e5780638e8f294b146108565780638ebf63641461089e578063929fe9a1146108bd5761035c565b8063731f0c2b146108185780637d3ab61a1461083e5780637dc0d1d0146108465761035c565b80634ada90af116102ad5780635c7786051161024b5780635fc7e71e116102255780635fc7e71e1461072a5780636a56947e146107705780636d154ea5146107ac5780636d35bf91146107d25761035c565b80635c778605146106a85780635ec88c79146106de5780635f5af1aa146107045761035c565b80634fd42e17116102875780634fd42e171461062157806351dff9891461063e57806355ee1fe11461067a57806357e871e7146106a05761035c565b80634ada90af146105895780634e79238f146105915780634ef4c3e1146105eb5761035c565b8063267822471161031a5780633bcf7ec1116102f45780633bcf7ec1146104cb5780633c94786f146104f957806341c728b91461050157806347ef3b3b1461053d5761035c565b806326782247146104875780632d70db781461048f578063317b0b77146104ae5761035c565b80627e3dd21461036157806318c882a51461037d5780631d504dc6146103ab5780631ededc91146103d357806324008a621461041557806324a3d62214610463575b600080fd5b610369610c74565b604080519115158252519081900360200190f35b6103696004803603604081101561039357600080fd5b506001600160a01b0381351690602001351515610c79565b6103d1600480360360208110156103c157600080fd5b50356001600160a01b0316610e19565b005b6103d1600480360360a08110156103e957600080fd5b506001600160a01b03813581169160208101358216916040820135169060608101359060800135610f7e565b6104516004803603608081101561042b57600080fd5b506001600160a01b03813581169160208101358216916040820135169060600135610f85565b60408051918252519081900360200190f35b61046b610fbb565b604080516001600160a01b039092168252519081900360200190f35b61046b610fca565b610369600480360360208110156104a557600080fd5b50351515610fd9565b610451600480360360208110156104c457600080fd5b5035611113565b610369600480360360408110156104e157600080fd5b506001600160a01b0381351690602001351515611224565b6103696113bf565b6103d16004803603608081101561051757600080fd5b506001600160a01b038135811691602081013590911690604081013590606001356113cf565b6103d1600480360360c081101561055357600080fd5b506001600160a01b0381358116916020810135821691604082013581169160608101359091169060808101359060a001356113d5565b6104516113dd565b6105cd600480360360808110156105a757600080fd5b506001600160a01b038135811691602081013590911690604081013590606001356113e3565b60408051938452602084019290925282820152519081900360600190f35b6104516004803603606081101561060157600080fd5b506001600160a01b0381358116916020810135909116906040013561141d565b6104516004803603602081101561063757600080fd5b50356114b3565b6103d16004803603608081101561065457600080fd5b506001600160a01b038135811691602081013590911690604081013590606001356115a7565b6104516004803603602081101561069057600080fd5b50356001600160a01b03166115fb565b610451611682565b6103d1600480360360608110156106be57600080fd5b506001600160a01b03813581169160208101359091169060400135611688565b6105cd600480360360208110156106f457600080fd5b50356001600160a01b031661168d565b6104516004803603602081101561071a57600080fd5b50356001600160a01b03166116c2565b610451600480360360a081101561074057600080fd5b506001600160a01b0381358116916020810135821691604082013581169160608101359091169060800135611746565b6103d16004803603608081101561078657600080fd5b506001600160a01b038135811691602081013582169160408201351690606001356113cf565b610369600480360360208110156107c257600080fd5b50356001600160a01b03166118cd565b6103d1600480360360a08110156107e857600080fd5b506001600160a01b0381358116916020810135821691604082013581169160608101359091169060800135610f7e565b6103696004803603602081101561082e57600080fd5b50356001600160a01b03166118e2565b61046b6118f7565b61046b611906565b610369611915565b61087c6004803603602081101561086c57600080fd5b50356001600160a01b0316611925565b6040805193151584526020840192909252151582820152519081900360600190f35b610369600480360360208110156108b457600080fd5b5035151561194b565b610369600480360360408110156108d357600080fd5b506001600160a01b0381358116916020013516611a84565b610451611ab7565b6104516004803603602081101561090957600080fd5b50356001600160a01b0316611abd565b6103d16004803603602081101561092f57600080fd5b5035611c0b565b61095c6004803603602081101561094c57600080fd5b50356001600160a01b0316611c10565b60408051602080825283518183015283519192839290830191858101910280838360005b83811015610998578181015183820152602001610980565b505050509050019250505060405180910390f35b610369611c99565b61046b611ca9565b610451600480360360808110156109d257600080fd5b506001600160a01b03813581169160208101358216916040820135169060600135611cb8565b61095c60048036036020811015610a0e57600080fd5b810190602081018135640100000000811115610a2957600080fd5b820183602082011115610a3b57600080fd5b80359060200191846020830284011164010000000083111715610a5d57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550611d1a945050505050565b610ad160048036036060811015610ab157600080fd5b506001600160a01b03813581169160208101359091169060400135611db1565b6040805192835260208301919091528051918290030190f35b610451600480360360a0811015610b0057600080fd5b506001600160a01b0381358116916020810135821691604082013581169160608101359091169060800135612026565b61045160048036036020811015610b4657600080fd5b50356121bd565b61045160048036036060811015610b6357600080fd5b506001600160a01b03813581169160208101359091169060400135612226565b61046b60048036036040811015610b9957600080fd5b506001600160a01b038135169060200135612473565b61046b6124a8565b61045160048036036040811015610bcd57600080fd5b506001600160a01b0381351690602001356124b7565b610369612667565b610451612677565b61045160048036036060811015610c0957600080fd5b506001600160a01b0381358116916020810135909116906040013561267d565b61045160048036036020811015610c3f57600080fd5b50356001600160a01b031661268a565b61046b61299d565b61045160048036036020811015610c6d57600080fd5b50356129ac565b600181565b6001600160a01b03821660009081526009602052604081205460ff16610cd05760405162461bcd60e51b81526004018080602001828103825260288152602001806135106028913960400191505060405180910390fd5b600a546001600160a01b0316331480610cf357506000546001600160a01b031633145b610d2e5760405162461bcd60e51b81526004018080602001828103825260278152602001806135386027913960400191505060405180910390fd5b6000546001600160a01b0316331480610d4957506001821515145b610d93576040805162461bcd60e51b81526020600482015260166024820152756f6e6c792061646d696e2063616e20756e706175736560501b604482015290519081900360640190fd5b6001600160a01b0383166000818152600c6020908152604091829020805486151560ff199091168117909155825193845283830152606090830181905260069083015265426f72726f7760d01b6080830152517f71aec636243f9709bb0007ae15e9afb8150ab01716d75fd7573be5cc096e03b09181900360a00190a150805b92915050565b806001600160a01b031663f851a4406040518163ffffffff1660e01b815260040160206040518083038186803b158015610e5257600080fd5b505afa158015610e66573d6000803e3d6000fd5b505050506040513d6020811015610e7c57600080fd5b50516001600160a01b03163314610ec45760405162461bcd60e51b81526004018080602001828103825260278152602001806135846027913960400191505060405180910390fd5b6000816001600160a01b031663c1e803346040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610f0157600080fd5b505af1158015610f15573d6000803e3d6000fd5b505050506040513d6020811015610f2b57600080fd5b505190508015610f7a576040805162461bcd60e51b815260206004820152601560248201527418da185b99d9481b9bdd08185d5d1a1bdc9a5e9959605a1b604482015290519081900360640190fd5b5050565b5050505050565b6001600160a01b03841660009081526009602052604081205460ff16610fad57506009610fb3565b60005b90505b949350505050565b600a546001600160a01b031681565b6001546001600160a01b031681565b600a546000906001600160a01b0316331480610fff57506000546001600160a01b031633145b61103a5760405162461bcd60e51b81526004018080602001828103825260278152602001806135386027913960400191505060405180910390fd5b6000546001600160a01b031633148061105557506001821515145b61109f576040805162461bcd60e51b81526020600482015260166024820152756f6e6c792061646d696e2063616e20756e706175736560501b604482015290519081900360640190fd5b600a8054831515600160b81b810260ff60b81b1990921691909117909155604080516020810192909252808252600582820152645365697a6560d81b6060830152517fef159d9a32b2472e32b098f954f3ce62d232939f1c207070b584df1814de2de09181900360800190a150805b919050565b600080546001600160a01b0316331461113957611132600160046129bb565b905061110e565b61114161344d565b50604080516020810190915282815261115861344d565b50604080516020810190915266b1a2bc2ec5000081526111788282612a21565b15611191576111886005806129bb565b9250505061110e565b61119961344d565b506040805160208101909152670c7d713b49da000081526111ba8184612a29565b156111d4576111ca6005806129bb565b935050505061110e565b6005805490869055604080518281526020810188905281517f3b9670cf975d26958e754b57098eaa2ac914d8d2a31b83257997b9f346110fd9929181900390910190a160005b9695505050505050565b6001600160a01b03821660009081526009602052604081205460ff1661127b5760405162461bcd60e51b81526004018080602001828103825260288152602001806135106028913960400191505060405180910390fd5b600a546001600160a01b031633148061129e57506000546001600160a01b031633145b6112d95760405162461bcd60e51b81526004018080602001828103825260278152602001806135386027913960400191505060405180910390fd5b6000546001600160a01b03163314806112f457506001821515145b61133e576040805162461bcd60e51b81526020600482015260166024820152756f6e6c792061646d696e2063616e20756e706175736560501b604482015290519081900360640190fd5b6001600160a01b0383166000818152600b6020908152604091829020805486151560ff199091168117909155825193845283830152606090830181905260049083015263135a5b9d60e21b6080830152517f71aec636243f9709bb0007ae15e9afb8150ab01716d75fd7573be5cc096e03b09181900360a00190a150919050565b600a54600160a01b900460ff1681565b50505050565b505050505050565b60065481565b6000806000806000806113f88a8a8a8a612a30565b92509250925082601181111561140a57fe5b95509093509150505b9450945094915050565b6001600160a01b0383166000908152600b602052604081205460ff161561147c576040805162461bcd60e51b815260206004820152600e60248201526d1b5a5b9d081a5cc81c185d5cd95960921b604482015290519081900360640190fd5b6001600160a01b03841660009081526009602052604090205460ff166114a65760095b90506114ac565b60005b90505b9392505050565b600080546001600160a01b031633146114d2576111326001600b6129bb565b6114da61344d565b5060408051602081019091528281526114f161344d565b506040805160208101909152670de0b6b3a764000081526115128282612a29565b15611523576111886007600c6129bb565b61152b61344d565b5060408051602081019091526714d1120d7b160000815261154c8184612a29565b1561155d576111ca6007600c6129bb565b6006805490869055604080518281526020810188905281517faeba5a6c40a8ac138134bff1aaa65debf25971188a58804bad717f82f0ec1316929181900390910190a1600061121a565b801580156115b55750600082115b156113cf576040805162461bcd60e51b815260206004820152601160248201527072656465656d546f6b656e73207a65726f60781b604482015290519081900360640190fd5b600080546001600160a01b0316331461161a57611132600160106129bb565b600480546001600160a01b038481166001600160a01b0319831681179093556040805191909216808252602082019390935281517fd52b2b9b7e9ee655fcb95d2e5b9e0c9f69e7ef2b8e9d2d0ea78402d576d22e22929181900390910190a160009392505050565b600d5481565b505050565b6000806000806000806116a4876000806000612a30565b9250925092508260118111156116b657fe5b97919650945092505050565b600080546001600160a01b031633146116e157611132600160136129bb565b600a80546001600160a01b038481166001600160a01b0319831617928390556040805192821680845293909116602083015280517f0613b6ee6a04f0d09f390e4d9318894b9f6ac7fd83897cd8d18896ba579c401e9281900390910190a160006114ac565b6001600160a01b03851660009081526009602052604081205460ff16158061178757506001600160a01b03851660009081526009602052604090205460ff16155b156117965760095b90506118c4565b6000806117a285612e4b565b919350909150600090508260118111156117b857fe5b146117d2578160118111156117c957fe5b925050506118c4565b806117de5760036117c9565b6000886001600160a01b03166395dd9193876040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561183657600080fd5b505afa15801561184a573d6000803e3d6000fd5b505050506040513d602081101561186057600080fd5b50516040805160208101909152600554815290915060009081906118849084612e6b565b9092509050600082600381111561189757fe5b146118ab57600b5b955050505050506118c4565b808711156118ba57601161189f565b6000955050505050505b95945050505050565b600c6020526000908152604090205460ff1681565b600b6020526000908152604090205460ff1681565b600e546001600160a01b031681565b6004546001600160a01b031681565b600a54600160b01b900460ff1681565b60096020526000908152604090208054600182015460039092015460ff91821692911683565b600a546000906001600160a01b031633148061197157506000546001600160a01b031633145b6119ac5760405162461bcd60e51b81526004018080602001828103825260278152602001806135386027913960400191505060405180910390fd5b6000546001600160a01b03163314806119c757506001821515145b611a11576040805162461bcd60e51b81526020600482015260166024820152756f6e6c792061646d696e2063616e20756e706175736560501b604482015290519081900360640190fd5b600a8054831515600160b01b810260ff60b01b1990921691909117909155604080516020810192909252808252600882820152672a3930b739b332b960c11b6060830152517fef159d9a32b2472e32b098f954f3ce62d232939f1c207070b584df1814de2de09181900360800190a15090565b6001600160a01b038082166000908152600960209081526040808320938616835260029093019052205460ff1692915050565b60075481565b600080546001600160a01b03163314611adc57611132600160126129bb565b6001600160a01b03821660009081526009602052604090205460ff1615611b0957611132600a60116129bb565b816001600160a01b031663fe9c44ae6040518163ffffffff1660e01b815260040160206040518083038186803b158015611b4257600080fd5b505afa158015611b56573d6000803e3d6000fd5b505050506040513d6020811015611b6c57600080fd5b5050604080516060810182526001808252600060208381018281528486018381526001600160a01b03891680855260098452938790209551865490151560ff199182161787559151948601949094559251600390940180549415159490931693909317909155825190815291517fcf583bb0c569eb967f806b11601c4cb93c10310485c67add5f8362c2f212321f9281900390910190a1600092915050565b600d55565b60608060086000846001600160a01b03166001600160a01b03168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015611c8c57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611c6e575b5093979650505050505050565b600a54600160b81b900460ff1681565b6002546001600160a01b031681565b600a54600090600160b01b900460ff1615611d0f576040805162461bcd60e51b81526020600482015260126024820152711d1c985b9cd9995c881a5cc81c185d5cd95960721b604482015290519081900360640190fd5b610fb0858584612ebf565b6060600082519050606081604051908082528060200260200182016040528015611d4e578160200160208202803883390190505b50905060005b82811015611da9576000858281518110611d6a57fe5b60200260200101519050611d7e8133612f2e565b6011811115611d8957fe5b838381518110611d9557fe5b602090810291909101015250600101611d54565b509392505050565b600480546040805163fc57d4df60e01b81526001600160a01b038781169482019490945290516000938493849391169163fc57d4df91602480820192602092909190829003018186803b158015611e0757600080fd5b505afa158015611e1b573d6000803e3d6000fd5b505050506040513d6020811015611e3157600080fd5b5051600480546040805163fc57d4df60e01b81526001600160a01b038a8116948201949094529051939450600093929091169163fc57d4df91602480820192602092909190829003018186803b158015611e8a57600080fd5b505afa158015611e9e573d6000803e3d6000fd5b505050506040513d6020811015611eb457600080fd5b50519050811580611ec3575080155b15611ed857600d93506000925061201e915050565b6000866001600160a01b031663182df0f56040518163ffffffff1660e01b815260040160206040518083038186803b158015611f1357600080fd5b505afa158015611f27573d6000803e3d6000fd5b505050506040513d6020811015611f3d57600080fd5b505190506000611f4b61344d565b611f5361344d565b611f5b61344d565b6000611f696006548961304f565b945090506000816003811115611f7b57fe5b14611f9757600b5b99506000985061201e975050505050505050565b611fa1878761304f565b935090506000816003811115611fb357fe5b14611fbf57600b611f83565b611fc9848461308a565b925090506000816003811115611fdb57fe5b14611fe757600b611f83565b611ff1828c612e6b565b95509050600081600381111561200357fe5b1461200f57600b611f83565b60009950939750505050505050505b935093915050565b600a54600090600160b81b900460ff161561207a576040805162461bcd60e51b815260206004820152600f60248201526e1cd95a5e99481a5cc81c185d5cd959608a1b604482015290519081900360640190fd5b6001600160a01b03861660009081526009602052604090205460ff1615806120bb57506001600160a01b03851660009081526009602052604090205460ff16155b156120c757600961178f565b846001600160a01b0316635fe3b5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561210057600080fd5b505afa158015612114573d6000803e3d6000fd5b505050506040513d602081101561212a57600080fd5b505160408051635fe3b56760e01b815290516001600160a01b0392831692891691635fe3b567916004808301926020929190829003018186803b15801561217057600080fd5b505afa158015612184573d6000803e3d6000fd5b505050506040513d602081101561219a57600080fd5b50516001600160a01b0316146121b157600261178f565b60009695505050505050565b600080546001600160a01b031633146121dc576111326001600d6129bb565b6007805490839055604080518281526020810185905281517f7093cf1eb653f749c3ff531d6df7f92764536a7fa0d13530cd26e070780c32ea929181900390910190a160006114ac565b6001600160a01b0383166000908152600c602052604081205460ff1615612287576040805162461bcd60e51b815260206004820152601060248201526f189bdc9c9bddc81a5cc81c185d5cd95960821b604482015290519081900360640190fd5b6001600160a01b03841660009081526009602052604090205460ff166122ae57600961149f565b6001600160a01b038085166000908152600960209081526040808320938716835260029093019052205460ff1661239e57336001600160a01b03851614612334576040805162461bcd60e51b815260206004820152601560248201527439b2b73232b91036bab9ba1031329031aa37b5b2b760591b604482015290519081900360640190fd5b60006123403385612f2e565b9050600081601181111561235057fe5b146123695780601181111561236157fe5b9150506114ac565b6001600160a01b038086166000908152600960209081526040808320938816835260029093019052205460ff1661239c57fe5b505b600480546040805163fc57d4df60e01b81526001600160a01b03888116948201949094529051929091169163fc57d4df91602480820192602092909190829003018186803b1580156123ef57600080fd5b505afa158015612403573d6000803e3d6000fd5b505050506040513d602081101561241957600080fd5b505161242657600d61149f565b6000806124368587600087612a30565b9193509091506000905082601181111561244c57fe5b146124665781601181111561245d57fe5b925050506114ac565b80156121b157600461245d565b6008602052816000526040600020818154811061248c57fe5b6000918252602090912001546001600160a01b03169150829050565b6003546001600160a01b031681565b600080546001600160a01b031633146124dd576124d6600160066129bb565b9050610e13565b6001600160a01b0383166000908152600960205260409020805460ff166125125761250a600960076129bb565b915050610e13565b61251a61344d565b50604080516020810190915283815261253161344d565b506040805160208101909152670c7d713b49da000081526125528183612a29565b1561256d57612563600660086129bb565b9350505050610e13565b84158015906125f65750600480546040805163fc57d4df60e01b81526001600160a01b038a8116948201949094529051929091169163fc57d4df91602480820192602092909190829003018186803b1580156125c857600080fd5b505afa1580156125dc573d6000803e3d6000fd5b505050506040513d60208110156125f257600080fd5b5051155b1561260757612563600d60096129bb565b60018301805490869055604080516001600160a01b03891681526020810183905280820188905290517f70483e6592cd5182d45ac970e05bc62cdcc90e9d8ef2c2dbe686cf383bcd7fc59181900360600190a16000979650505050505050565b600a54600160a81b900460ff1681565b60055481565b60006114a9848484612ebf565b6000808290506000806000836001600160a01b031663c37f68e2336040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060806040518083038186803b1580156126eb57600080fd5b505afa1580156126ff573d6000803e3d6000fd5b505050506040513d608081101561271557600080fd5b5080516020820151604090920151909450909250905082156127685760405162461bcd60e51b815260040180806020018281038252602581526020018061355f6025913960400191505060405180910390fd5b80156127855761277a600c60026129bb565b94505050505061110e565b6000612792873385612ebf565b905080156127b3576127a7600e6003836130a2565b9550505050505061110e565b6001600160a01b0385166000908152600960209081526040808320338452600281019092529091205460ff166127f2576000965050505050505061110e565b3360009081526002820160209081526040808320805460ff19169055600882529182902080548351818402810184019094528084526060939283018282801561286457602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612846575b5050835193945083925060009150505b828110156128b957896001600160a01b031684828151811061289257fe5b60200260200101516001600160a01b031614156128b1578091506128b9565b600101612874565b508181106128c357fe5b3360009081526008602052604090208054819060001981019081106128e457fe5b9060005260206000200160009054906101000a90046001600160a01b031681838154811061290e57fe5b600091825260209091200180546001600160a01b0319166001600160a01b03929092169190911790558054612947826000198301613460565b50604080516001600160a01b038c16815233602082015281517fe699a64c18b07ac5b7301aa273f36a2287239eb9501d81950672794afba29a0d929181900390910190a160009c9b505050505050505050505050565b6000546001600160a01b031681565b600d8054820190819055919050565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa08360118111156129ea57fe5b8360138111156129f657fe5b604080519283526020830191909152600082820152519081900360600190a18260118111156114ac57fe5b519051111590565b5190511090565b6000806000612a3d613484565b6001600160a01b038816600090815260086020908152604080832080548251818502810185019093528083528493606093929190830182828015612aaa57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612a8c575b50939450600093505050505b8151811015612e06576000828281518110612acd57fe5b60200260200101519050806001600160a01b031663c37f68e28e6040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060806040518083038186803b158015612b2d57600080fd5b505afa158015612b41573d6000803e3d6000fd5b505050506040513d6080811015612b5757600080fd5b508051602082015160408084015160609485015160808c0152938a01939093529188019190915294508415612b9d5750600f975060009650869550611413945050505050565b60408051602080820183526001600160a01b0380851660008181526009845285902060010154845260c08b01939093528351808301855260808b0151815260e08b015260048054855163fc57d4df60e01b815291820194909452935192169263fc57d4df9260248083019392829003018186803b158015612c1d57600080fd5b505afa158015612c31573d6000803e3d6000fd5b505050506040513d6020811015612c4757600080fd5b505160a08701819052612c6b5750600d975060009650869550611413945050505050565b604080516020810190915260a08701518152610100870181905260c087015160e0880151612c9892613108565b61012088015293506000846003811115612cae57fe5b14612cca5750600b975060009650869550611413945050505050565b612ce286610120015187604001518860000151613160565b875293506000846003811115612cf457fe5b14612d105750600b975060009650869550611413945050505050565b612d2886610100015187606001518860200151613160565b602088015293506000846003811115612d3d57fe5b14612d595750600b975060009650869550611413945050505050565b8b6001600160a01b0316816001600160a01b03161415612dfd57612d878661012001518c8860200151613160565b602088015293506000846003811115612d9c57fe5b14612db85750600b975060009650869550611413945050505050565b612dcc8661010001518b8860200151613160565b602088015293506000846003811115612de157fe5b14612dfd5750600b975060009650869550611413945050505050565b50600101612ab6565b50602084015184511115612e2d575050506020810151905160009450039150829050611413565b50508151602090920151600095508594509190910391506114139050565b6000806000612e5e846000806000612a30565b9250925092509193909250565b6000806000612e7861344d565b612e8286866131ad565b90925090506000826003811115612e9557fe5b14612ea65750915060009050612eb8565b6000612eb182613215565b9350935050505b9250929050565b6001600160a01b03831660009081526009602052604081205460ff16612ee657600961149f565b6001600160a01b038085166000908152600960209081526040808320938716835260029093019052205460ff16612f1e57600061149f565b6000806124368587866000612a30565b6001600160a01b0382166000908152600960205260408120805460ff16612f59576009915050610e13565b6001600160a01b038316600090815260028201602052604090205460ff16151560011415612f8b576000915050610e13565b6007546001600160a01b03841660009081526008602052604090205410612fb6576010915050610e13565b6001600160a01b0380841660008181526002840160209081526040808320805460ff19166001908117909155600883528184208054918201815584529282902090920180549489166001600160a01b031990951685179055815193845283019190915280517f3ab23ab0d51cccc0c3085aec51f99228625aa1a922b3a8ca89a26b0f2027a1a59281900390910190a15060009392505050565b600061305961344d565b61307f604051806020016040528086815250604051806020016040528086815250613224565b915091509250929050565b600061309461344d565b8351835161307f919061330d565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa08460118111156130d157fe5b8460138111156130dd57fe5b604080519283526020830191909152818101859052519081900360600190a18360118111156114a957fe5b600061311261344d565b600061311c61344d565b6131268787613224565b9092509050600082600381111561313957fe5b1461314857909250905061201e565b6131528186613224565b935093505050935093915050565b600080600061316d61344d565b61317787876131ad565b9092509050600082600381111561318a57fe5b1461319b575091506000905061201e565b6131526131a782613215565b866133bd565b60006131b761344d565b6000806131c88660000151866133e3565b909250905060008260038111156131db57fe5b146131fa57506040805160208101909152600081529092509050612eb8565b60408051602081019091529081526000969095509350505050565b51670de0b6b3a7640000900490565b600061322e61344d565b600080613243866000015186600001516133e3565b9092509050600082600381111561325657fe5b1461327557506040805160208101909152600081529092509050612eb8565b60008061328a6706f05b59d3b20000846133bd565b9092509050600082600381111561329d57fe5b146132bf57506040805160208101909152600081529094509250612eb8915050565b6000806132d483670de0b6b3a7640000613422565b909250905060008260038111156132e757fe5b146132ee57fe5b604080516020810190915290815260009a909950975050505050505050565b600061331761344d565b60008061332c86670de0b6b3a76400006133e3565b9092509050600082600381111561333f57fe5b1461335e57506040805160208101909152600081529092509050612eb8565b60008061336b8388613422565b9092509050600082600381111561337e57fe5b146133a057506040805160208101909152600081529094509250612eb8915050565b604080516020810190915290815260009890975095505050505050565b6000808383018481106133d557600092509050612eb8565b506002915060009050612eb8565b600080836133f657506000905080612eb8565b8383028385828161340357fe5b041461341757506002915060009050612eb8565b600092509050612eb8565b600080826134365750600190506000612eb8565b600083858161344157fe5b04915091509250929050565b6040518060200160405280600081525090565b815481835581811115611688576000838152602090206116889181019083016134ee565b6040518061014001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016134c261344d565b81526020016134cf61344d565b81526020016134dc61344d565b81526020016134e961344d565b905290565b61350c91905b8082111561350857600081556001016134f4565b5090565b9056fe63616e6e6f742070617573652061206d61726b65742074686174206973206e6f74206c69737465646f6e6c7920706175736520677561726469616e20616e642061646d696e2063616e207061757365657869744d61726b65743a206765744163636f756e74536e617073686f74206661696c65646f6e6c7920756e6974726f6c6c65722061646d696e2063616e206368616e676520627261696e73a265627a7a7231582052b91b050f7ccf12e2e1c067772bc867b5e8c11d8a045246ab6257fa1312124864736f6c63430005100032", + "metadata": "{\"compiler\":{\"version\":\"0.5.16+commit.9c3226ce\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"action\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"pauseState\",\"type\":\"bool\"}],\"name\":\"ActionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"action\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"pauseState\",\"type\":\"bool\"}],\"name\":\"ActionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketEntered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketExited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"MarketListed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCloseFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCloseFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCollateralFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCollateralFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldLiquidationIncentiveMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"NewLiquidationIncentive\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMaxAssets\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMaxAssets\",\"type\":\"uint256\"}],\"name\":\"NewMaxAssets\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldPauseGuardian\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"NewPauseGuardian\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"oldPriceOracle\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"newPriceOracle\",\"type\":\"address\"}],\"name\":\"NewPriceOracle\",\"type\":\"event\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract Unitroller\",\"name\":\"unitroller\",\"type\":\"address\"}],\"name\":\"_become\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setBorrowPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCloseFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCollateralFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"_setLiquidationIncentive\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newMaxAssets\",\"type\":\"uint256\"}],\"name\":\"_setMaxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setMintPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"_setPauseGuardian\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"newOracle\",\"type\":\"address\"}],\"name\":\"_setPriceOracle\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setSeizePaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setTransferPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"_supportMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"blockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"checkMembership\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"enterMarkets\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenAddress\",\"type\":\"address\"}],\"name\":\"exitMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blocks\",\"type\":\"uint256\"}],\"name\":\"fastForward\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAssetsIn\",\"outputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenModify\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"getHypotheticalAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"isComptroller\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateCalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"liquidationIncentiveMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"markets\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isComped\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"mintAmount\",\"type\":\"uint256\"}],\"name\":\"mintAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualMintAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"mintTokens\",\"type\":\"uint256\"}],\"name\":\"mintVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"repayBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowerIndex\",\"type\":\"uint256\"}],\"name\":\"repayBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"seizeGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"}],\"name\":\"setBlockNumber\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"transferGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"methods\":{\"_setCloseFactor(uint256)\":{\"details\":\"Admin function to set closeFactor\",\"params\":{\"newCloseFactorMantissa\":\"New close factor, scaled by 1e18\"},\"return\":\"uint 0=success, otherwise a failure. (See ErrorReporter for details)\"},\"_setCollateralFactor(address,uint256)\":{\"details\":\"Admin function to set per-market collateralFactor\",\"params\":{\"cToken\":\"The market to set the factor on\",\"newCollateralFactorMantissa\":\"The new collateral factor, scaled by 1e18\"},\"return\":\"uint 0=success, otherwise a failure. (See ErrorReporter for details)\"},\"_setLiquidationIncentive(uint256)\":{\"details\":\"Admin function to set liquidationIncentive\",\"params\":{\"newLiquidationIncentiveMantissa\":\"New liquidationIncentive scaled by 1e18\"},\"return\":\"uint 0=success, otherwise a failure. (See ErrorReporter for details)\"},\"_setMaxAssets(uint256)\":{\"details\":\"Admin function to set maxAssets\",\"params\":{\"newMaxAssets\":\"New max assets\"},\"return\":\"uint 0=success, otherwise a failure. (See ErrorReporter for details)\"},\"_setPauseGuardian(address)\":{\"params\":{\"newPauseGuardian\":\"The address of the new Pause Guardian\"},\"return\":\"uint 0=success, otherwise a failure. (See enum Error for details)\"},\"_setPriceOracle(address)\":{\"details\":\"Admin function to set a new price oracle\",\"return\":\"uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\"},\"_supportMarket(address)\":{\"details\":\"Admin function to set isListed and add support for the market\",\"params\":{\"cToken\":\"The address of the market (token) to list\"},\"return\":\"uint 0=success, otherwise a failure. (See enum Error for details)\"},\"borrowAllowed(address,address,uint256)\":{\"params\":{\"borrowAmount\":\"The amount of underlying the account would borrow\",\"borrower\":\"The account which would borrow the asset\",\"cToken\":\"The market to verify the borrow against\"},\"return\":\"0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"borrowVerify(address,address,uint256)\":{\"params\":{\"borrowAmount\":\"The amount of the underlying asset requested to borrow\",\"borrower\":\"The address borrowing the underlying\",\"cToken\":\"Asset whose underlying is being borrowed\"}},\"checkMembership(address,address)\":{\"params\":{\"account\":\"The address of the account to check\",\"cToken\":\"The cToken to check\"},\"return\":\"True if the account is in the asset, otherwise false.\"},\"enterMarkets(address[])\":{\"params\":{\"cTokens\":\"The list of addresses of the cToken markets to be enabled\"},\"return\":\"Success indicator for whether each corresponding market was entered\"},\"exitMarket(address)\":{\"details\":\"Sender must not have an outstanding borrow balance in the asset, or be providing neccessary collateral for an outstanding borrow.\",\"params\":{\"cTokenAddress\":\"The address of the asset to be removed\"},\"return\":\"Whether or not the account successfully exited the market\"},\"getAccountLiquidity(address)\":{\"return\":\"(possible error code (semi-opaque), account liquidity in excess of collateral requirements, account shortfall below collateral requirements)\"},\"getAssetsIn(address)\":{\"params\":{\"account\":\"The address of the account to pull assets for\"},\"return\":\"A dynamic list with the assets the account has entered\"},\"getHypotheticalAccountLiquidity(address,address,uint256,uint256)\":{\"params\":{\"account\":\"The account to determine liquidity for\",\"borrowAmount\":\"The amount of underlying to hypothetically borrow\",\"cTokenModify\":\"The market to hypothetically redeem/borrow in\",\"redeemTokens\":\"The number of tokens to hypothetically redeem\"},\"return\":\"(possible error code (semi-opaque), hypothetical account liquidity in excess of collateral requirements, hypothetical account shortfall below collateral requirements)\"},\"liquidateBorrowAllowed(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"repayAmount\":\"The amount of underlying being repaid\"}},\"liquidateBorrowVerify(address,address,address,address,uint256,uint256)\":{\"params\":{\"actualRepayAmount\":\"The amount of underlying being repaid\",\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\"}},\"liquidateCalculateSeizeTokens(address,address,uint256)\":{\"details\":\"Used in liquidation (called in cToken.liquidateBorrowFresh)\",\"params\":{\"actualRepayAmount\":\"The amount of cTokenBorrowed underlying to convert into cTokenCollateral tokens\",\"cTokenBorrowed\":\"The address of the borrowed cToken\",\"cTokenCollateral\":\"The address of the collateral cToken\"},\"return\":\"(errorCode, number of cTokenCollateral tokens to be seized in a liquidation)\"},\"mintAllowed(address,address,uint256)\":{\"params\":{\"cToken\":\"The market to verify the mint against\",\"mintAmount\":\"The amount of underlying being supplied to the market in exchange for tokens\",\"minter\":\"The account which would get the minted tokens\"},\"return\":\"0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"mintVerify(address,address,uint256,uint256)\":{\"params\":{\"actualMintAmount\":\"The amount of the underlying asset being minted\",\"cToken\":\"Asset being minted\",\"mintTokens\":\"The number of tokens being minted\",\"minter\":\"The address minting the tokens\"}},\"redeemAllowed(address,address,uint256)\":{\"params\":{\"cToken\":\"The market to verify the redeem against\",\"redeemTokens\":\"The number of cTokens to exchange for the underlying asset in the market\",\"redeemer\":\"The account which would redeem the tokens\"},\"return\":\"0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"redeemVerify(address,address,uint256,uint256)\":{\"params\":{\"cToken\":\"Asset being redeemed\",\"redeemAmount\":\"The amount of the underlying asset being redeemed\",\"redeemTokens\":\"The number of tokens being redeemed\",\"redeemer\":\"The address redeeming the tokens\"}},\"repayBorrowAllowed(address,address,address,uint256)\":{\"params\":{\"borrower\":\"The account which would borrowed the asset\",\"cToken\":\"The market to verify the repay against\",\"payer\":\"The account which would repay the asset\",\"repayAmount\":\"The amount of the underlying asset the account would repay\"},\"return\":\"0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"repayBorrowVerify(address,address,address,uint256,uint256)\":{\"params\":{\"actualRepayAmount\":\"The amount of underlying being repaid\",\"borrower\":\"The address of the borrower\",\"cToken\":\"Asset being repaid\",\"payer\":\"The address repaying the borrow\"}},\"seizeAllowed(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"seizeTokens\":\"The number of collateral tokens to seize\"}},\"seizeVerify(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"seizeTokens\":\"The number of collateral tokens to seize\"}},\"transferAllowed(address,address,address,uint256)\":{\"params\":{\"cToken\":\"The market to verify the transfer against\",\"dst\":\"The account which receives the tokens\",\"src\":\"The account which sources the tokens\",\"transferTokens\":\"The number of cTokens to transfer\"},\"return\":\"0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"transferVerify(address,address,address,uint256)\":{\"params\":{\"cToken\":\"Asset being transferred\",\"dst\":\"The account which receives the tokens\",\"src\":\"The account which sources the tokens\",\"transferTokens\":\"The number of cTokens to transfer\"}}}},\"userdoc\":{\"methods\":{\"_setCloseFactor(uint256)\":{\"notice\":\"Sets the closeFactor used when liquidating borrows\"},\"_setCollateralFactor(address,uint256)\":{\"notice\":\"Sets the collateralFactor for a market\"},\"_setLiquidationIncentive(uint256)\":{\"notice\":\"Sets liquidationIncentive\"},\"_setMaxAssets(uint256)\":{\"notice\":\"Sets maxAssets which controls how many markets can be entered\"},\"_setPauseGuardian(address)\":{\"notice\":\"Admin function to change the Pause Guardian\"},\"_setPriceOracle(address)\":{\"notice\":\"Sets a new price oracle for the comptroller\"},\"_supportMarket(address)\":{\"notice\":\"Add the market to the markets mapping and set it as listed\"},\"borrowAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to borrow the underlying asset of the given market\"},\"borrowVerify(address,address,uint256)\":{\"notice\":\"Validates borrow and reverts on rejection. May emit logs.\"},\"checkMembership(address,address)\":{\"notice\":\"Returns whether the given account is entered in the given asset\"},\"enterMarkets(address[])\":{\"notice\":\"Add assets to be included in account liquidity calculation\"},\"exitMarket(address)\":{\"notice\":\"Removes asset from sender's account liquidity calculation\"},\"getAccountLiquidity(address)\":{\"notice\":\"Determine the current account liquidity wrt collateral requirements\"},\"getAssetsIn(address)\":{\"notice\":\"Returns the assets an account has entered\"},\"getHypotheticalAccountLiquidity(address,address,uint256,uint256)\":{\"notice\":\"Determine what the account liquidity would be if the given amounts were redeemed/borrowed\"},\"liquidateBorrowAllowed(address,address,address,address,uint256)\":{\"notice\":\"Checks if the liquidation should be allowed to occur\"},\"liquidateBorrowVerify(address,address,address,address,uint256,uint256)\":{\"notice\":\"Validates liquidateBorrow and reverts on rejection. May emit logs.\"},\"liquidateCalculateSeizeTokens(address,address,uint256)\":{\"notice\":\"Calculate number of tokens of collateral asset to seize given an underlying amount\"},\"mintAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to mint tokens in the given market\"},\"mintVerify(address,address,uint256,uint256)\":{\"notice\":\"Validates mint and reverts on rejection. May emit logs.\"},\"redeemAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to redeem tokens in the given market\"},\"redeemVerify(address,address,uint256,uint256)\":{\"notice\":\"Validates redeem and reverts on rejection. May emit logs.\"},\"repayBorrowAllowed(address,address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to repay a borrow in the given market\"},\"repayBorrowVerify(address,address,address,uint256,uint256)\":{\"notice\":\"Validates repayBorrow and reverts on rejection. May emit logs.\"},\"seizeAllowed(address,address,address,address,uint256)\":{\"notice\":\"Checks if the seizing of assets should be allowed to occur\"},\"seizeVerify(address,address,address,address,uint256)\":{\"notice\":\"Validates seize and reverts on rejection. May emit logs.\"},\"transferAllowed(address,address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to transfer tokens in the given market\"},\"transferVerify(address,address,address,uint256)\":{\"notice\":\"Validates transfer and reverts on rejection. May emit logs.\"}}}},\"settings\":{\"compilationTarget\":{\"tests/Contracts/ComptrollerScenarioG2.sol\":\"ComptrollerScenarioG2\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/CToken.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./CTokenInterfaces.sol\\\";\\nimport \\\"./ErrorReporter.sol\\\";\\nimport \\\"./Exponential.sol\\\";\\nimport \\\"./EIP20Interface.sol\\\";\\nimport \\\"./InterestRateModel.sol\\\";\\n\\n/**\\n * @title Compound's CToken Contract\\n * @notice Abstract base for CTokens\\n * @author Compound\\n */\\ncontract CToken is CTokenInterface, Exponential, TokenErrorReporter {\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_) public {\\n require(msg.sender == admin, \\\"only admin may initialize the market\\\");\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = getBlockNumber();\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Transfer `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = uint(-1);\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srcTokensNew;\\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, srcTokensNew) = 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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srcTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != uint(-1)) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n // unused function\\n // comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transfer(address dst, uint256 amount) external nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferFrom(address src, address dst, uint256 amount) external nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (-1 means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool) {\\n address src = msg.sender;\\n transferAllowances[src][spender] = amount;\\n emit Approval(src, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (-1 means infinite)\\n */\\n function allowance(address owner, address spender) external view returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external returns (uint) {\\n Exp memory exchangeRate = Exp({mantissa: exchangeRateCurrent()});\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n require(mErr == MathError.NO_ERROR, \\\"balance could not be calculated\\\");\\n return balance;\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view returns (uint, uint, uint, uint) {\\n uint cTokenBalance = accountTokens[account];\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), cTokenBalance, borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @dev Function to simply retrieve block number\\n * This exists mainly for inheriting test contracts to stub this result.\\n */\\n function getBlockNumber() internal view returns (uint) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this cToken\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view returns (uint) {\\n return interestRateModel.getBorrowRate(getCashPrior(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this cToken\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view returns (uint) {\\n return interestRateModel.getSupplyRate(getCashPrior(), totalBorrows, totalReserves, reserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n require(err == MathError.NO_ERROR, \\\"borrowBalanceStored: borrowBalanceStoredInternal failed\\\");\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return (error code, the calculated balance or 0 if error code is non-zero)\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the CToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n require(err == MathError.NO_ERROR, \\\"exchangeRateStored: exchangeRateStoredInternal failed\\\");\\n return result;\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the CToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return (error code, calculated exchange rate scaled by 1e18)\\n */\\n function exchangeRateStoredInternal() internal view returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows - totalReserves) / totalSupply\\n */\\n uint totalCash = getCashPrior();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Get cash balance of this cToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage.\\n */\\n function accrueInterest() public returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = getBlockNumber();\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = getCashPrior();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n require(mathErr == MathError.NO_ERROR, \\\"could not calculate block delta\\\");\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({mantissa: borrowRateMantissa}), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(Exp({mantissa: reserveFactorMantissa}), interestAccumulated, reservesPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives cTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n struct MintLocalVars {\\n Error err;\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives cTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, 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's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the cToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of cTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.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 cTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED\\\");\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\\");\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender redeems cTokens in exchange for the underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemTokens The number of cTokens to redeem into underlying\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemInternal(uint redeemTokens) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(msg.sender, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems cTokens in exchange for a specified amount of underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemAmount The amount of underlying to receive from redeeming cTokens\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemUnderlyingInternal(uint redeemAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(msg.sender, 0, redeemAmount);\\n }\\n\\n struct RedeemLocalVars {\\n Error err;\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n /**\\n * @notice User redeems cTokens in exchange for the underlying asset\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param redeemTokensIn The number of cTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming cTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemFresh(address payable redeemer, uint redeemTokensIn, uint redeemAmountIn) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr));\\n }\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(Exp({mantissa: vars.exchangeRateMantissa}), redeemTokensIn);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(redeemAmountIn, Exp({mantissa: vars.exchangeRateMantissa}));\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REDEEM_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDEEM_FRESHNESS_CHECK);\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDEEM_TRANSFER_OUT_NOT_POSSIBLE);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We invoke doTransferOut for the redeemer and the redeemAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(redeemer, vars.redeemAmount);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n /* We call the defense hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender borrows assets from the protocol to their own address\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function borrowInternal(uint borrowAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(msg.sender, borrowAmount);\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n /**\\n * @notice Users borrow assets from the protocol to their own address\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function borrowFresh(address payable borrower, uint borrowAmount) internal returns (uint) {\\n /* Fail if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.BORROW_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.BORROW_FRESHNESS_CHECK);\\n }\\n\\n /* Fail gracefully if protocol has insufficient underlying cash */\\n if (getCashPrior() < borrowAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.BORROW_CASH_NOT_AVAILABLE);\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We invoke doTransferOut for the borrower and the borrowAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(borrower, borrowAmount);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to borrower\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer the account paying off the borrow\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount the amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED\\\");\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED\\\");\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this cToken to be liquidated\\n * @param cTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) 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 = cTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, cTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this cToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param cTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowFresh(address liquidator, address borrower, uint repayAmount, CTokenInterface cTokenCollateral) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(address(this), address(cTokenCollateral), liquidator, borrower, repayAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify cTokenCollateral market's block number equals current block number */\\n if (cTokenCollateral.accrualBlockNumber() != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = -1 */\\n if (repayAmount == uint(-1)) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & 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(cTokenCollateral), actualRepayAmount);\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(cTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(cTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = cTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(cTokenCollateral), seizeTokens);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.liquidateBorrowVerify(address(this), address(cTokenCollateral), liquidator, borrower, actualRepayAmount, seizeTokens);\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another cToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed cToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of cTokens to seize\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function seize(address liquidator, address borrower, uint seizeTokens) external nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n struct SeizeInternalLocalVars {\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n uint liquidatorSeizeTokens;\\n uint protocolSeizeTokens;\\n uint protocolSeizeAmount;\\n uint exchangeRateMantissa;\\n uint totalReservesNew;\\n uint totalSupplyNew;\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another CToken.\\n * Its absolutely critical to use msg.sender as the seizer cToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed cToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of cTokens to seize\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function seizeInternal(address seizerToken, address liquidator, address borrower, uint seizeTokens) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n SeizeInternalLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (vars.mathErr, vars.borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(vars.mathErr));\\n }\\n\\n vars.protocolSeizeTokens = mul_(seizeTokens, Exp({mantissa: protocolSeizeShareMantissa}));\\n vars.liquidatorSeizeTokens = sub_(seizeTokens, vars.protocolSeizeTokens);\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n require(vars.mathErr == MathError.NO_ERROR, \\\"exchange rate math error\\\");\\n\\n vars.protocolSeizeAmount = mul_ScalarTruncate(Exp({mantissa: vars.exchangeRateMantissa}), vars.protocolSeizeTokens);\\n\\n vars.totalReservesNew = add_(totalReserves, vars.protocolSeizeAmount);\\n vars.totalSupplyNew = sub_(totalSupply, vars.protocolSeizeTokens);\\n\\n (vars.mathErr, vars.liquidatorTokensNew) = addUInt(accountTokens[liquidator], vars.liquidatorSeizeTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(vars.mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n totalReserves = vars.totalReservesNew;\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[borrower] = vars.borrowerTokensNew;\\n accountTokens[liquidator] = vars.liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, vars.liquidatorSeizeTokens);\\n emit Transfer(borrower, address(this), vars.protocolSeizeTokens);\\n emit ReservesAdded(address(this), vars.protocolSeizeAmount, vars.totalReservesNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n\\n /*** Admin Functions ***/\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPendingAdmin(address payable newPendingAdmin) external returns (uint) {\\n // Check caller = admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\\n }\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptAdmin() external returns (uint) {\\n // Check caller is pendingAdmin and pendingAdmin \\u2260 address(0)\\n if (msg.sender != pendingAdmin || msg.sender == address(0)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = address(0);\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setComptroller(ComptrollerInterface newComptroller) public returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_COMPTROLLER_OWNER_CHECK);\\n }\\n\\n ComptrollerInterface oldComptroller = comptroller;\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(oldComptroller, newComptroller);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh\\n * @dev Admin function to accrue interest and set a new reserve factor\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setReserveFactor(uint newReserveFactorMantissa) external nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\\n * @dev Admin function to set a new reserve factor\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_RESERVE_FACTOR_ADMIN_CHECK);\\n }\\n\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring from msg.sender\\n * @param addAmount Amount of addition to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to admin\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _reduceReserves(uint reduceAmount) external nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to admin\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _reduceReservesFresh(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's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n totalReservesNew = totalReserves - reduceAmount;\\n // We checked reduceAmount <= totalReserves above, so this should never revert.\\n require(totalReservesNew <= 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't be sure if side effects occurred.\\n doTransferOut(admin, reduceAmount);\\n\\n emit ReservesReduced(admin, reduceAmount, totalReservesNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Admin function to accrue interest and update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel);\\n }\\n\\n /**\\n * @notice updates the interest rate model (*requires fresh interest accrual)\\n * @dev Admin function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal returns (uint) {\\n\\n // Used to store old model for use in the event that is emitted on success\\n InterestRateModel oldInterestRateModel;\\n\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_INTEREST_RATE_MODEL_OWNER_CHECK);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Track the market's current interest rate model\\n oldInterestRateModel = interestRateModel;\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view returns (uint);\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure tather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal;\\n\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n}\\n\",\"keccak256\":\"0x436ec2e309682995f8a82dfdd9e8f75928599c10a9a680dddbee6c275014008d\"},\"contracts/CTokenInterfaces.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./InterestRateModel.sol\\\";\\nimport \\\"./EIP20NonStandardInterface.sol\\\";\\n\\ncontract CTokenStorage {\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-cToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModel public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first CTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping (address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping (address => mapping (address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Share of seized collateral that is added to reserves\\n */\\n uint public constant protocolSeizeShareMantissa = 2.8e16; //2.8%\\n\\n}\\n\\ncontract CTokenInterface is CTokenStorage {\\n /**\\n * @notice Indicator that this is a CToken contract (for inspection)\\n */\\n bool public constant isCToken = true;\\n\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(address liquidator, address borrower, uint repayAmount, address cTokenCollateral, uint seizeTokens);\\n\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin is updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(InterestRateModel oldInterestRateModel, InterestRateModel newInterestRateModel);\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address admin, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Failure event\\n */\\n event Failure(uint error, uint info, uint detail);\\n\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external returns (bool);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function approve(address spender, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function balanceOfUnderlying(address owner) external returns (uint);\\n function getAccountSnapshot(address account) external view returns (uint, uint, uint, uint);\\n function borrowRatePerBlock() external view returns (uint);\\n function supplyRatePerBlock() external view returns (uint);\\n function totalBorrowsCurrent() external returns (uint);\\n function borrowBalanceCurrent(address account) external returns (uint);\\n function borrowBalanceStored(address account) public view returns (uint);\\n function exchangeRateCurrent() public returns (uint);\\n function exchangeRateStored() public view returns (uint);\\n function getCash() external view returns (uint);\\n function accrueInterest() public returns (uint);\\n function seize(address liquidator, address borrower, uint seizeTokens) external returns (uint);\\n\\n\\n /*** Admin Functions ***/\\n\\n function _setPendingAdmin(address payable newPendingAdmin) external returns (uint);\\n function _acceptAdmin() external returns (uint);\\n function _setComptroller(ComptrollerInterface newComptroller) public returns (uint);\\n function _setReserveFactor(uint newReserveFactorMantissa) external returns (uint);\\n function _reduceReserves(uint reduceAmount) external returns (uint);\\n function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint);\\n}\\n\\ncontract CErc20Storage {\\n /**\\n * @notice Underlying asset for this CToken\\n */\\n address public underlying;\\n}\\n\\ncontract CErc20Interface is CErc20Storage {\\n\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n function redeem(uint redeemTokens) external returns (uint);\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n function borrow(uint borrowAmount) external returns (uint);\\n function repayBorrow(uint repayAmount) external returns (uint);\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n function liquidateBorrow(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) external returns (uint);\\n function sweepToken(EIP20NonStandardInterface token) external;\\n\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ncontract CDelegationStorage {\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n}\\n\\ncontract CDelegatorInterface is CDelegationStorage {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(address implementation_, bool allowResign, bytes memory becomeImplementationData) public;\\n}\\n\\ncontract CDelegateInterface is CDelegationStorage {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) public;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() public;\\n}\\n\",\"keccak256\":\"0x963bbf60b4c0b76900b3fcb2db8c8be634934b37b4113f1055e57a308197d21a\"},\"contracts/CarefulMath.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Careful Math\\n * @author Compound\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c = a * b;\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n return (MathError.NO_ERROR, a - b);\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c = a + b;\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\",\"keccak256\":\"0x0647348f27e41d22555d99eebd217dee02a4d737df6accd7cce5347a7487c7de\"},\"contracts/ComptrollerG2.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.sol\\\";\\nimport \\\"./ErrorReporter.sol\\\";\\nimport \\\"./Exponential.sol\\\";\\nimport \\\"./PriceOracle.sol\\\";\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./ComptrollerStorage.sol\\\";\\nimport \\\"./Unitroller.sol\\\";\\n\\n/**\\n * @title Compound's Comptroller Contract\\n * @author Compound\\n */\\ncontract ComptrollerG2 is ComptrollerV2Storage, ComptrollerInterface, ComptrollerErrorReporter, Exponential {\\n /**\\n * @notice Emitted when an admin supports a market\\n */\\n event MarketListed(CToken cToken);\\n\\n /**\\n * @notice Emitted when an account enters a market\\n */\\n event MarketEntered(CToken cToken, address account);\\n\\n /**\\n * @notice Emitted when an account exits a market\\n */\\n event MarketExited(CToken cToken, address account);\\n\\n /**\\n * @notice Emitted when close factor is changed by admin\\n */\\n event NewCloseFactor(uint oldCloseFactorMantissa, uint newCloseFactorMantissa);\\n\\n /**\\n * @notice Emitted when a collateral factor is changed by admin\\n */\\n event NewCollateralFactor(CToken cToken, uint oldCollateralFactorMantissa, uint newCollateralFactorMantissa);\\n\\n /**\\n * @notice Emitted when liquidation incentive is changed by admin\\n */\\n event NewLiquidationIncentive(uint oldLiquidationIncentiveMantissa, uint newLiquidationIncentiveMantissa);\\n\\n /**\\n * @notice Emitted when maxAssets is changed by admin\\n */\\n event NewMaxAssets(uint oldMaxAssets, uint newMaxAssets);\\n\\n /**\\n * @notice Emitted when price oracle is changed\\n */\\n event NewPriceOracle(PriceOracle oldPriceOracle, PriceOracle newPriceOracle);\\n\\n /**\\n * @notice Emitted when pause guardian is changed\\n */\\n event NewPauseGuardian(address oldPauseGuardian, address newPauseGuardian);\\n\\n /**\\n * @notice Emitted when an action is paused globally\\n */\\n event ActionPaused(string action, bool pauseState);\\n\\n /**\\n * @notice Emitted when an action is paused on a market\\n */\\n event ActionPaused(CToken cToken, string action, bool pauseState);\\n\\n // closeFactorMantissa must be strictly greater than this value\\n uint internal constant closeFactorMinMantissa = 0.05e18; // 0.05\\n\\n // closeFactorMantissa must not exceed this value\\n uint internal constant closeFactorMaxMantissa = 0.9e18; // 0.9\\n\\n // No collateralFactorMantissa may exceed this value\\n uint internal constant collateralFactorMaxMantissa = 0.9e18; // 0.9\\n\\n // liquidationIncentiveMantissa must be no less than this value\\n uint internal constant liquidationIncentiveMinMantissa = 1.0e18; // 1.0\\n\\n // liquidationIncentiveMantissa must be no greater than this value\\n uint internal constant liquidationIncentiveMaxMantissa = 1.5e18; // 1.5\\n\\n constructor() public {\\n admin = msg.sender;\\n }\\n\\n /*** Assets You Are In ***/\\n\\n /**\\n * @notice Returns the assets an account has entered\\n * @param account The address of the account to pull assets for\\n * @return A dynamic list with the assets the account has entered\\n */\\n function getAssetsIn(address account) external view returns (CToken[] memory) {\\n CToken[] memory assetsIn = accountAssets[account];\\n\\n return assetsIn;\\n }\\n\\n /**\\n * @notice Returns whether the given account is entered in the given asset\\n * @param account The address of the account to check\\n * @param cToken The cToken to check\\n * @return True if the account is in the asset, otherwise false.\\n */\\n function checkMembership(address account, CToken cToken) external view returns (bool) {\\n return markets[address(cToken)].accountMembership[account];\\n }\\n\\n /**\\n * @notice Add assets to be included in account liquidity calculation\\n * @param cTokens The list of addresses of the cToken markets to be enabled\\n * @return Success indicator for whether each corresponding market was entered\\n */\\n function enterMarkets(address[] memory cTokens) public returns (uint[] memory) {\\n uint len = cTokens.length;\\n\\n uint[] memory results = new uint[](len);\\n for (uint i = 0; i < len; i++) {\\n CToken cToken = CToken(cTokens[i]);\\n\\n results[i] = uint(addToMarketInternal(cToken, msg.sender));\\n }\\n\\n return results;\\n }\\n\\n /**\\n * @notice Add the market to the borrower's \\\"assets in\\\" for liquidity calculations\\n * @param cToken The market to enter\\n * @param borrower The address of the account to modify\\n * @return Success indicator for whether the market was entered\\n */\\n function addToMarketInternal(CToken cToken, address borrower) internal returns (Error) {\\n Market storage marketToJoin = markets[address(cToken)];\\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 if (accountAssets[borrower].length >= maxAssets) {\\n // no space, cannot join\\n return Error.TOO_MANY_ASSETS;\\n }\\n\\n // survived the gauntlet, add to list\\n // NOTE: we store these somewhat redundantly as a significant optimization\\n // this avoids having to iterate through the list for the most common use cases\\n // that is, only when we need to perform liquidity checks\\n // and not whenever we want to check if an account is in a particular market\\n marketToJoin.accountMembership[borrower] = true;\\n accountAssets[borrower].push(cToken);\\n\\n emit MarketEntered(cToken, borrower);\\n\\n return Error.NO_ERROR;\\n }\\n\\n /**\\n * @notice Removes asset from sender's account liquidity calculation\\n * @dev Sender must not have an outstanding borrow balance in the asset,\\n * or be providing neccessary collateral for an outstanding borrow.\\n * @param cTokenAddress The address of the asset to be removed\\n * @return Whether or not the account successfully exited the market\\n */\\n function exitMarket(address cTokenAddress) external returns (uint) {\\n CToken cToken = CToken(cTokenAddress);\\n /* Get sender tokensHeld and amountOwed underlying from the cToken */\\n (uint oErr, uint tokensHeld, uint amountOwed, ) = cToken.getAccountSnapshot(msg.sender);\\n require(oErr == 0, \\\"exitMarket: getAccountSnapshot failed\\\"); // semi-opaque error code\\n\\n /* Fail if the sender has a borrow balance */\\n if (amountOwed != 0) {\\n return fail(Error.NONZERO_BORROW_BALANCE, FailureInfo.EXIT_MARKET_BALANCE_OWED);\\n }\\n\\n /* Fail if the sender is not permitted to redeem all of their tokens */\\n uint allowed = redeemAllowedInternal(cTokenAddress, msg.sender, tokensHeld);\\n if (allowed != 0) {\\n return failOpaque(Error.REJECTION, FailureInfo.EXIT_MARKET_REJECTION, allowed);\\n }\\n\\n Market storage marketToExit = markets[address(cToken)];\\n\\n /* Return true if the sender is not already \\u2018in\\u2019 the market */\\n if (!marketToExit.accountMembership[msg.sender]) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Set cToken account membership to false */\\n delete marketToExit.accountMembership[msg.sender];\\n\\n /* Delete cToken from the account\\u2019s list of assets */\\n // load into memory for faster iteration\\n CToken[] memory userAssetList = accountAssets[msg.sender];\\n uint len = userAssetList.length;\\n uint assetIndex = len;\\n for (uint i = 0; i < len; i++) {\\n if (userAssetList[i] == cToken) {\\n assetIndex = i;\\n break;\\n }\\n }\\n\\n // We *must* have found the asset in the list or our redundant data structure is broken\\n assert(assetIndex < len);\\n\\n // copy last item in list to location of item to be removed, reduce length by 1\\n CToken[] storage storedList = accountAssets[msg.sender];\\n storedList[assetIndex] = storedList[storedList.length - 1];\\n storedList.length--;\\n\\n emit MarketExited(cToken, 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 cToken The market to verify the mint against\\n * @param minter The account which would get the minted tokens\\n * @param mintAmount The amount of underlying being supplied to the market in exchange for tokens\\n * @return 0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function mintAllowed(address cToken, address minter, uint mintAmount) external returns (uint) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n require(!mintGuardianPaused[cToken], \\\"mint is paused\\\");\\n\\n // Shh - currently unused\\n minter;\\n mintAmount;\\n\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n // *may include Policy Hook-type checks\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates mint and reverts on rejection. May emit logs.\\n * @param cToken Asset being minted\\n * @param minter The address minting the tokens\\n * @param actualMintAmount The amount of the underlying asset being minted\\n * @param mintTokens The number of tokens being minted\\n */\\n function mintVerify(address cToken, address minter, uint actualMintAmount, uint mintTokens) external {\\n // Shh - currently unused\\n cToken;\\n minter;\\n actualMintAmount;\\n mintTokens;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to redeem tokens in the given market\\n * @param cToken The market to verify the redeem against\\n * @param redeemer The account which would redeem the tokens\\n * @param redeemTokens The number of cTokens to exchange for the underlying asset in the market\\n * @return 0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function redeemAllowed(address cToken, address redeemer, uint redeemTokens) external returns (uint) {\\n return redeemAllowedInternal(cToken, redeemer, redeemTokens);\\n }\\n\\n function redeemAllowedInternal(address cToken, address redeemer, uint redeemTokens) internal view returns (uint) {\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n // *may include Policy Hook-type checks\\n\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!markets[cToken].accountMembership[redeemer]) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n (Error err, , uint shortfall) = getHypotheticalAccountLiquidityInternal(redeemer, CToken(cToken), redeemTokens, 0);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n if (shortfall > 0) {\\n return uint(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates redeem and reverts on rejection. May emit logs.\\n * @param cToken Asset being redeemed\\n * @param redeemer The address redeeming the tokens\\n * @param redeemAmount The amount of the underlying asset being redeemed\\n * @param redeemTokens The number of tokens being redeemed\\n */\\n function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) external {\\n // Shh - currently unused\\n cToken;\\n redeemer;\\n\\n // Require tokens is zero or amount is also zero\\n if (redeemTokens == 0 && redeemAmount > 0) {\\n revert(\\\"redeemTokens zero\\\");\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to borrow the underlying asset of the given market\\n * @param cToken The market to verify the borrow against\\n * @param borrower The account which would borrow the asset\\n * @param borrowAmount The amount of underlying the account would borrow\\n * @return 0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function borrowAllowed(address cToken, address borrower, uint borrowAmount) external returns (uint) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n require(!borrowGuardianPaused[cToken], \\\"borrow is paused\\\");\\n\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n // *may include Policy Hook-type checks\\n\\n if (!markets[cToken].accountMembership[borrower]) {\\n // only cTokens may call borrowAllowed if borrower not in market\\n require(msg.sender == cToken, \\\"sender must be cToken\\\");\\n\\n // attempt to add borrower to the market\\n Error err = addToMarketInternal(CToken(msg.sender), borrower);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n\\n // it should be impossible to break the important invariant\\n assert(markets[cToken].accountMembership[borrower]);\\n }\\n\\n if (oracle.getUnderlyingPrice(CToken(cToken)) == 0) {\\n return uint(Error.PRICE_ERROR);\\n }\\n\\n (Error err, , uint shortfall) = getHypotheticalAccountLiquidityInternal(borrower, CToken(cToken), 0, borrowAmount);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n if (shortfall > 0) {\\n return uint(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates borrow and reverts on rejection. May emit logs.\\n * @param cToken Asset whose underlying is being borrowed\\n * @param borrower The address borrowing the underlying\\n * @param borrowAmount The amount of the underlying asset requested to borrow\\n */\\n function borrowVerify(address cToken, address borrower, uint borrowAmount) external {\\n // Shh - currently unused\\n cToken;\\n borrower;\\n borrowAmount;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to repay a borrow in the given market\\n * @param cToken The market to verify the repay against\\n * @param payer The account which would repay the asset\\n * @param borrower The account which would borrowed the asset\\n * @param repayAmount The amount of the underlying asset the account would repay\\n * @return 0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function repayBorrowAllowed(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount) external returns (uint) {\\n // Shh - currently unused\\n payer;\\n borrower;\\n repayAmount;\\n\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n // *may include Policy Hook-type checks\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates repayBorrow and reverts on rejection. May emit logs.\\n * @param cToken Asset being repaid\\n * @param payer The address repaying the borrow\\n * @param borrower The address of the borrower\\n * @param actualRepayAmount The amount of underlying being repaid\\n */\\n function repayBorrowVerify(\\n address cToken,\\n address payer,\\n address borrower,\\n uint actualRepayAmount,\\n uint borrowerIndex) external {\\n // Shh - currently unused\\n cToken;\\n payer;\\n borrower;\\n actualRepayAmount;\\n borrowerIndex;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the liquidation should be allowed to occur\\n * @param cTokenBorrowed Asset which was borrowed by the borrower\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param repayAmount The amount of underlying being repaid\\n */\\n function liquidateBorrowAllowed(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount) external returns (uint) {\\n // Shh - currently unused\\n liquidator;\\n\\n if (!markets[cTokenBorrowed].isListed || !markets[cTokenCollateral].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n // *may include Policy Hook-type checks\\n\\n /* The borrower must have shortfall in order to be liquidatable */\\n (Error err, , uint shortfall) = getAccountLiquidityInternal(borrower);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n if (shortfall == 0) {\\n return uint(Error.INSUFFICIENT_SHORTFALL);\\n }\\n\\n /* The liquidator may not repay more than what is allowed by the closeFactor */\\n uint borrowBalance = CToken(cTokenBorrowed).borrowBalanceStored(borrower);\\n (MathError mathErr, uint maxClose) = mulScalarTruncate(Exp({mantissa: closeFactorMantissa}), borrowBalance);\\n if (mathErr != MathError.NO_ERROR) {\\n return uint(Error.MATH_ERROR);\\n }\\n if (repayAmount > 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 cTokenBorrowed Asset which was borrowed by the borrower\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param actualRepayAmount The amount of underlying being repaid\\n */\\n function liquidateBorrowVerify(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint actualRepayAmount,\\n uint seizeTokens) external {\\n // Shh - currently unused\\n cTokenBorrowed;\\n cTokenCollateral;\\n liquidator;\\n borrower;\\n actualRepayAmount;\\n seizeTokens;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the seizing of assets should be allowed to occur\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param cTokenBorrowed Asset which was borrowed by the borrower\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param seizeTokens The number of collateral tokens to seize\\n */\\n function seizeAllowed(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external returns (uint) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n require(!seizeGuardianPaused, \\\"seize is paused\\\");\\n\\n // Shh - currently unused\\n liquidator;\\n borrower;\\n seizeTokens;\\n\\n if (!markets[cTokenCollateral].isListed || !markets[cTokenBorrowed].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n if (CToken(cTokenCollateral).comptroller() != CToken(cTokenBorrowed).comptroller()) {\\n return uint(Error.COMPTROLLER_MISMATCH);\\n }\\n\\n // *may include Policy Hook-type checks\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates seize and reverts on rejection. May emit logs.\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param cTokenBorrowed Asset which was borrowed by the borrower\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param seizeTokens The number of collateral tokens to seize\\n */\\n function seizeVerify(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external {\\n // Shh - currently unused\\n cTokenCollateral;\\n cTokenBorrowed;\\n liquidator;\\n borrower;\\n seizeTokens;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to transfer tokens in the given market\\n * @param cToken The market to verify the transfer against\\n * @param src The account which sources the tokens\\n * @param dst The account which receives the tokens\\n * @param transferTokens The number of cTokens to transfer\\n * @return 0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function transferAllowed(address cToken, address src, address dst, uint transferTokens) external returns (uint) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n require(!transferGuardianPaused, \\\"transfer is paused\\\");\\n\\n // Shh - currently unused\\n dst;\\n\\n // *may include Policy Hook-type checks\\n\\n // Currently the only consideration is whether or not\\n // the src is allowed to redeem this many tokens\\n return redeemAllowedInternal(cToken, src, transferTokens);\\n }\\n\\n /**\\n * @notice Validates transfer and reverts on rejection. May emit logs.\\n * @param cToken Asset being transferred\\n * @param src The account which sources the tokens\\n * @param dst The account which receives the tokens\\n * @param transferTokens The number of cTokens to transfer\\n */\\n function transferVerify(address cToken, address src, address dst, uint transferTokens) external {\\n // Shh - currently unused\\n cToken;\\n src;\\n dst;\\n transferTokens;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n /**\\n * @dev Local vars for avoiding stack-depth limits in calculating account liquidity.\\n * Note that `cTokenBalance` is the number of cTokens the account owns in the market,\\n * whereas `borrowBalance` is the amount of underlying that the account has borrowed.\\n */\\n struct AccountLiquidityLocalVars {\\n uint sumCollateral;\\n uint sumBorrowPlusEffects;\\n uint cTokenBalance;\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n uint oraclePriceMantissa;\\n Exp collateralFactor;\\n Exp exchangeRate;\\n Exp oraclePrice;\\n Exp tokensToEther;\\n }\\n\\n /**\\n * @notice Determine the current account liquidity wrt collateral requirements\\n * @return (possible error code (semi-opaque),\\n account liquidity in excess of collateral requirements,\\n * account shortfall below collateral requirements)\\n */\\n function getAccountLiquidity(address account) public view returns (uint, uint, uint) {\\n (Error err, uint liquidity, uint shortfall) = getHypotheticalAccountLiquidityInternal(account, CToken(0), 0, 0);\\n\\n return (uint(err), liquidity, shortfall);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity wrt collateral requirements\\n * @return (possible error code,\\n account liquidity in excess of collateral requirements,\\n * account shortfall below collateral requirements)\\n */\\n function getAccountLiquidityInternal(address account) internal view returns (Error, uint, uint) {\\n return getHypotheticalAccountLiquidityInternal(account, CToken(0), 0, 0);\\n }\\n\\n /**\\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\\n * @param cTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @return (possible error code (semi-opaque),\\n hypothetical account liquidity in excess of collateral requirements,\\n * hypothetical account shortfall below collateral requirements)\\n */\\n function getHypotheticalAccountLiquidity(\\n address account,\\n address cTokenModify,\\n uint redeemTokens,\\n uint borrowAmount) public view returns (uint, uint, uint) {\\n (Error err, uint liquidity, uint shortfall) = getHypotheticalAccountLiquidityInternal(account, CToken(cTokenModify), 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 cTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @dev Note that we calculate the exchangeRateStored for each collateral cToken using stored data,\\n * without calculating accumulated interest.\\n * @return (possible error code,\\n hypothetical account liquidity in excess of collateral requirements,\\n * hypothetical account shortfall below collateral requirements)\\n */\\n function getHypotheticalAccountLiquidityInternal(\\n address account,\\n CToken cTokenModify,\\n uint redeemTokens,\\n uint borrowAmount) internal view returns (Error, uint, uint) {\\n\\n AccountLiquidityLocalVars memory vars; // Holds all our calculation results\\n uint oErr;\\n MathError mErr;\\n\\n // For each asset the account is in\\n CToken[] memory assets = accountAssets[account];\\n for (uint i = 0; i < assets.length; i++) {\\n CToken asset = assets[i];\\n\\n // Read the balances and exchange rate from the cToken\\n (oErr, vars.cTokenBalance, vars.borrowBalance, vars.exchangeRateMantissa) = asset.getAccountSnapshot(account);\\n if (oErr != 0) { // semi-opaque error code, we assume NO_ERROR == 0 is invariant between upgrades\\n return (Error.SNAPSHOT_ERROR, 0, 0);\\n }\\n vars.collateralFactor = Exp({mantissa: markets[address(asset)].collateralFactorMantissa});\\n vars.exchangeRate = Exp({mantissa: vars.exchangeRateMantissa});\\n\\n // Get the normalized price of the asset\\n vars.oraclePriceMantissa = oracle.getUnderlyingPrice(asset);\\n if (vars.oraclePriceMantissa == 0) {\\n return (Error.PRICE_ERROR, 0, 0);\\n }\\n vars.oraclePrice = Exp({mantissa: vars.oraclePriceMantissa});\\n\\n // Pre-compute a conversion factor from tokens -> ether (normalized price value)\\n (mErr, vars.tokensToEther) = mulExp3(vars.collateralFactor, vars.exchangeRate, vars.oraclePrice);\\n if (mErr != MathError.NO_ERROR) {\\n return (Error.MATH_ERROR, 0, 0);\\n }\\n\\n // sumCollateral += tokensToEther * cTokenBalance\\n (mErr, vars.sumCollateral) = mulScalarTruncateAddUInt(vars.tokensToEther, vars.cTokenBalance, 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 cTokenModify\\n if (asset == cTokenModify) {\\n // redeem effect\\n // sumBorrowPlusEffects += tokensToEther * redeemTokens\\n (mErr, vars.sumBorrowPlusEffects) = mulScalarTruncateAddUInt(vars.tokensToEther, redeemTokens, vars.sumBorrowPlusEffects);\\n if (mErr != MathError.NO_ERROR) {\\n return (Error.MATH_ERROR, 0, 0);\\n }\\n\\n // borrow effect\\n // sumBorrowPlusEffects += oraclePrice * borrowAmount\\n (mErr, vars.sumBorrowPlusEffects) = mulScalarTruncateAddUInt(vars.oraclePrice, borrowAmount, vars.sumBorrowPlusEffects);\\n if (mErr != MathError.NO_ERROR) {\\n return (Error.MATH_ERROR, 0, 0);\\n }\\n }\\n }\\n\\n // These are safe, as the underflow condition is checked first\\n if (vars.sumCollateral > vars.sumBorrowPlusEffects) {\\n return (Error.NO_ERROR, vars.sumCollateral - vars.sumBorrowPlusEffects, 0);\\n } else {\\n return (Error.NO_ERROR, 0, vars.sumBorrowPlusEffects - vars.sumCollateral);\\n }\\n }\\n\\n /**\\n * @notice Calculate number of tokens of collateral asset to seize given an underlying amount\\n * @dev Used in liquidation (called in cToken.liquidateBorrowFresh)\\n * @param cTokenBorrowed The address of the borrowed cToken\\n * @param cTokenCollateral The address of the collateral cToken\\n * @param actualRepayAmount The amount of cTokenBorrowed underlying to convert into cTokenCollateral tokens\\n * @return (errorCode, number of cTokenCollateral tokens to be seized in a liquidation)\\n */\\n function liquidateCalculateSeizeTokens(address cTokenBorrowed, address cTokenCollateral, uint actualRepayAmount) external view returns (uint, uint) {\\n /* Read oracle prices for borrowed and collateral markets */\\n uint priceBorrowedMantissa = oracle.getUnderlyingPrice(CToken(cTokenBorrowed));\\n uint priceCollateralMantissa = oracle.getUnderlyingPrice(CToken(cTokenCollateral));\\n if (priceBorrowedMantissa == 0 || priceCollateralMantissa == 0) {\\n return (uint(Error.PRICE_ERROR), 0);\\n }\\n\\n /*\\n * Get the exchange rate and calculate the number of collateral tokens to seize:\\n * seizeAmount = actualRepayAmount * liquidationIncentive * priceBorrowed / priceCollateral\\n * seizeTokens = seizeAmount / exchangeRate\\n * = actualRepayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate)\\n */\\n uint exchangeRateMantissa = CToken(cTokenCollateral).exchangeRateStored(); // Note: reverts on error\\n uint seizeTokens;\\n Exp memory numerator;\\n Exp memory denominator;\\n Exp memory ratio;\\n MathError mathErr;\\n\\n (mathErr, numerator) = mulExp(liquidationIncentiveMantissa, priceBorrowedMantissa);\\n if (mathErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0);\\n }\\n\\n (mathErr, denominator) = mulExp(priceCollateralMantissa, exchangeRateMantissa);\\n if (mathErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0);\\n }\\n\\n (mathErr, ratio) = divExp(numerator, denominator);\\n if (mathErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0);\\n }\\n\\n (mathErr, seizeTokens) = mulScalarTruncate(ratio, actualRepayAmount);\\n if (mathErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0);\\n }\\n\\n return (uint(Error.NO_ERROR), seizeTokens);\\n }\\n\\n /*** Admin Functions ***/\\n\\n /**\\n * @notice Sets a new price oracle for the comptroller\\n * @dev Admin function to set a new price oracle\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPriceOracle(PriceOracle newOracle) public returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PRICE_ORACLE_OWNER_CHECK);\\n }\\n\\n // Track the old oracle for the comptroller\\n PriceOracle oldOracle = oracle;\\n\\n // Set comptroller's oracle to newOracle\\n oracle = newOracle;\\n\\n // Emit NewPriceOracle(oldOracle, newOracle)\\n emit NewPriceOracle(oldOracle, newOracle);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets the closeFactor used when liquidating borrows\\n * @dev Admin function to set closeFactor\\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\\n * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function _setCloseFactor(uint newCloseFactorMantissa) external returns (uint256) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_CLOSE_FACTOR_OWNER_CHECK);\\n }\\n\\n Exp memory newCloseFactorExp = Exp({mantissa: newCloseFactorMantissa});\\n Exp memory lowLimit = Exp({mantissa: closeFactorMinMantissa});\\n if (lessThanOrEqualExp(newCloseFactorExp, lowLimit)) {\\n return fail(Error.INVALID_CLOSE_FACTOR, FailureInfo.SET_CLOSE_FACTOR_VALIDATION);\\n }\\n\\n Exp memory highLimit = Exp({mantissa: closeFactorMaxMantissa});\\n if (lessThanExp(highLimit, newCloseFactorExp)) {\\n return fail(Error.INVALID_CLOSE_FACTOR, FailureInfo.SET_CLOSE_FACTOR_VALIDATION);\\n }\\n\\n uint oldCloseFactorMantissa = closeFactorMantissa;\\n closeFactorMantissa = newCloseFactorMantissa;\\n emit NewCloseFactor(oldCloseFactorMantissa, closeFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets the collateralFactor for a market\\n * @dev Admin function to set per-market collateralFactor\\n * @param cToken The market to set the factor on\\n * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18\\n * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function _setCollateralFactor(CToken cToken, uint newCollateralFactorMantissa) external returns (uint256) {\\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(cToken)];\\n if (!market.isListed) {\\n return fail(Error.MARKET_NOT_LISTED, FailureInfo.SET_COLLATERAL_FACTOR_NO_EXISTS);\\n }\\n\\n Exp memory newCollateralFactorExp = Exp({mantissa: newCollateralFactorMantissa});\\n\\n // Check collateral factor <= 0.9\\n Exp memory highLimit = Exp({mantissa: collateralFactorMaxMantissa});\\n if (lessThanExp(highLimit, newCollateralFactorExp)) {\\n return fail(Error.INVALID_COLLATERAL_FACTOR, FailureInfo.SET_COLLATERAL_FACTOR_VALIDATION);\\n }\\n\\n // If collateral factor != 0, fail if price == 0\\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(cToken) == 0) {\\n return fail(Error.PRICE_ERROR, FailureInfo.SET_COLLATERAL_FACTOR_WITHOUT_PRICE);\\n }\\n\\n // Set market's collateral factor to new collateral factor, remember old value\\n uint oldCollateralFactorMantissa = market.collateralFactorMantissa;\\n market.collateralFactorMantissa = newCollateralFactorMantissa;\\n\\n // Emit event with asset, old collateral factor, and new collateral factor\\n emit NewCollateralFactor(cToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets maxAssets which controls how many markets can be entered\\n * @dev Admin function to set maxAssets\\n * @param newMaxAssets New max assets\\n * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function _setMaxAssets(uint newMaxAssets) external returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_MAX_ASSETS_OWNER_CHECK);\\n }\\n\\n uint oldMaxAssets = maxAssets;\\n maxAssets = newMaxAssets;\\n emit NewMaxAssets(oldMaxAssets, newMaxAssets);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets liquidationIncentive\\n * @dev Admin function to set liquidationIncentive\\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\\n * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function _setLiquidationIncentive(uint newLiquidationIncentiveMantissa) external returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_LIQUIDATION_INCENTIVE_OWNER_CHECK);\\n }\\n\\n // Check de-scaled min <= newLiquidationIncentive <= max\\n Exp memory newLiquidationIncentive = Exp({mantissa: newLiquidationIncentiveMantissa});\\n Exp memory minLiquidationIncentive = Exp({mantissa: liquidationIncentiveMinMantissa});\\n if (lessThanExp(newLiquidationIncentive, minLiquidationIncentive)) {\\n return fail(Error.INVALID_LIQUIDATION_INCENTIVE, FailureInfo.SET_LIQUIDATION_INCENTIVE_VALIDATION);\\n }\\n\\n Exp memory maxLiquidationIncentive = Exp({mantissa: liquidationIncentiveMaxMantissa});\\n if (lessThanExp(maxLiquidationIncentive, newLiquidationIncentive)) {\\n return fail(Error.INVALID_LIQUIDATION_INCENTIVE, FailureInfo.SET_LIQUIDATION_INCENTIVE_VALIDATION);\\n }\\n\\n // Save current value for use in log\\n uint oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa;\\n\\n // Set liquidation incentive to new incentive\\n liquidationIncentiveMantissa = newLiquidationIncentiveMantissa;\\n\\n // Emit event with old incentive, new incentive\\n emit NewLiquidationIncentive(oldLiquidationIncentiveMantissa, newLiquidationIncentiveMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Add the market to the markets mapping and set it as listed\\n * @dev Admin function to set isListed and add support for the market\\n * @param cToken The address of the market (token) to list\\n * @return uint 0=success, otherwise a failure. (See enum Error for details)\\n */\\n function _supportMarket(CToken cToken) external returns (uint) {\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SUPPORT_MARKET_OWNER_CHECK);\\n }\\n\\n if (markets[address(cToken)].isListed) {\\n return fail(Error.MARKET_ALREADY_LISTED, FailureInfo.SUPPORT_MARKET_EXISTS);\\n }\\n\\n cToken.isCToken(); // Sanity check to make sure its really a CToken\\n\\n markets[address(cToken)] = Market({isListed: true, isComped: false, collateralFactorMantissa: 0});\\n emit MarketListed(cToken);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Admin function to change the Pause Guardian\\n * @param newPauseGuardian The address of the new Pause Guardian\\n * @return uint 0=success, otherwise a failure. (See enum Error for details)\\n */\\n function _setPauseGuardian(address newPauseGuardian) public returns (uint) {\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PAUSE_GUARDIAN_OWNER_CHECK);\\n }\\n\\n // Save current value for inclusion in log\\n address oldPauseGuardian = pauseGuardian;\\n\\n // Store pauseGuardian with value newPauseGuardian\\n pauseGuardian = newPauseGuardian;\\n\\n // Emit NewPauseGuardian(OldPauseGuardian, NewPauseGuardian)\\n emit NewPauseGuardian(oldPauseGuardian, pauseGuardian);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n function _setMintPaused(CToken cToken, bool state) public returns (bool) {\\n require(markets[address(cToken)].isListed, \\\"cannot pause a market that is not listed\\\");\\n require(msg.sender == pauseGuardian || msg.sender == admin, \\\"only pause guardian and admin can pause\\\");\\n require(msg.sender == admin || state == true, \\\"only admin can unpause\\\");\\n\\n mintGuardianPaused[address(cToken)] = state;\\n emit ActionPaused(cToken, \\\"Mint\\\", state);\\n return state;\\n }\\n\\n function _setBorrowPaused(CToken cToken, bool state) public returns (bool) {\\n require(markets[address(cToken)].isListed, \\\"cannot pause a market that is not listed\\\");\\n require(msg.sender == pauseGuardian || msg.sender == admin, \\\"only pause guardian and admin can pause\\\");\\n require(msg.sender == admin || state == true, \\\"only admin can unpause\\\");\\n\\n borrowGuardianPaused[address(cToken)] = state;\\n emit ActionPaused(cToken, \\\"Borrow\\\", state);\\n return state;\\n }\\n\\n function _setTransferPaused(bool state) public returns (bool) {\\n require(msg.sender == pauseGuardian || msg.sender == admin, \\\"only pause guardian and admin can pause\\\");\\n require(msg.sender == admin || state == true, \\\"only admin can unpause\\\");\\n\\n transferGuardianPaused = state;\\n emit ActionPaused(\\\"Transfer\\\", state);\\n return state;\\n }\\n\\n function _setSeizePaused(bool state) public returns (bool) {\\n require(msg.sender == pauseGuardian || msg.sender == admin, \\\"only pause guardian and admin can pause\\\");\\n require(msg.sender == admin || state == true, \\\"only admin can unpause\\\");\\n\\n seizeGuardianPaused = state;\\n emit ActionPaused(\\\"Seize\\\", state);\\n return state;\\n }\\n\\n function _become(Unitroller unitroller) public {\\n require(msg.sender == unitroller.admin(), \\\"only unitroller admin can change brains\\\");\\n\\n uint changeStatus = unitroller._acceptImplementation();\\n require(changeStatus == 0, \\\"change not authorized\\\");\\n }\\n}\\n\",\"keccak256\":\"0xc65f8c07e0f55cc119be511c5c108b3f78d319daba3b2b54e3bc7fbcdbe89380\"},\"contracts/ComptrollerInterface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\ncontract ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n bool public constant isComptroller = true;\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata cTokens) external returns (uint[] memory);\\n function exitMarket(address cToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address cToken, address minter, uint mintAmount) external returns (uint);\\n function mintVerify(address cToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address cToken, address redeemer, uint redeemTokens) external returns (uint);\\n function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address cToken, address borrower, uint borrowAmount) external returns (uint);\\n function borrowVerify(address cToken, address borrower, uint borrowAmount) external;\\n\\n function repayBorrowAllowed(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount) external returns (uint);\\n function repayBorrowVerify(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex) external;\\n\\n function liquidateBorrowAllowed(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount) external returns (uint);\\n function liquidateBorrowVerify(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens) external;\\n\\n function seizeAllowed(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external returns (uint);\\n function seizeVerify(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external;\\n\\n function transferAllowed(address cToken, address src, address dst, uint transferTokens) external returns (uint);\\n function transferVerify(address cToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n uint repayAmount) external view returns (uint, uint);\\n}\\n\",\"keccak256\":\"0xede7670d2dd7b25d0187aecd2c28b7b5ca7d7c1bdac144fbedecf5d4bdd92a6b\"},\"contracts/ComptrollerStorage.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.sol\\\";\\nimport \\\"./PriceOracle.sol\\\";\\n\\ncontract UnitrollerAdminStorage {\\n /**\\n * @notice Administrator for this contract\\n */\\n address public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address public pendingAdmin;\\n\\n /**\\n * @notice Active brains of Unitroller\\n */\\n address public comptrollerImplementation;\\n\\n /**\\n * @notice Pending brains of Unitroller\\n */\\n address public pendingComptrollerImplementation;\\n}\\n\\ncontract ComptrollerV1Storage is UnitrollerAdminStorage {\\n\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n PriceOracle public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives\\n */\\n uint public liquidationIncentiveMantissa;\\n\\n /**\\n * @notice Max number of assets a single account can participate in (borrow or use as collateral)\\n */\\n uint public maxAssets;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\\n */\\n mapping(address => CToken[]) public accountAssets;\\n\\n}\\n\\ncontract ComptrollerV2Storage is ComptrollerV1Storage {\\n struct Market {\\n /// @notice Whether or not this market is listed\\n bool isListed;\\n\\n /**\\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\\n * For instance, 0.9 to allow borrowing 90% of collateral value.\\n * Must be between 0 and 1, and stored as a mantissa.\\n */\\n uint collateralFactorMantissa;\\n\\n /// @notice Per-market mapping of \\\"accounts in this asset\\\"\\n mapping(address => bool) accountMembership;\\n\\n /// @notice Whether or not this market receives COMP\\n bool isComped;\\n }\\n\\n /**\\n * @notice Official mapping of cTokens -> Market metadata\\n * @dev Used e.g. to determine if a market is supported\\n */\\n mapping(address => Market) public markets;\\n\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n * Actions which allow users to remove their own assets cannot be paused.\\n * Liquidation / seizing / transfer can only be paused globally, not by market.\\n */\\n address public pauseGuardian;\\n bool public _mintGuardianPaused;\\n bool public _borrowGuardianPaused;\\n bool public transferGuardianPaused;\\n bool public seizeGuardianPaused;\\n mapping(address => bool) public mintGuardianPaused;\\n mapping(address => bool) public borrowGuardianPaused;\\n}\\n\\ncontract ComptrollerV3Storage is ComptrollerV2Storage {\\n struct CompMarketState {\\n /// @notice The market's last updated compBorrowIndex or compSupplyIndex\\n uint224 index;\\n\\n /// @notice The block number the index was last updated at\\n uint32 block;\\n }\\n\\n /// @notice A list of all markets\\n CToken[] public allMarkets;\\n\\n /// @notice The rate at which the flywheel distributes COMP, per block\\n uint public compRate;\\n\\n /// @notice The portion of compRate that each market currently receives\\n mapping(address => uint) public compSpeeds;\\n\\n /// @notice The COMP market supply state for each market\\n mapping(address => CompMarketState) public compSupplyState;\\n\\n /// @notice The COMP market borrow state for each market\\n mapping(address => CompMarketState) public compBorrowState;\\n\\n /// @notice The COMP borrow index for each market for each supplier as of the last time they accrued COMP\\n mapping(address => mapping(address => uint)) public compSupplierIndex;\\n\\n /// @notice The COMP borrow index for each market for each borrower as of the last time they accrued COMP\\n mapping(address => mapping(address => uint)) public compBorrowerIndex;\\n\\n /// @notice The COMP accrued but not yet transferred to each user\\n mapping(address => uint) public compAccrued;\\n}\\n\\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\\n // @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\\n address public borrowCapGuardian;\\n\\n // @notice Borrow caps enforced by borrowAllowed for each cToken address. Defaults to zero which corresponds to unlimited borrowing.\\n mapping(address => uint) public borrowCaps;\\n}\\n\\ncontract ComptrollerV5Storage is ComptrollerV4Storage {\\n /// @notice The portion of COMP that each contributor receives per block\\n mapping(address => uint) public compContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's COMP rewards have been allocated\\n mapping(address => uint) public lastContributorBlock;\\n}\\n\",\"keccak256\":\"0x5db970485549f493618b5e36bfd4d799d4f8701a136bf71ed6e0117e1ed8c254\"},\"contracts/EIP20Interface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title ERC 20 Token Standard Interface\\n * https://eips.ethereum.org/EIPS/eip-20\\n */\\ninterface EIP20Interface {\\n function name() external view returns (string memory);\\n function symbol() external view returns (string memory);\\n function decimals() external view returns (uint8);\\n\\n /**\\n * @notice Get the total number of tokens in circulation\\n * @return The supply of tokens\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @notice Gets the balance of the specified address\\n * @param owner The address from which the balance will be retrieved\\n * @return The balance\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transfer(address dst, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferFrom(address src, address dst, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (-1 means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (-1 means infinite)\\n */\\n function allowance(address owner, address spender) external view returns (uint256 remaining);\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n}\\n\",\"keccak256\":\"0xfd8ed2eac6d0b4d9ee6b32628ba68bae17544b66f190a5f7ce0c6ad024579dc8\"},\"contracts/EIP20NonStandardInterface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title EIP20NonStandardInterface\\n * @dev Version of ERC20 with no return values for `transfer` and `transferFrom`\\n * See https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\\n */\\ninterface EIP20NonStandardInterface {\\n\\n /**\\n * @notice Get the total number of tokens in circulation\\n * @return The supply of tokens\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @notice Gets the balance of the specified address\\n * @param owner The address from which the balance will be retrieved\\n * @return The balance\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n ///\\n /// !!!!!!!!!!!!!!\\n /// !!! NOTICE !!! `transfer` does not return a value, in violation of the ERC-20 specification\\n /// !!!!!!!!!!!!!!\\n ///\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n */\\n function transfer(address dst, uint256 amount) external;\\n\\n ///\\n /// !!!!!!!!!!!!!!\\n /// !!! NOTICE !!! `transferFrom` does not return a value, in violation of the ERC-20 specification\\n /// !!!!!!!!!!!!!!\\n ///\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n */\\n function transferFrom(address src, address dst, uint256 amount) external;\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent\\n */\\n function allowance(address owner, address spender) external view returns (uint256 remaining);\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n}\\n\",\"keccak256\":\"0x9719f12e4b80b51147ac195553a198cf8b0c516e7e4d04fc324a23ed15cbafb2\"},\"contracts/ErrorReporter.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\ncontract ComptrollerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\",\"keccak256\":\"0x5179afb1071c0fd555e5c1f1d2565f72dbe1740cc3dd02f6e52037f150afc5c9\"},\"contracts/Exponential.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CarefulMath.sol\\\";\\nimport \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @dev Legacy contract for compatibility reasons with existing contracts that still use MathError\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: rational}));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({mantissa: result}));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({mantissa: result}));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: scaledMantissa}));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: descaledMantissa}));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) pure internal returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({mantissa: 0}));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({mantissa: product}));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) pure internal returns (MathError, Exp memory) {\\n return mulExp(Exp({mantissa: a}), Exp({mantissa: b}));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) pure internal returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6ff054d65a0289dbb43c9f437d6909f9cf1207c9b8f984b3cb8e97a9de76a434\"},\"contracts/ExponentialNoError.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\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 Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) pure internal returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) pure internal returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) pure internal returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) pure internal returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) pure internal returns (uint224) {\\n require(n < 2**224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) pure internal returns (uint32) {\\n require(n < 2**32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: add_(a.mantissa, b.mantissa)});\\n }\\n\\n function add_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: add_(a.mantissa, b.mantissa)});\\n }\\n\\n function add_(uint a, uint b) pure internal returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: sub_(a.mantissa, b.mantissa)});\\n }\\n\\n function sub_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: sub_(a.mantissa, b.mantissa)});\\n }\\n\\n function sub_(uint a, uint b) pure internal returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: mul_(a.mantissa, b.mantissa) / expScale});\\n }\\n\\n function mul_(Exp memory a, uint b) pure internal returns (Exp memory) {\\n return Exp({mantissa: mul_(a.mantissa, b)});\\n }\\n\\n function mul_(uint a, Exp memory b) pure internal returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: mul_(a.mantissa, b.mantissa) / doubleScale});\\n }\\n\\n function mul_(Double memory a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: mul_(a.mantissa, b)});\\n }\\n\\n function mul_(uint a, Double memory b) pure internal returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) pure internal returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) pure internal 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) pure internal returns (Exp memory) {\\n return Exp({mantissa: div_(mul_(a.mantissa, expScale), b.mantissa)});\\n }\\n\\n function div_(Exp memory a, uint b) pure internal returns (Exp memory) {\\n return Exp({mantissa: div_(a.mantissa, b)});\\n }\\n\\n function div_(uint a, Exp memory b) pure internal returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa)});\\n }\\n\\n function div_(Double memory a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(a.mantissa, b)});\\n }\\n\\n function div_(uint a, Double memory b) pure internal returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) pure internal returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(mul_(a, doubleScale), b)});\\n }\\n}\\n\",\"keccak256\":\"0x7cb184b7cee71a5e707053dfba7eebbd46f11974004028100510ccce19b6694d\"},\"contracts/InterestRateModel.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Compound's InterestRateModel Interface\\n * @author Compound\\n */\\ncontract InterestRateModel {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint cash, uint borrows, uint reserves) external view returns (uint);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) external view returns (uint);\\n\\n}\\n\",\"keccak256\":\"0x929282d73c79e6d700ebe79f9fafc1e414b3848acff5a56d6740afd1dc908678\"},\"contracts/PriceOracle.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.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 cToken asset\\n * @param cToken The cToken to get the underlying price of\\n * @return The underlying asset price mantissa (scaled by 1e18).\\n * Zero means the price is unavailable.\\n */\\n function getUnderlyingPrice(CToken cToken) external view returns (uint);\\n}\\n\",\"keccak256\":\"0xe79ebc23bba508eb2479e7b3340abf566da1ab62131f106aee1aac3dc53816ef\"},\"contracts/Unitroller.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ErrorReporter.sol\\\";\\nimport \\\"./ComptrollerStorage.sol\\\";\\n/**\\n * @title ComptrollerCore\\n * @dev Storage for the comptroller is at this address, while execution is delegated to the `comptrollerImplementation`.\\n * CTokens should reference this contract as their comptroller.\\n */\\ncontract Unitroller is UnitrollerAdminStorage, ComptrollerErrorReporter {\\n\\n /**\\n * @notice Emitted when pendingComptrollerImplementation is changed\\n */\\n event NewPendingImplementation(address oldPendingImplementation, address newPendingImplementation);\\n\\n /**\\n * @notice Emitted when pendingComptrollerImplementation is accepted, which means comptroller implementation is updated\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Emitted when pendingAdmin is accepted, which means admin is updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n constructor() public {\\n // Set admin to caller\\n admin = msg.sender;\\n }\\n\\n /*** Admin Functions ***/\\n function _setPendingImplementation(address newPendingImplementation) public returns (uint) {\\n\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_IMPLEMENTATION_OWNER_CHECK);\\n }\\n\\n address oldPendingImplementation = pendingComptrollerImplementation;\\n\\n pendingComptrollerImplementation = newPendingImplementation;\\n\\n emit NewPendingImplementation(oldPendingImplementation, pendingComptrollerImplementation);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts new implementation of comptroller. msg.sender must be pendingImplementation\\n * @dev Admin function for new implementation to accept it's role as implementation\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptImplementation() public returns (uint) {\\n // Check caller is pendingImplementation and pendingImplementation \\u2260 address(0)\\n if (msg.sender != pendingComptrollerImplementation || pendingComptrollerImplementation == address(0)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldImplementation = comptrollerImplementation;\\n address oldPendingImplementation = pendingComptrollerImplementation;\\n\\n comptrollerImplementation = pendingComptrollerImplementation;\\n\\n pendingComptrollerImplementation = address(0);\\n\\n emit NewImplementation(oldImplementation, comptrollerImplementation);\\n emit NewPendingImplementation(oldPendingImplementation, pendingComptrollerImplementation);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPendingAdmin(address newPendingAdmin) public returns (uint) {\\n // Check caller = admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\\n }\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptAdmin() public returns (uint) {\\n // Check caller is pendingAdmin and pendingAdmin \\u2260 address(0)\\n if (msg.sender != pendingAdmin || msg.sender == address(0)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = address(0);\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return 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 () payable external {\\n // delegate all other functions to current implementation\\n (bool success, ) = comptrollerImplementation.delegatecall(msg.data);\\n\\n assembly {\\n let free_mem_ptr := mload(0x40)\\n returndatacopy(free_mem_ptr, 0, returndatasize)\\n\\n switch success\\n case 0 { revert(free_mem_ptr, returndatasize) }\\n default { return(free_mem_ptr, returndatasize) }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x51f81451eab9d5c4849507e724f2b2c53e41f54e5359fdbeae89432a727c16df\"},\"tests/Contracts/ComptrollerScenarioG2.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"../../contracts/ComptrollerG2.sol\\\";\\n\\ncontract ComptrollerScenarioG2 is ComptrollerG2 {\\n uint public blockNumber;\\n address public compAddress;\\n\\n constructor() ComptrollerG2() public {}\\n\\n function fastForward(uint blocks) public returns (uint) {\\n blockNumber += blocks;\\n return blockNumber;\\n }\\n\\n function setBlockNumber(uint number) public {\\n blockNumber = number;\\n }\\n}\\n\",\"keccak256\":\"0x174700aecc783c2544108a2c346add30629a1bdd8ba5aef0e2434f0949d870f0\"}},\"version\":1}" + }, + "tests/Contracts/ComptrollerScenarioG3.sol:ComptrollerScenarioG3": { + "abi": "[{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"action\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"pauseState\",\"type\":\"bool\"}],\"name\":\"ActionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"action\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"pauseState\",\"type\":\"bool\"}],\"name\":\"ActionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSpeed\",\"type\":\"uint256\"}],\"name\":\"CompSpeedUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compBorrowIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedBorrowerComp\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"supplier\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compSupplyIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedSupplierComp\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isComped\",\"type\":\"bool\"}],\"name\":\"MarketComped\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketEntered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketExited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"MarketListed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCloseFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCloseFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCollateralFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCollateralFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCompRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCompRate\",\"type\":\"uint256\"}],\"name\":\"NewCompRate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldLiquidationIncentiveMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"NewLiquidationIncentive\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMaxAssets\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMaxAssets\",\"type\":\"uint256\"}],\"name\":\"NewMaxAssets\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldPauseGuardian\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"NewPauseGuardian\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"oldPriceOracle\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"newPriceOracle\",\"type\":\"address\"}],\"name\":\"NewPriceOracle\",\"type\":\"event\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"_addCompMarkets\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract Unitroller\",\"name\":\"unitroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"compRate_\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"compMarketsToAdd\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"otherMarketsToAdd\",\"type\":\"address[]\"}],\"name\":\"_become\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"compRate_\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"compMarketsToAdd\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"otherMarketsToAdd\",\"type\":\"address[]\"}],\"name\":\"_becomeG3\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"_dropCompMarket\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setBorrowPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCloseFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCollateralFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"compRate_\",\"type\":\"uint256\"}],\"name\":\"_setCompRate\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"_setLiquidationIncentive\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newMaxAssets\",\"type\":\"uint256\"}],\"name\":\"_setMaxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setMintPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"_setPauseGuardian\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"newOracle\",\"type\":\"address\"}],\"name\":\"_setPriceOracle\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setSeizePaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setTransferPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"_supportMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allMarkets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"blockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"checkMembership\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"},{\"internalType\":\"contract CToken[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"holders\",\"type\":\"address[]\"},{\"internalType\":\"contract CToken[]\",\"name\":\"cTokens\",\"type\":\"address[]\"},{\"internalType\":\"bool\",\"name\":\"borrowers\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"suppliers\",\"type\":\"bool\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compAccrued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compBorrowState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compBorrowerIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compClaimThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compInitialIndex\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSupplierIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSupplyState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"enterMarkets\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenAddress\",\"type\":\"address\"}],\"name\":\"exitMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blocks\",\"type\":\"uint256\"}],\"name\":\"fastForward\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getAllMarkets\",\"outputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAssetsIn\",\"outputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getCompAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getCompMarkets\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenModify\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"getHypotheticalAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"isComptroller\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateCalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"liquidationIncentiveMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"markets\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isComped\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"membershipLength\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"mintAmount\",\"type\":\"uint256\"}],\"name\":\"mintAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualMintAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"mintTokens\",\"type\":\"uint256\"}],\"name\":\"mintVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"refreshCompSpeeds\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"repayBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowerIndex\",\"type\":\"uint256\"}],\"name\":\"repayBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"seizeGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"}],\"name\":\"setBlockNumber\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"compAddress_\",\"type\":\"address\"}],\"name\":\"setCompAddress\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"transferGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"unlist\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + "bin": "608060405234801561001057600080fd5b50600080546001600160a01b0319163317905561617d80620000336000396000f3fe608060405234801561001057600080fd5b506004361061047f5760003560e01c80637dc0d1d011610257578063bdcdc25811610146578063dce15449116100c3578063e9af029211610087578063e9af029214611418578063eabe7d911461143e578063ede4edd014611474578063f851a4401461149a578063fccbe7f6146114a25761047f565b8063dce15449146113a8578063dcfbc0c7146113d4578063e4028eee146113dc578063e6653f3d14611408578063e8755446146114105761047f565b8063cc7ebdc41161010a578063cc7ebdc414611248578063ce485c5e1461126e578063d02f73511461130f578063d9226ced14611355578063da3d454c146113725761047f565b8063bdcdc258146110c8578063bde3672d14611104578063c29982381461112a578063c488847b146111cb578063ca0af0431461121a5761047f565b8063a76b3fda116101d4578063ac0b0bb711610198578063ac0b0bb71461107a578063aee260b414611082578063b0772d0b1461108a578063b21be7fd14611092578063bb82aa5e146110c05761047f565b8063a76b3fda14610f95578063a7f0e23114610fbb578063a8c3c85014610fdf578063aa90075414610ffc578063abfceffc146110045761047f565b80638ebf63641161021b5780638ebf636414610e00578063929fe9a114610e1f57806394b2294b14610e4d578063992c529414610e555780639d1b5a0a14610f8d5761047f565b80637dc0d1d014610d5c578063858aa5e514610d6457806387f7630314610d8a5780638c57804e14610d925780638e8f294b14610db85761047f565b80634e79238f116103735780635fc7e71e116102f05780636d154ea5116102b45780636d154ea514610cba5780636d35bf9114610ce0578063731f0c2b14610d26578063747026c914610d4c5780637d3ab61a14610d545761047f565b80635fc7e71e14610aa15780636810dfa614610ae75780636a49111214610c135780636a56947e14610c305780636b79c38d14610c6c5761047f565b806355ee1fe11161033757806355ee1fe1146109f157806357e871e714610a175780635c77860514610a1f5780635ec88c7914610a555780635f5af1aa14610a7b5761047f565b80634e79238f146108eb5780634ef4c3e1146109455780634fd42e171461097b57806351dff9891461099857806352d84d1e146109d45761047f565b8063317b0b771161040157806342cbb15c116103c557806342cbb15c1461086157806347ef3b3b146108695780634ada90af146108b55780634bca0d8c146108bd5780634d8e5037146108e35761047f565b8063317b0b77146107ac5780633aa729b4146107c95780633bcf7ec1146107ef5780633c94786f1461081d57806341c728b9146108255761047f565b80632327c7df116104485780632327c7df146105fb57806324008a621461072557806324a3d6221461076157806326782247146107855780632d70db781461078d5761047f565b80627e3dd21461048457806318c882a5146104a05780631c3db2e0146104ce5780631d7b33d7146105815780631ededc91146105b9575b600080fd5b61048c6114bf565b604080519115158252519081900360200190f35b61048c600480360360408110156104b657600080fd5b506001600160a01b03813516906020013515156114c4565b61057f600480360360408110156104e457600080fd5b6001600160a01b038235169190810190604081016020820135600160201b81111561050e57600080fd5b82018360208201111561052057600080fd5b803590602001918460208302840111600160201b8311171561054157600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550611664945050505050565b005b6105a76004803603602081101561059757600080fd5b50356001600160a01b03166116c6565b60408051918252519081900360200190f35b61057f600480360360a08110156105cf57600080fd5b506001600160a01b038135811691602081013582169160408201351690606081013590608001356116d8565b61057f6004803603606081101561061157600080fd5b81359190810190604081016020820135600160201b81111561063257600080fd5b82018360208201111561064457600080fd5b803590602001918460208302840111600160201b8311171561066557600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b8111156106b457600080fd5b8201836020820111156106c657600080fd5b803590602001918460208302840111600160201b831117156106e757600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295506116df945050505050565b6105a76004803603608081101561073b57600080fd5b506001600160a01b038135811691602081013582169160408201351690606001356117a5565b61076961186e565b604080516001600160a01b039092168252519081900360200190f35b61076961187d565b61048c600480360360208110156107a357600080fd5b5035151561188c565b6105a7600480360360208110156107c257600080fd5b50356119c6565b61057f600480360360208110156107df57600080fd5b50356001600160a01b0316611ad7565b61048c6004803603604081101561080557600080fd5b506001600160a01b0381351690602001351515611c08565b61048c611da3565b61057f6004803603608081101561083b57600080fd5b506001600160a01b03813581169160208101359091169060408101359060600135611db3565b6105a7611db9565b61057f600480360360c081101561087f57600080fd5b506001600160a01b0381358116916020810135821691604082013581169160608101359091169060808101359060a00135611dc0565b6105a7611dc8565b6105a7600480360360208110156108d357600080fd5b50356001600160a01b0316611dce565b61057f611de9565b6109276004803603608081101561090157600080fd5b506001600160a01b0381358116916020810135909116906040810135906060013561223b565b60408051938452602084019290925282820152519081900360600190f35b6105a76004803603606081101561095b57600080fd5b506001600160a01b03813581169160208101359091169060400135612275565b6105a76004803603602081101561099157600080fd5b5035612320565b61057f600480360360808110156109ae57600080fd5b506001600160a01b03813581169160208101359091169060408101359060600135612414565b610769600480360360208110156109ea57600080fd5b5035612468565b6105a760048036036020811015610a0757600080fd5b50356001600160a01b031661248f565b6105a7612516565b61057f60048036036060811015610a3557600080fd5b506001600160a01b0381358116916020810135909116906040013561251c565b61092760048036036020811015610a6b57600080fd5b50356001600160a01b0316612521565b6105a760048036036020811015610a9157600080fd5b50356001600160a01b0316612556565b6105a7600480360360a0811015610ab757600080fd5b506001600160a01b03813581169160208101358216916040820135811691606081013590911690608001356125da565b61057f60048036036080811015610afd57600080fd5b810190602081018135600160201b811115610b1757600080fd5b820183602082011115610b2957600080fd5b803590602001918460208302840111600160201b83111715610b4a57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b811115610b9957600080fd5b820183602082011115610bab57600080fd5b803590602001918460208302840111600160201b83111715610bcc57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550505050803515159150602001351515612761565b61057f60048036036020811015610c2957600080fd5b503561290a565b61057f60048036036080811015610c4657600080fd5b506001600160a01b03813581169160208101358216916040820135169060600135611db3565b610c9260048036036020811015610c8257600080fd5b50356001600160a01b03166129ae565b604080516001600160e01b03909316835263ffffffff90911660208301528051918290030190f35b61048c60048036036020811015610cd057600080fd5b50356001600160a01b03166129d8565b61057f600480360360a0811015610cf657600080fd5b506001600160a01b03813581169160208101358216916040820135811691606081013590911690608001356116d8565b61048c60048036036020811015610d3c57600080fd5b50356001600160a01b03166129ed565b6105a7612a02565b610769612a0d565b610769612a1c565b61057f60048036036020811015610d7a57600080fd5b50356001600160a01b0316612a2b565b61048c612a4d565b610c9260048036036020811015610da857600080fd5b50356001600160a01b0316612a5d565b610dde60048036036020811015610dce57600080fd5b50356001600160a01b0316612a87565b6040805193151584526020840192909252151582820152519081900360600190f35b61048c60048036036020811015610e1657600080fd5b50351515612aad565b61048c60048036036040811015610e3557600080fd5b506001600160a01b0381358116916020013516612be6565b6105a7612c19565b61057f60048036036080811015610e6b57600080fd5b6001600160a01b0382351691602081013591810190606081016040820135600160201b811115610e9a57600080fd5b820183602082011115610eac57600080fd5b803590602001918460208302840111600160201b83111715610ecd57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b811115610f1c57600080fd5b820183602082011115610f2e57600080fd5b803590602001918460208302840111600160201b83111715610f4f57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550612c1f945050505050565b610769612e6b565b6105a760048036036020811015610fab57600080fd5b50356001600160a01b0316612e7a565b610fc3612fd7565b604080516001600160e01b039092168252519081900360200190f35b61057f60048036036020811015610ff557600080fd5b5035612fea565b6105a7612fef565b61102a6004803603602081101561101a57600080fd5b50356001600160a01b0316612ff5565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561106657818101518382015260200161104e565b505050509050019250505060405180910390f35b61048c61307e565b61102a61308e565b61102a6131d6565b6105a7600480360360408110156110a857600080fd5b506001600160a01b0381358116916020013516613238565b610769613255565b6105a7600480360360808110156110de57600080fd5b506001600160a01b03813581169160208101358216916040820135169060600135613264565b61057f6004803603602081101561111a57600080fd5b50356001600160a01b03166132f8565b61102a6004803603602081101561114057600080fd5b810190602081018135600160201b81111561115a57600080fd5b82018360208201111561116c57600080fd5b803590602001918460208302840111600160201b8311171561118d57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550613319945050505050565b611201600480360360608110156111e157600080fd5b506001600160a01b038135811691602081013590911690604001356133b0565b6040805192835260208301919091528051918290030190f35b6105a76004803603604081101561123057600080fd5b506001600160a01b0381358116916020013516613625565b6105a76004803603602081101561125e57600080fd5b50356001600160a01b0316613642565b61057f6004803603602081101561128457600080fd5b810190602081018135600160201b81111561129e57600080fd5b8201836020820111156112b057600080fd5b803590602001918460208302840111600160201b831117156112d157600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550613654945050505050565b6105a7600480360360a081101561132557600080fd5b506001600160a01b03813581169160208101358216916040820135811691606081013590911690608001356136e9565b6105a76004803603602081101561136b57600080fd5b50356138a1565b6105a76004803603606081101561138857600080fd5b506001600160a01b0381358116916020810135909116906040013561390a565b610769600480360360408110156113be57600080fd5b506001600160a01b038135169060200135613bf7565b610769613c2c565b6105a7600480360360408110156113f257600080fd5b506001600160a01b038135169060200135613c3b565b61048c613deb565b6105a7613dfb565b61057f6004803603602081101561142e57600080fd5b50356001600160a01b0316613e01565b6105a76004803603606081101561145457600080fd5b506001600160a01b03813581169160208101359091169060400135613e65565b6105a76004803603602081101561148a57600080fd5b50356001600160a01b0316613ea2565b6107696141b5565b6105a7600480360360208110156114b857600080fd5b50356141c4565b600181565b6001600160a01b03821660009081526009602052604081205460ff1661151b5760405162461bcd60e51b815260040180806020018281038252602881526020018061608e6028913960400191505060405180910390fd5b600a546001600160a01b031633148061153e57506000546001600160a01b031633145b6115795760405162461bcd60e51b81526004018080602001828103825260278152602001806160b66027913960400191505060405180910390fd5b6000546001600160a01b031633148061159457506001821515145b6115de576040805162461bcd60e51b81526020600482015260166024820152756f6e6c792061646d696e2063616e20756e706175736560501b604482015290519081900360640190fd5b6001600160a01b0383166000818152600c6020908152604091829020805486151560ff199091168117909155825193845283830152606090830181905260069083015265426f72726f7760d01b6080830152517f71aec636243f9709bb0007ae15e9afb8150ab01716d75fd7573be5cc096e03b09181900360a00190a150805b92915050565b60408051600180825281830190925260609160208083019080388339019050509050828160008151811061169457fe5b60200260200101906001600160a01b031690816001600160a01b0316815250506116c18183600180612761565b505050565b600f6020526000908152604090205481565b5050505050565b6002546001600160a01b0316331461173e576040805162461bcd60e51b815260206004820152601d60248201527f6f6e6c7920627261696e732063616e206265636f6d6520697473656c66000000604482015290519081900360640190fd5b60005b825181101561176e5761176683828151811061175957fe5b60200260200101516141d3565b600101611741565b5060005b81518110156117925761178a82828151811061175957fe5b600101611772565b5061179c8361290a565b6116c182613654565b6001600160a01b03841660009081526009602052604081205460ff166117cd57506009611866565b6117d5615fce565b6040518060200160405280876001600160a01b031663aa5af0fd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561181957600080fd5b505afa15801561182d573d6000803e3d6000fd5b505050506040513d602081101561184357600080fd5b50519052905061185386826142b1565b6118608685836000614539565b60009150505b949350505050565b600a546001600160a01b031681565b6001546001600160a01b031681565b600a546000906001600160a01b03163314806118b257506000546001600160a01b031633145b6118ed5760405162461bcd60e51b81526004018080602001828103825260278152602001806160b66027913960400191505060405180910390fd5b6000546001600160a01b031633148061190857506001821515145b611952576040805162461bcd60e51b81526020600482015260166024820152756f6e6c792061646d696e2063616e20756e706175736560501b604482015290519081900360640190fd5b600a8054831515600160b81b810260ff60b81b1990921691909117909155604080516020810192909252808252600582820152645365697a6560d81b6060830152517fef159d9a32b2472e32b098f954f3ce62d232939f1c207070b584df1814de2de09181900360800190a150805b919050565b600080546001600160a01b031633146119ec576119e560016004614724565b90506119c1565b6119f4615fce565b506040805160208101909152828152611a0b615fce565b50604080516020810190915266b1a2bc2ec500008152611a2b828261478a565b15611a4457611a3b600580614724565b925050506119c1565b611a4c615fce565b506040805160208101909152670c7d713b49da00008152611a6d8184614792565b15611a8757611a7d600580614724565b93505050506119c1565b6005805490869055604080518281526020810188905281517f3b9670cf975d26958e754b57098eaa2ac914d8d2a31b83257997b9f346110fd9929181900390910190a160005b9695505050505050565b6000546001600160a01b03163314611b36576040805162461bcd60e51b815260206004820152601f60248201527f6f6e6c792061646d696e2063616e2064726f7020636f6d70206d61726b657400604482015290519081900360640190fd5b6001600160a01b0381166000908152600960205260409020600381015460ff161515600114611bac576040805162461bcd60e51b815260206004820152601b60248201527f6d61726b6574206973206e6f74206120636f6d70206d61726b65740000000000604482015290519081900360640190fd5b60038101805460ff19169055604080516001600160a01b03841681526000602082015281517f93c1f3e36ed71139f466a4ce8c9751790e2e33f5afb2df0dcfb3aeabe55d5aa2929181900390910190a1611c04611de9565b5050565b6001600160a01b03821660009081526009602052604081205460ff16611c5f5760405162461bcd60e51b815260040180806020018281038252602881526020018061608e6028913960400191505060405180910390fd5b600a546001600160a01b0316331480611c8257506000546001600160a01b031633145b611cbd5760405162461bcd60e51b81526004018080602001828103825260278152602001806160b66027913960400191505060405180910390fd5b6000546001600160a01b0316331480611cd857506001821515145b611d22576040805162461bcd60e51b81526020600482015260166024820152756f6e6c792061646d696e2063616e20756e706175736560501b604482015290519081900360640190fd5b6001600160a01b0383166000818152600b6020908152604091829020805486151560ff199091168117909155825193845283830152606090830181905260049083015263135a5b9d60e21b6080830152517f71aec636243f9709bb0007ae15e9afb8150ab01716d75fd7573be5cc096e03b09181900360a00190a150919050565b600a54600160a01b900460ff1681565b50505050565b6015545b90565b505050505050565b60065481565b6001600160a01b031660009081526008602052604090205490565b6060600d805480602002602001604051908101604052809291908181526020018280548015611e4157602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611e23575b50939450600093505050505b8151811015611f07576000828281518110611e6457fe5b60200260200101519050611e76615fce565b6040518060200160405280836001600160a01b031663aa5af0fd6040518163ffffffff1660e01b815260040160206040518083038186803b158015611eba57600080fd5b505afa158015611ece573d6000803e3d6000fd5b505050506040513d6020811015611ee457600080fd5b505190529050611ef382614799565b611efd82826142b1565b5050600101611e4d565b50611f10615fce565b60405180602001604052806000815250905060608251604051908082528060200260200182016040528015611f5f57816020015b611f4c615fce565b815260200190600190039081611f445790505b50905060005b8351811015612172576000848281518110611f7c57fe5b6020908102919091018101516001600160a01b0381166000908152600990925260409091206003015490915060ff161561216957611fb8615fce565b60408051602080820180845260045463fc57d4df60e01b9091526001600160a01b03868116602485015293519293849391169163fc57d4df916044808601929190818703018186803b15801561200d57600080fd5b505afa158015612021573d6000803e3d6000fd5b505050506040513d602081101561203757600080fd5b505190529050612045615fce565b61212b6040518060200160405280856001600160a01b031663f8f9da286040518163ffffffff1660e01b815260040160206040518083038186803b15801561208c57600080fd5b505afa1580156120a0573d6000803e3d6000fd5b505050506040513d60208110156120b657600080fd5b50519052604080516308f7a6e360e31b815290516001600160a01b038716916347bd3718916004808301926020929190829003018186803b1580156120fa57600080fd5b505afa15801561210e573d6000803e3d6000fd5b505050506040513d602081101561212457600080fd5b5051614a17565b9050612135615fce565b61213f8284614a41565b90508086868151811061214e57fe5b60200260200101819052506121638782614a80565b96505050505b50600101611f65565b5060005b8351811015611db3576000600d828154811061218e57fe5b600091825260208220015485516001600160a01b0390911692506121b35760006121db565b6121db600e546121d68686815181106121c857fe5b602002602001015188614aa5565b614ad8565b6001600160a01b0383166000818152600f60209081526040918290208490558151848152915193945091927f2ab93f65628379309f36cb125e90d7c902454a545c4f8b8cb0794af75c24b807929181900390910190a25050600101612176565b6000806000806000806122508a8a8a8a614b00565b92509250925082601181111561226257fe5b95509093509150505b9450945094915050565b6001600160a01b0383166000908152600b602052604081205460ff16156122d4576040805162461bcd60e51b815260206004820152600e60248201526d1b5a5b9d081a5cc81c185d5cd95960921b604482015290519081900360640190fd5b6001600160a01b03841660009081526009602052604090205460ff166122fe5760095b9050612319565b61230784614799565b61231384846000614f1b565b60005b90505b9392505050565b600080546001600160a01b0316331461233f576119e56001600b614724565b612347615fce565b50604080516020810190915282815261235e615fce565b506040805160208101909152670de0b6b3a7640000815261237f8282614792565b1561239057611a3b6007600c614724565b612398615fce565b5060408051602081019091526714d1120d7b16000081526123b98184614792565b156123ca57611a7d6007600c614724565b6006805490869055604080518281526020810188905281517faeba5a6c40a8ac138134bff1aaa65debf25971188a58804bad717f82f0ec1316929181900390910190a16000611acd565b801580156124225750600082115b15611db3576040805162461bcd60e51b815260206004820152601160248201527072656465656d546f6b656e73207a65726f60781b604482015290519081900360640190fd5b600d818154811061247557fe5b6000918252602090912001546001600160a01b0316905081565b600080546001600160a01b031633146124ae576119e560016010614724565b600480546001600160a01b038481166001600160a01b0319831681179093556040805191909216808252602082019390935281517fd52b2b9b7e9ee655fcb95d2e5b9e0c9f69e7ef2b8e9d2d0ea78402d576d22e22929181900390910190a160009392505050565b60155481565b6116c1565b600080600080600080612538876000806000614b00565b92509250925082601181111561254a57fe5b97919650945092505050565b600080546001600160a01b03163314612575576119e560016013614724565b600a80546001600160a01b038481166001600160a01b0319831617928390556040805192821680845293909116602083015280517f0613b6ee6a04f0d09f390e4d9318894b9f6ac7fd83897cd8d18896ba579c401e9281900390910190a16000612319565b6001600160a01b03851660009081526009602052604081205460ff16158061261b57506001600160a01b03851660009081526009602052604090205460ff16155b1561262a5760095b9050612758565b60008061263685615113565b9193509091506000905082601181111561264c57fe5b146126665781601181111561265d57fe5b92505050612758565b8061267257600361265d565b6000886001600160a01b03166395dd9193876040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b1580156126ca57600080fd5b505afa1580156126de573d6000803e3d6000fd5b505050506040513d60208110156126f457600080fd5b50516040805160208101909152600554815290915060009081906127189084615133565b9092509050600082600381111561272b57fe5b1461273f57600b5b95505050505050612758565b8087111561274e576011612733565b6000955050505050505b95945050505050565b60005b83518110156116d857600084828151811061277b57fe5b6020908102919091018101516001600160a01b0381166000908152600990925260409091205490915060ff166127f0576040805162461bcd60e51b81526020600482015260156024820152741b585c9ad95d081b5d5cdd081899481b1a5cdd1959605a1b604482015290519081900360640190fd5b600184151514156128b857612803615fce565b6040518060200160405280836001600160a01b031663aa5af0fd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561284757600080fd5b505afa15801561285b573d6000803e3d6000fd5b505050506040513d602081101561287157600080fd5b50519052905061288182826142b1565b60005b87518110156128b5576128ad8389838151811061289d57fe5b6020026020010151846001614539565b600101612884565b50505b60018315151415612901576128cc81614799565b60005b86518110156128ff576128f7828883815181106128e857fe5b60200260200101516001614f1b565b6001016128cf565b505b50600101612764565b612912615187565b612963576040805162461bcd60e51b815260206004820152601f60248201527f6f6e6c792061646d696e2063616e206368616e676520636f6d70207261746500604482015290519081900360640190fd5b600e805490829055604080518281526020810184905281517fc227c9272633c3a307d9845bf2bc2509cefb20d655b5f3c1002d8e1e3f22c8b0929181900390910190a1611c04611de9565b6010602052600090815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b600c6020526000908152604090205460ff1681565b600b6020526000908152604090205460ff1681565b66038d7ea4c6800081565b6016546001600160a01b031681565b6004546001600160a01b031681565b601680546001600160a01b0319166001600160a01b0392909216919091179055565b600a54600160b01b900460ff1681565b6011602052600090815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b60096020526000908152604090208054600182015460039092015460ff91821692911683565b600a546000906001600160a01b0316331480612ad357506000546001600160a01b031633145b612b0e5760405162461bcd60e51b81526004018080602001828103825260278152602001806160b66027913960400191505060405180910390fd5b6000546001600160a01b0316331480612b2957506001821515145b612b73576040805162461bcd60e51b81526020600482015260166024820152756f6e6c792061646d696e2063616e20756e706175736560501b604482015290519081900360640190fd5b600a8054831515600160b01b810260ff60b01b1990921691909117909155604080516020810192909252808252600882820152672a3930b739b332b960c11b6060830152517fef159d9a32b2472e32b098f954f3ce62d232939f1c207070b584df1814de2de09181900360800190a15090565b6001600160a01b038082166000908152600960209081526040808320938616835260029093019052205460ff1692915050565b60075481565b836001600160a01b031663f851a4406040518163ffffffff1660e01b815260040160206040518083038186803b158015612c5857600080fd5b505afa158015612c6c573d6000803e3d6000fd5b505050506040513d6020811015612c8257600080fd5b50516001600160a01b03163314612cca5760405162461bcd60e51b81526004018080602001828103825260278152602001806161226027913960400191505060405180910390fd5b836001600160a01b031663c1e803346040518163ffffffff1660e01b8152600401602060405180830381600087803b158015612d0557600080fd5b505af1158015612d19573d6000803e3d6000fd5b505050506040513d6020811015612d2f57600080fd5b505115612d7b576040805162461bcd60e51b815260206004820152601560248201527418da185b99d9481b9bdd08185d5d1a1bdc9a5e9959605a1b604482015290519081900360640190fd5b836001600160a01b0316632327c7df8484846040518463ffffffff1660e01b8152600401808481526020018060200180602001838103835285818151815260200191508051906020019060200280838360005b83811015612de6578181015183820152602001612dce565b50505050905001838103825284818151815260200191508051906020019060200280838360005b83811015612e25578181015183820152602001612e0d565b5050505090500195505050505050600060405180830381600087803b158015612e4d57600080fd5b505af1158015612e61573d6000803e3d6000fd5b5050505050505050565b6016546001600160a01b031690565b600080546001600160a01b03163314612e99576119e560016012614724565b6001600160a01b03821660009081526009602052604090205460ff1615612ec6576119e5600a6011614724565b816001600160a01b031663fe9c44ae6040518163ffffffff1660e01b815260040160206040518083038186803b158015612eff57600080fd5b505afa158015612f13573d6000803e3d6000fd5b505050506040513d6020811015612f2957600080fd5b5050604080516060810182526001808252600060208381018281528486018381526001600160a01b03891684526009909252949091209251835490151560ff19918216178455935191830191909155516003909101805491151591909216179055612f93826141d3565b604080516001600160a01b038416815290517fcf583bb0c569eb967f806b11601c4cb93c10310485c67add5f8362c2f212321f9181900360200190a1600092915050565b6ec097ce7bc90715b34b9f100000000081565b601555565b600e5481565b60608060086000846001600160a01b03166001600160a01b0316815260200190815260200160002080548060200260200160405190810160405280929190818152602001828054801561307157602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311613053575b5093979650505050505050565b600a54600160b81b900460ff1681565b600d546060906000805b828110156130f05760096000600d83815481106130b157fe5b60009182526020808320909101546001600160a01b0316835282019290925260400190206003015460ff16156130e8576001909101905b600101613098565b5060608160405190808252806020026020018201604052801561311d578160200160208202803883390190505b5090506000805b848110156131cc5760096000600d838154811061313d57fe5b60009182526020808320909101546001600160a01b0316835282019290925260400190206003015460ff16156131c457600d818154811061317a57fe5b600091825260209091200154835160018401936001600160a01b0390921691859181106131a357fe5b60200260200101906001600160a01b031690816001600160a01b0316815250505b600101613124565b5090935050505090565b6060600d80548060200260200160405190810160405280929190818152602001828054801561322e57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311613210575b5050505050905090565b601260209081526000928352604080842090915290825290205481565b6002546001600160a01b031681565b600a54600090600160b01b900460ff16156132bb576040805162461bcd60e51b81526020600482015260126024820152711d1c985b9cd9995c881a5cc81c185d5cd95960721b604482015290519081900360640190fd5b60006132c88686856151b0565b905080156132d7579050611866565b6132e086614799565b6132ec86866000614f1b565b61186086856000614f1b565b6001600160a01b03166000908152600960205260409020805460ff19169055565b606060008251905060608160405190808252806020026020018201604052801561334d578160200160208202803883390190505b50905060005b828110156133a857600085828151811061336957fe5b6020026020010151905061337d8133615253565b601181111561338857fe5b83838151811061339457fe5b602090810291909101015250600101613353565b509392505050565b600480546040805163fc57d4df60e01b81526001600160a01b038781169482019490945290516000938493849391169163fc57d4df91602480820192602092909190829003018186803b15801561340657600080fd5b505afa15801561341a573d6000803e3d6000fd5b505050506040513d602081101561343057600080fd5b5051600480546040805163fc57d4df60e01b81526001600160a01b038a8116948201949094529051939450600093929091169163fc57d4df91602480820192602092909190829003018186803b15801561348957600080fd5b505afa15801561349d573d6000803e3d6000fd5b505050506040513d60208110156134b357600080fd5b505190508115806134c2575080155b156134d757600d93506000925061361d915050565b6000866001600160a01b031663182df0f56040518163ffffffff1660e01b815260040160206040518083038186803b15801561351257600080fd5b505afa158015613526573d6000803e3d6000fd5b505050506040513d602081101561353c57600080fd5b50519050600061354a615fce565b613552615fce565b61355a615fce565b600061356860065489615374565b94509050600081600381111561357a57fe5b1461359657600b5b99506000985061361d975050505050505050565b6135a08787615374565b9350905060008160038111156135b257fe5b146135be57600b613582565b6135c884846153af565b9250905060008160038111156135da57fe5b146135e657600b613582565b6135f0828c615133565b95509050600081600381111561360257fe5b1461360e57600b613582565b60009950939750505050505050505b935093915050565b601360209081526000928352604080842090915290825290205481565b60146020526000908152604090205481565b61365c615187565b6136ad576040805162461bcd60e51b815260206004820152601e60248201527f6f6e6c792061646d696e2063616e2061646420636f6d70206d61726b65740000604482015290519081900360640190fd5b60005b81518110156136dd576136d58282815181106136c857fe5b60200260200101516153c7565b6001016136b0565b506136e6611de9565b50565b600a54600090600160b81b900460ff161561373d576040805162461bcd60e51b815260206004820152600f60248201526e1cd95a5e99481a5cc81c185d5cd959608a1b604482015290519081900360640190fd5b6001600160a01b03861660009081526009602052604090205460ff16158061377e57506001600160a01b03851660009081526009602052604090205460ff16155b1561378a576009612623565b846001600160a01b0316635fe3b5676040518163ffffffff1660e01b815260040160206040518083038186803b1580156137c357600080fd5b505afa1580156137d7573d6000803e3d6000fd5b505050506040513d60208110156137ed57600080fd5b505160408051635fe3b56760e01b815290516001600160a01b0392831692891691635fe3b567916004808301926020929190829003018186803b15801561383357600080fd5b505afa158015613847573d6000803e3d6000fd5b505050506040513d602081101561385d57600080fd5b50516001600160a01b031614613874576002612623565b61387d86614799565b61388986846000614f1b565b61389586856000614f1b565b60009695505050505050565b600080546001600160a01b031633146138c0576119e56001600d614724565b6007805490839055604080518281526020810185905281517f7093cf1eb653f749c3ff531d6df7f92764536a7fa0d13530cd26e070780c32ea929181900390910190a16000612319565b6001600160a01b0383166000908152600c602052604081205460ff161561396b576040805162461bcd60e51b815260206004820152601060248201526f189bdc9c9bddc81a5cc81c185d5cd95960821b604482015290519081900360640190fd5b6001600160a01b03841660009081526009602052604090205460ff166139925760096122f7565b6001600160a01b038085166000908152600960209081526040808320938716835260029093019052205460ff16613a8257336001600160a01b03851614613a18576040805162461bcd60e51b815260206004820152601560248201527439b2b73232b91036bab9ba1031329031aa37b5b2b760591b604482015290519081900360640190fd5b6000613a243385615253565b90506000816011811115613a3457fe5b14613a4d57806011811115613a4557fe5b915050612319565b6001600160a01b038086166000908152600960209081526040808320938816835260029093019052205460ff16613a8057fe5b505b600480546040805163fc57d4df60e01b81526001600160a01b03888116948201949094529051929091169163fc57d4df91602480820192602092909190829003018186803b158015613ad357600080fd5b505afa158015613ae7573d6000803e3d6000fd5b505050506040513d6020811015613afd57600080fd5b5051613b0a57600d6122f7565b600080613b1a8587600087614b00565b91935090915060009050826011811115613b3057fe5b14613b4a57816011811115613b4157fe5b92505050612319565b8015613b57576004613b41565b613b5f615fce565b6040518060200160405280886001600160a01b031663aa5af0fd6040518163ffffffff1660e01b815260040160206040518083038186803b158015613ba357600080fd5b505afa158015613bb7573d6000803e3d6000fd5b505050506040513d6020811015613bcd57600080fd5b505190529050613bdd87826142b1565b613bea8787836000614539565b6000979650505050505050565b60086020528160005260406000208181548110613c1057fe5b6000918252602090912001546001600160a01b03169150829050565b6003546001600160a01b031681565b600080546001600160a01b03163314613c6157613c5a60016006614724565b905061165e565b6001600160a01b0383166000908152600960205260409020805460ff16613c9657613c8e60096007614724565b91505061165e565b613c9e615fce565b506040805160208101909152838152613cb5615fce565b506040805160208101909152670c7d713b49da00008152613cd68183614792565b15613cf157613ce760066008614724565b935050505061165e565b8415801590613d7a5750600480546040805163fc57d4df60e01b81526001600160a01b038a8116948201949094529051929091169163fc57d4df91602480820192602092909190829003018186803b158015613d4c57600080fd5b505afa158015613d60573d6000803e3d6000fd5b505050506040513d6020811015613d7657600080fd5b5051155b15613d8b57613ce7600d6009614724565b60018301805490869055604080516001600160a01b03891681526020810183905280820188905290517f70483e6592cd5182d45ac970e05bc62cdcc90e9d8ef2c2dbe686cf383bcd7fc59181900360600190a16000979650505050505050565b600a54600160a81b900460ff1681565b60055481565b6136e681600d805480602002602001604051908101604052809291908181526020018280548015613e5b57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311613e3d575b5050505050611664565b600080613e738585856151b0565b90508015613e82579050612319565b613e8b85614799565b613e9785856000614f1b565b600095945050505050565b6000808290506000806000836001600160a01b031663c37f68e2336040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060806040518083038186803b158015613f0357600080fd5b505afa158015613f17573d6000803e3d6000fd5b505050506040513d6080811015613f2d57600080fd5b508051602082015160409092015190945090925090508215613f805760405162461bcd60e51b81526004018080602001828103825260258152602001806160dd6025913960400191505060405180910390fd5b8015613f9d57613f92600c6002614724565b9450505050506119c1565b6000613faa8733856151b0565b90508015613fcb57613fbf600e6003836156e2565b955050505050506119c1565b6001600160a01b0385166000908152600960209081526040808320338452600281019092529091205460ff1661400a57600096505050505050506119c1565b3360009081526002820160209081526040808320805460ff19169055600882529182902080548351818402810184019094528084526060939283018282801561407c57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161405e575b5050835193945083925060009150505b828110156140d157896001600160a01b03168482815181106140aa57fe5b60200260200101516001600160a01b031614156140c9578091506140d1565b60010161408c565b508181106140db57fe5b3360009081526008602052604090208054819060001981019081106140fc57fe5b9060005260206000200160009054906101000a90046001600160a01b031681838154811061412657fe5b600091825260209091200180546001600160a01b0319166001600160a01b0392909216919091179055805461415f826000198301615fe1565b50604080516001600160a01b038c16815233602082015281517fe699a64c18b07ac5b7301aa273f36a2287239eb9501d81950672794afba29a0d929181900390910190a160009c9b505050505050505050505050565b6000546001600160a01b031681565b60158054820190819055919050565b60005b600d5481101561425e57816001600160a01b0316600d82815481106141f757fe5b6000918252602090912001546001600160a01b03161415614256576040805162461bcd60e51b81526020600482015260146024820152731b585c9ad95d08185b1c9958591e48185919195960621b604482015290519081900360640190fd5b6001016141d6565b50600d80546001810182556000919091527fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb50180546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0382166000908152601160209081526040808320600f90925282205490916142de611db9565b83549091506000906142fe908390600160e01b900463ffffffff16615748565b90506000811180156143105750600083115b156144df576000614385876001600160a01b03166347bd37186040518163ffffffff1660e01b815260040160206040518083038186803b15801561435357600080fd5b505afa158015614367573d6000803e3d6000fd5b505050506040513d602081101561437d57600080fd5b505187615782565b9050600061439383866157a0565b905061439d615fce565b600083116143ba57604051806020016040528060008152506143c4565b6143c482846157e2565b90506143ce615fce565b604080516020810190915288546001600160e01b031681526143f09083614a80565b9050604051806040016040528061444083600001516040518060400160405280601a81526020017f6e657720696e6465782065786365656473203232342062697473000000000000815250615817565b6001600160e01b0316815260200161447b886040518060400160405280601c81526020016000805160206161028339815191528152506158b1565b63ffffffff9081169091526001600160a01b038c166000908152601160209081526040909120835181549490920151909216600160e01b026001600160e01b039182166001600160e01b0319909416939093171691909117905550611dc092505050565b8015611dc057614512826040518060400160405280601c81526020016000805160206161028339815191528152506158b1565b845463ffffffff91909116600160e01b026001600160e01b03909116178455505050505050565b6001600160a01b0384166000908152601160205260409020614559615fce565b50604080516020810190915281546001600160e01b0316815261457a615fce565b5060408051602080820183526001600160a01b03808a16600090815260138352848120918a168082528284529481208054855286519590915291529190915580511561471b576145c8615fce565b6145d28383615906565b90506000614661896001600160a01b03166395dd91938a6040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561462f57600080fd5b505afa158015614643573d6000803e3d6000fd5b505050506040513d602081101561465957600080fd5b505188615782565b9050600061466f828461592b565b6001600160a01b038a1660009081526014602052604081205491925090614696908361594b565b90506146b78a828a6146af5766038d7ea4c680006146b2565b60005b615981565b6001600160a01b03808c1660008181526014602090815260409182902094909455895181518781529485015280519193928f16927f1fc3ecc087d8d2d15e23d0032af5a47059c3892d003d8e139fdcb6bb327c99a6929081900390910190a3505050505b50505050505050565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa083601181111561475357fe5b83601381111561475f57fe5b604080519283526020830191909152600082820152519081900360600190a182601181111561231957fe5b519051111590565b5190511090565b6001600160a01b0381166000908152601060209081526040808320600f90925282205490916147c6611db9565b83549091506000906147e6908390600160e01b900463ffffffff16615748565b90506000811180156147f85750600083115b156149be576000856001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561483857600080fd5b505afa15801561484c573d6000803e3d6000fd5b505050506040513d602081101561486257600080fd5b50519050600061487283866157a0565b905061487c615fce565b6000831161489957604051806020016040528060008152506148a3565b6148a382846157e2565b90506148ad615fce565b604080516020810190915288546001600160e01b031681526148cf9083614a80565b9050604051806040016040528061491f83600001516040518060400160405280601a81526020017f6e657720696e6465782065786365656473203232342062697473000000000000815250615817565b6001600160e01b0316815260200161495a886040518060400160405280601c81526020016000805160206161028339815191528152506158b1565b63ffffffff9081169091526001600160a01b038b166000908152601060209081526040909120835181549490920151909216600160e01b026001600160e01b039182166001600160e01b03199094169390931716919091179055506116d892505050565b80156116d8576149f1826040518060400160405280601c81526020016000805160206161028339815191528152506158b1565b845463ffffffff91909116600160e01b026001600160e01b039091161784555050505050565b614a1f615fce565b6040518060200160405280614a388560000151856157a0565b90529392505050565b614a49615fce565b6040518060200160405280670de0b6b3a7640000614a6f866000015186600001516157a0565b81614a7657fe5b0490529392505050565b614a88615fce565b6040518060200160405280614a388560000151856000015161594b565b614aad615fce565b6040518060200160405280614a38614ad18660000151670de0b6b3a76400006157a0565b8551615ac6565b6000670de0b6b3a7640000614af18484600001516157a0565b81614af857fe5b049392505050565b6000806000614b0d616005565b6001600160a01b038816600090815260086020908152604080832080548251818502810185019093528083528493606093929190830182828015614b7a57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311614b5c575b50939450600093505050505b8151811015614ed6576000828281518110614b9d57fe5b60200260200101519050806001600160a01b031663c37f68e28e6040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060806040518083038186803b158015614bfd57600080fd5b505afa158015614c11573d6000803e3d6000fd5b505050506040513d6080811015614c2757600080fd5b508051602082015160408084015160609485015160808c0152938a01939093529188019190915294508415614c6d5750600f97506000965086955061226b945050505050565b60408051602080820183526001600160a01b0380851660008181526009845285902060010154845260c08b01939093528351808301855260808b0151815260e08b015260048054855163fc57d4df60e01b815291820194909452935192169263fc57d4df9260248083019392829003018186803b158015614ced57600080fd5b505afa158015614d01573d6000803e3d6000fd5b505050506040513d6020811015614d1757600080fd5b505160a08701819052614d3b5750600d97506000965086955061226b945050505050565b604080516020810190915260a08701518152610100870181905260c087015160e0880151614d6892615af9565b61012088015293506000846003811115614d7e57fe5b14614d9a5750600b97506000965086955061226b945050505050565b614db286610120015187604001518860000151615b51565b875293506000846003811115614dc457fe5b14614de05750600b97506000965086955061226b945050505050565b614df886610100015187606001518860200151615b51565b602088015293506000846003811115614e0d57fe5b14614e295750600b97506000965086955061226b945050505050565b8b6001600160a01b0316816001600160a01b03161415614ecd57614e578661012001518c8860200151615b51565b602088015293506000846003811115614e6c57fe5b14614e885750600b97506000965086955061226b945050505050565b614e9c8661010001518b8860200151615b51565b602088015293506000846003811115614eb157fe5b14614ecd5750600b97506000965086955061226b945050505050565b50600101614b86565b50602084015184511115614efd57505050602081015190516000945003915082905061226b565b505081516020909201516000955085945091909103915061226b9050565b6001600160a01b0383166000908152601060205260409020614f3b615fce565b50604080516020810190915281546001600160e01b03168152614f5c615fce565b5060408051602080820183526001600160a01b03808916600090815260128352848120918916808252828452948120805485528651959091529152919091558051158015614faa5750815115155b15614fc2576ec097ce7bc90715b34b9f100000000081525b614fca615fce565b614fd48383615906565b90506000876001600160a01b03166370a08231886040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561502e57600080fd5b505afa158015615042573d6000803e3d6000fd5b505050506040513d602081101561505857600080fd5b505190506000615068828461592b565b6001600160a01b0389166000908152601460205260408120549192509061508f908361594b565b90506150a889828a6146af5766038d7ea4c680006146b2565b6001600160a01b03808b1660008181526014602090815260409182902094909455895181518781529485015280519193928e16927f2caecd17d02f56fa897705dcc740da2d237c373f70686f4e0d9bd3bf0400ea7a929081900390910190a350505050505050505050565b6000806000615126846000806000614b00565b9250925092509193909250565b6000806000615140615fce565b61514a8686615b9e565b9092509050600082600381111561515d57fe5b1461516e5750915060009050615180565b600061517982615c06565b9350935050505b9250929050565b600080546001600160a01b03163314806151ab57506002546001600160a01b031633145b905090565b6001600160a01b03831660009081526009602052604081205460ff166151d75760096122f7565b6001600160a01b038085166000908152600960209081526040808320938716835260029093019052205460ff1661520f5760006122f7565b60008061521f8587866000614b00565b9193509091506000905082601181111561523557fe5b1461524657816011811115613b4157fe5b8015613895576004613b41565b6001600160a01b0382166000908152600960205260408120805460ff1661527e57600991505061165e565b6001600160a01b038316600090815260028201602052604090205460ff161515600114156152b057600091505061165e565b6007546001600160a01b038416600090815260086020526040902054106152db57601091505061165e565b6001600160a01b0380841660008181526002840160209081526040808320805460ff19166001908117909155600883528184208054918201815584529282902090920180549489166001600160a01b031990951685179055815193845283019190915280517f3ab23ab0d51cccc0c3085aec51f99228625aa1a922b3a8ca89a26b0f2027a1a59281900390910190a15060009392505050565b600061537e615fce565b6153a4604051806020016040528086815250604051806020016040528086815250615c15565b915091509250929050565b60006153b9615fce565b835183516153a49190615cfe565b6001600160a01b0381166000908152600960205260409020805460ff16151560011461543a576040805162461bcd60e51b815260206004820152601960248201527f636f6d70206d61726b6574206973206e6f74206c697374656400000000000000604482015290519081900360640190fd5b600381015460ff1615615494576040805162461bcd60e51b815260206004820152601960248201527f636f6d70206d61726b657420616c726561647920616464656400000000000000604482015290519081900360640190fd5b60038101805460ff19166001908117909155604080516001600160a01b0385168152602081019290925280517f93c1f3e36ed71139f466a4ce8c9751790e2e33f5afb2df0dcfb3aeabe55d5aa29281900390910190a16001600160a01b0382166000908152601060205260409020546001600160e01b031615801561553c57506001600160a01b038216600090815260106020526040902054600160e01b900463ffffffff16155b156155f95760405180604001604052806ec097ce7bc90715b34b9f10000000006001600160e01b0316815260200161559e615575611db9565b6040518060400160405280601c81526020016000805160206161028339815191528152506158b1565b63ffffffff9081169091526001600160a01b0384166000908152601060209081526040909120835181549490920151909216600160e01b026001600160e01b039182166001600160e01b031990941693909317169190911790555b6001600160a01b0382166000908152601160205260409020546001600160e01b031615801561564b57506001600160a01b038216600090815260116020526040902054600160e01b900463ffffffff16155b15611c045760405180604001604052806ec097ce7bc90715b34b9f10000000006001600160e01b03168152602001615684615575611db9565b63ffffffff9081169091526001600160a01b0384166000908152601160209081526040909120835181549490920151909216600160e01b026001600160e01b039182166001600160e01b031990941693909317169190911790555050565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa084601181111561571157fe5b84601381111561571d57fe5b604080519283526020830191909152818101859052519081900360600190a183601181111561231657fe5b60006123198383604051806040016040528060158152602001747375627472616374696f6e20756e646572666c6f7760581b815250615dae565b600061231961579984670de0b6b3a76400006157a0565b8351615ac6565b600061231983836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f77000000000000000000815250615e08565b6157ea615fce565b6040518060200160405280614a38615811866ec097ce7bc90715b34b9f10000000006157a0565b85615ac6565b600081600160e01b84106158a95760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561586e578181015183820152602001615856565b50505050905090810190601f16801561589b5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b509192915050565b600081600160201b84106158a95760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561586e578181015183820152602001615856565b61590e615fce565b6040518060200160405280614a3885600001518560000151615748565b60006ec097ce7bc90715b34b9f1000000000614af18484600001516157a0565b60006123198383604051806040016040528060118152602001706164646974696f6e206f766572666c6f7760781b815250615e87565b60008183101580156159935750600083115b15615abe5760006159a2612e6b565b604080516370a0823160e01b815230600482015290519192506000916001600160a01b038416916370a08231916024808301926020929190829003018186803b1580156159ee57600080fd5b505afa158015615a02573d6000803e3d6000fd5b505050506040513d6020811015615a1857600080fd5b50519050808511615abb57816001600160a01b031663a9059cbb87876040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b158015615a8357600080fd5b505af1158015615a97573d6000803e3d6000fd5b505050506040513d6020811015615aad57600080fd5b506000935061231992505050565b50505b509092915050565b600061231983836040518060400160405280600e81526020016d646976696465206279207a65726f60901b815250615edc565b6000615b03615fce565b6000615b0d615fce565b615b178787615c15565b90925090506000826003811115615b2a57fe5b14615b3957909250905061361d565b615b438186615c15565b935093505050935093915050565b6000806000615b5e615fce565b615b688787615b9e565b90925090506000826003811115615b7b57fe5b14615b8c575091506000905061361d565b615b43615b9882615c06565b86615f3e565b6000615ba8615fce565b600080615bb9866000015186615f64565b90925090506000826003811115615bcc57fe5b14615beb57506040805160208101909152600081529092509050615180565b60408051602081019091529081526000969095509350505050565b51670de0b6b3a7640000900490565b6000615c1f615fce565b600080615c3486600001518660000151615f64565b90925090506000826003811115615c4757fe5b14615c6657506040805160208101909152600081529092509050615180565b600080615c7b6706f05b59d3b2000084615f3e565b90925090506000826003811115615c8e57fe5b14615cb057506040805160208101909152600081529094509250615180915050565b600080615cc583670de0b6b3a7640000615fa3565b90925090506000826003811115615cd857fe5b14615cdf57fe5b604080516020810190915290815260009a909950975050505050505050565b6000615d08615fce565b600080615d1d86670de0b6b3a7640000615f64565b90925090506000826003811115615d3057fe5b14615d4f57506040805160208101909152600081529092509050615180565b600080615d5c8388615fa3565b90925090506000826003811115615d6f57fe5b14615d9157506040805160208101909152600081529094509250615180915050565b604080516020810190915290815260009890975095505050505050565b60008184841115615e005760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561586e578181015183820152602001615856565b505050900390565b6000831580615e15575082155b15615e2257506000612319565b83830283858281615e2f57fe5b04148390615e7e5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561586e578181015183820152602001615856565b50949350505050565b60008383018285821015615e7e5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561586e578181015183820152602001615856565b60008183615f2b5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561586e578181015183820152602001615856565b50828481615f3557fe5b04949350505050565b600080838301848110615f5657600092509050615180565b506002915060009050615180565b60008083615f7757506000905080615180565b83830283858281615f8457fe5b0414615f9857506002915060009050615180565b600092509050615180565b60008082615fb75750600190506000615180565b6000838581615fc257fe5b04915091509250929050565b6040518060200160405280600081525090565b8154818355818111156116c1576000838152602090206116c191810190830161606f565b604051806101400160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001616043615fce565b8152602001616050615fce565b815260200161605d615fce565b815260200161606a615fce565b905290565b611dbd91905b808211156160895760008155600101616075565b509056fe63616e6e6f742070617573652061206d61726b65742074686174206973206e6f74206c69737465646f6e6c7920706175736520677561726469616e20616e642061646d696e2063616e207061757365657869744d61726b65743a206765744163636f756e74536e617073686f74206661696c6564626c6f636b206e756d62657220657863656564732033322062697473000000006f6e6c7920756e6974726f6c6c65722061646d696e2063616e206368616e676520627261696e73a265627a7a72315820325f3280b3d3bf3749749a8e11b9ab4026a5c0abd803e6b75ec87161bb71938864736f6c63430005100032", + "metadata": "{\"compiler\":{\"version\":\"0.5.16+commit.9c3226ce\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"action\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"pauseState\",\"type\":\"bool\"}],\"name\":\"ActionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"action\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"pauseState\",\"type\":\"bool\"}],\"name\":\"ActionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSpeed\",\"type\":\"uint256\"}],\"name\":\"CompSpeedUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compBorrowIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedBorrowerComp\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"supplier\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compSupplyIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedSupplierComp\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isComped\",\"type\":\"bool\"}],\"name\":\"MarketComped\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketEntered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketExited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"MarketListed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCloseFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCloseFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCollateralFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCollateralFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCompRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCompRate\",\"type\":\"uint256\"}],\"name\":\"NewCompRate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldLiquidationIncentiveMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"NewLiquidationIncentive\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMaxAssets\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMaxAssets\",\"type\":\"uint256\"}],\"name\":\"NewMaxAssets\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldPauseGuardian\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"NewPauseGuardian\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"oldPriceOracle\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"newPriceOracle\",\"type\":\"address\"}],\"name\":\"NewPriceOracle\",\"type\":\"event\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"_addCompMarkets\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract Unitroller\",\"name\":\"unitroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"compRate_\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"compMarketsToAdd\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"otherMarketsToAdd\",\"type\":\"address[]\"}],\"name\":\"_become\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"compRate_\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"compMarketsToAdd\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"otherMarketsToAdd\",\"type\":\"address[]\"}],\"name\":\"_becomeG3\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"_dropCompMarket\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setBorrowPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCloseFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCollateralFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"compRate_\",\"type\":\"uint256\"}],\"name\":\"_setCompRate\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"_setLiquidationIncentive\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newMaxAssets\",\"type\":\"uint256\"}],\"name\":\"_setMaxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setMintPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"_setPauseGuardian\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"newOracle\",\"type\":\"address\"}],\"name\":\"_setPriceOracle\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setSeizePaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setTransferPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"_supportMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allMarkets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"blockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"checkMembership\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"},{\"internalType\":\"contract CToken[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"holders\",\"type\":\"address[]\"},{\"internalType\":\"contract CToken[]\",\"name\":\"cTokens\",\"type\":\"address[]\"},{\"internalType\":\"bool\",\"name\":\"borrowers\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"suppliers\",\"type\":\"bool\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compAccrued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compBorrowState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compBorrowerIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compClaimThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compInitialIndex\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSupplierIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSupplyState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"enterMarkets\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenAddress\",\"type\":\"address\"}],\"name\":\"exitMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blocks\",\"type\":\"uint256\"}],\"name\":\"fastForward\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getAllMarkets\",\"outputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAssetsIn\",\"outputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getCompAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getCompMarkets\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenModify\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"getHypotheticalAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"isComptroller\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateCalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"liquidationIncentiveMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"markets\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isComped\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"membershipLength\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"mintAmount\",\"type\":\"uint256\"}],\"name\":\"mintAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualMintAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"mintTokens\",\"type\":\"uint256\"}],\"name\":\"mintVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"refreshCompSpeeds\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"repayBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowerIndex\",\"type\":\"uint256\"}],\"name\":\"repayBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"seizeGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"}],\"name\":\"setBlockNumber\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"compAddress_\",\"type\":\"address\"}],\"name\":\"setCompAddress\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"transferGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"unlist\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"methods\":{\"_addCompMarkets(address[])\":{\"params\":{\"cTokens\":\"The addresses of the markets to add\"}},\"_dropCompMarket(address)\":{\"params\":{\"cToken\":\"The address of the market to drop\"}},\"_setCloseFactor(uint256)\":{\"details\":\"Admin function to set closeFactor\",\"params\":{\"newCloseFactorMantissa\":\"New close factor, scaled by 1e18\"},\"return\":\"uint 0=success, otherwise a failure. (See ErrorReporter for details)\"},\"_setCollateralFactor(address,uint256)\":{\"details\":\"Admin function to set per-market collateralFactor\",\"params\":{\"cToken\":\"The market to set the factor on\",\"newCollateralFactorMantissa\":\"The new collateral factor, scaled by 1e18\"},\"return\":\"uint 0=success, otherwise a failure. (See ErrorReporter for details)\"},\"_setCompRate(uint256)\":{\"params\":{\"compRate_\":\"The amount of COMP wei per block to distribute\"}},\"_setLiquidationIncentive(uint256)\":{\"details\":\"Admin function to set liquidationIncentive\",\"params\":{\"newLiquidationIncentiveMantissa\":\"New liquidationIncentive scaled by 1e18\"},\"return\":\"uint 0=success, otherwise a failure. (See ErrorReporter for details)\"},\"_setMaxAssets(uint256)\":{\"details\":\"Admin function to set maxAssets\",\"params\":{\"newMaxAssets\":\"New max assets\"},\"return\":\"uint 0=success, otherwise a failure. (See ErrorReporter for details)\"},\"_setPauseGuardian(address)\":{\"params\":{\"newPauseGuardian\":\"The address of the new Pause Guardian\"},\"return\":\"uint 0=success, otherwise a failure. (See enum Error for details)\"},\"_setPriceOracle(address)\":{\"details\":\"Admin function to set a new price oracle\",\"return\":\"uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\"},\"_supportMarket(address)\":{\"details\":\"Admin function to set isListed and add support for the market\",\"params\":{\"cToken\":\"The address of the market (token) to list\"},\"return\":\"uint 0=success, otherwise a failure. (See enum Error for details)\"},\"borrowAllowed(address,address,uint256)\":{\"params\":{\"borrowAmount\":\"The amount of underlying the account would borrow\",\"borrower\":\"The account which would borrow the asset\",\"cToken\":\"The market to verify the borrow against\"},\"return\":\"0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"borrowVerify(address,address,uint256)\":{\"params\":{\"borrowAmount\":\"The amount of the underlying asset requested to borrow\",\"borrower\":\"The address borrowing the underlying\",\"cToken\":\"Asset whose underlying is being borrowed\"}},\"checkMembership(address,address)\":{\"params\":{\"account\":\"The address of the account to check\",\"cToken\":\"The cToken to check\"},\"return\":\"True if the account is in the asset, otherwise false.\"},\"claimComp(address)\":{\"params\":{\"holder\":\"The address to claim COMP for\"}},\"claimComp(address,address[])\":{\"params\":{\"cTokens\":\"The list of markets to claim COMP in\",\"holder\":\"The address to claim COMP for\"}},\"claimComp(address[],address[],bool,bool)\":{\"params\":{\"borrowers\":\"Whether or not to claim COMP earned by borrowing\",\"cTokens\":\"The list of markets to claim COMP in\",\"holders\":\"The addresses to claim COMP for\",\"suppliers\":\"Whether or not to claim COMP earned by supplying\"}},\"enterMarkets(address[])\":{\"params\":{\"cTokens\":\"The list of addresses of the cToken markets to be enabled\"},\"return\":\"Success indicator for whether each corresponding market was entered\"},\"exitMarket(address)\":{\"details\":\"Sender must not have an outstanding borrow balance in the asset, or be providing neccessary collateral for an outstanding borrow.\",\"params\":{\"cTokenAddress\":\"The address of the asset to be removed\"},\"return\":\"Whether or not the account successfully exited the market\"},\"getAccountLiquidity(address)\":{\"return\":\"(possible error code (semi-opaque), account liquidity in excess of collateral requirements, account shortfall below collateral requirements)\"},\"getAllMarkets()\":{\"details\":\"The automatic getter may be used to access an individual market.\",\"return\":\"The list of market addresses\"},\"getAssetsIn(address)\":{\"params\":{\"account\":\"The address of the account to pull assets for\"},\"return\":\"A dynamic list with the assets the account has entered\"},\"getHypotheticalAccountLiquidity(address,address,uint256,uint256)\":{\"params\":{\"account\":\"The account to determine liquidity for\",\"borrowAmount\":\"The amount of underlying to hypothetically borrow\",\"cTokenModify\":\"The market to hypothetically redeem/borrow in\",\"redeemTokens\":\"The number of tokens to hypothetically redeem\"},\"return\":\"(possible error code (semi-opaque), hypothetical account liquidity in excess of collateral requirements, hypothetical account shortfall below collateral requirements)\"},\"liquidateBorrowAllowed(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"repayAmount\":\"The amount of underlying being repaid\"}},\"liquidateBorrowVerify(address,address,address,address,uint256,uint256)\":{\"params\":{\"actualRepayAmount\":\"The amount of underlying being repaid\",\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\"}},\"liquidateCalculateSeizeTokens(address,address,uint256)\":{\"details\":\"Used in liquidation (called in cToken.liquidateBorrowFresh)\",\"params\":{\"actualRepayAmount\":\"The amount of cTokenBorrowed underlying to convert into cTokenCollateral tokens\",\"cTokenBorrowed\":\"The address of the borrowed cToken\",\"cTokenCollateral\":\"The address of the collateral cToken\"},\"return\":\"(errorCode, number of cTokenCollateral tokens to be seized in a liquidation)\"},\"mintAllowed(address,address,uint256)\":{\"params\":{\"cToken\":\"The market to verify the mint against\",\"mintAmount\":\"The amount of underlying being supplied to the market in exchange for tokens\",\"minter\":\"The account which would get the minted tokens\"},\"return\":\"0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"mintVerify(address,address,uint256,uint256)\":{\"params\":{\"actualMintAmount\":\"The amount of the underlying asset being minted\",\"cToken\":\"Asset being minted\",\"mintTokens\":\"The number of tokens being minted\",\"minter\":\"The address minting the tokens\"}},\"redeemAllowed(address,address,uint256)\":{\"params\":{\"cToken\":\"The market to verify the redeem against\",\"redeemTokens\":\"The number of cTokens to exchange for the underlying asset in the market\",\"redeemer\":\"The account which would redeem the tokens\"},\"return\":\"0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"redeemVerify(address,address,uint256,uint256)\":{\"params\":{\"cToken\":\"Asset being redeemed\",\"redeemAmount\":\"The amount of the underlying asset being redeemed\",\"redeemTokens\":\"The number of tokens being redeemed\",\"redeemer\":\"The address redeeming the tokens\"}},\"repayBorrowAllowed(address,address,address,uint256)\":{\"params\":{\"borrower\":\"The account which would borrowed the asset\",\"cToken\":\"The market to verify the repay against\",\"payer\":\"The account which would repay the asset\",\"repayAmount\":\"The amount of the underlying asset the account would repay\"},\"return\":\"0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"repayBorrowVerify(address,address,address,uint256,uint256)\":{\"params\":{\"actualRepayAmount\":\"The amount of underlying being repaid\",\"borrower\":\"The address of the borrower\",\"cToken\":\"Asset being repaid\",\"payer\":\"The address repaying the borrow\"}},\"seizeAllowed(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"seizeTokens\":\"The number of collateral tokens to seize\"}},\"seizeVerify(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"seizeTokens\":\"The number of collateral tokens to seize\"}},\"transferAllowed(address,address,address,uint256)\":{\"params\":{\"cToken\":\"The market to verify the transfer against\",\"dst\":\"The account which receives the tokens\",\"src\":\"The account which sources the tokens\",\"transferTokens\":\"The number of cTokens to transfer\"},\"return\":\"0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"transferVerify(address,address,address,uint256)\":{\"params\":{\"cToken\":\"Asset being transferred\",\"dst\":\"The account which receives the tokens\",\"src\":\"The account which sources the tokens\",\"transferTokens\":\"The number of cTokens to transfer\"}}}},\"userdoc\":{\"methods\":{\"_addCompMarkets(address[])\":{\"notice\":\"Add markets to compMarkets, allowing them to earn COMP in the flywheel\"},\"_dropCompMarket(address)\":{\"notice\":\"Remove a market from compMarkets, preventing it from earning COMP in the flywheel\"},\"_setCloseFactor(uint256)\":{\"notice\":\"Sets the closeFactor used when liquidating borrows\"},\"_setCollateralFactor(address,uint256)\":{\"notice\":\"Sets the collateralFactor for a market\"},\"_setCompRate(uint256)\":{\"notice\":\"Set the amount of COMP distributed per block\"},\"_setLiquidationIncentive(uint256)\":{\"notice\":\"Sets liquidationIncentive\"},\"_setMaxAssets(uint256)\":{\"notice\":\"Sets maxAssets which controls how many markets can be entered\"},\"_setPauseGuardian(address)\":{\"notice\":\"Admin function to change the Pause Guardian\"},\"_setPriceOracle(address)\":{\"notice\":\"Sets a new price oracle for the comptroller\"},\"_supportMarket(address)\":{\"notice\":\"Add the market to the markets mapping and set it as listed\"},\"borrowAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to borrow the underlying asset of the given market\"},\"borrowVerify(address,address,uint256)\":{\"notice\":\"Validates borrow and reverts on rejection. May emit logs.\"},\"checkMembership(address,address)\":{\"notice\":\"Returns whether the given account is entered in the given asset\"},\"claimComp(address)\":{\"notice\":\"Claim all the comp accrued by holder in all markets\"},\"claimComp(address,address[])\":{\"notice\":\"Claim all the comp accrued by holder in the specified markets\"},\"claimComp(address[],address[],bool,bool)\":{\"notice\":\"Claim all comp accrued by the holders\"},\"enterMarkets(address[])\":{\"notice\":\"Add assets to be included in account liquidity calculation\"},\"exitMarket(address)\":{\"notice\":\"Removes asset from sender's account liquidity calculation\"},\"getAccountLiquidity(address)\":{\"notice\":\"Determine the current account liquidity wrt collateral requirements\"},\"getAllMarkets()\":{\"notice\":\"Return all of the markets\"},\"getAssetsIn(address)\":{\"notice\":\"Returns the assets an account has entered\"},\"getHypotheticalAccountLiquidity(address,address,uint256,uint256)\":{\"notice\":\"Determine what the account liquidity would be if the given amounts were redeemed/borrowed\"},\"liquidateBorrowAllowed(address,address,address,address,uint256)\":{\"notice\":\"Checks if the liquidation should be allowed to occur\"},\"liquidateBorrowVerify(address,address,address,address,uint256,uint256)\":{\"notice\":\"Validates liquidateBorrow and reverts on rejection. May emit logs.\"},\"liquidateCalculateSeizeTokens(address,address,uint256)\":{\"notice\":\"Calculate number of tokens of collateral asset to seize given an underlying amount\"},\"mintAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to mint tokens in the given market\"},\"mintVerify(address,address,uint256,uint256)\":{\"notice\":\"Validates mint and reverts on rejection. May emit logs.\"},\"redeemAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to redeem tokens in the given market\"},\"redeemVerify(address,address,uint256,uint256)\":{\"notice\":\"Validates redeem and reverts on rejection. May emit logs.\"},\"refreshCompSpeeds()\":{\"notice\":\"Recalculate and update COMP speeds for all COMP markets\"},\"repayBorrowAllowed(address,address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to repay a borrow in the given market\"},\"repayBorrowVerify(address,address,address,uint256,uint256)\":{\"notice\":\"Validates repayBorrow and reverts on rejection. May emit logs.\"},\"seizeAllowed(address,address,address,address,uint256)\":{\"notice\":\"Checks if the seizing of assets should be allowed to occur\"},\"seizeVerify(address,address,address,address,uint256)\":{\"notice\":\"Validates seize and reverts on rejection. May emit logs.\"},\"transferAllowed(address,address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to transfer tokens in the given market\"},\"transferVerify(address,address,address,uint256)\":{\"notice\":\"Validates transfer and reverts on rejection. May emit logs.\"}}}},\"settings\":{\"compilationTarget\":{\"tests/Contracts/ComptrollerScenarioG3.sol\":\"ComptrollerScenarioG3\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/CToken.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./CTokenInterfaces.sol\\\";\\nimport \\\"./ErrorReporter.sol\\\";\\nimport \\\"./Exponential.sol\\\";\\nimport \\\"./EIP20Interface.sol\\\";\\nimport \\\"./InterestRateModel.sol\\\";\\n\\n/**\\n * @title Compound's CToken Contract\\n * @notice Abstract base for CTokens\\n * @author Compound\\n */\\ncontract CToken is CTokenInterface, Exponential, TokenErrorReporter {\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_) public {\\n require(msg.sender == admin, \\\"only admin may initialize the market\\\");\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = getBlockNumber();\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Transfer `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = uint(-1);\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srcTokensNew;\\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, srcTokensNew) = 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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srcTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != uint(-1)) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n // unused function\\n // comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transfer(address dst, uint256 amount) external nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferFrom(address src, address dst, uint256 amount) external nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (-1 means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool) {\\n address src = msg.sender;\\n transferAllowances[src][spender] = amount;\\n emit Approval(src, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (-1 means infinite)\\n */\\n function allowance(address owner, address spender) external view returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external returns (uint) {\\n Exp memory exchangeRate = Exp({mantissa: exchangeRateCurrent()});\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n require(mErr == MathError.NO_ERROR, \\\"balance could not be calculated\\\");\\n return balance;\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view returns (uint, uint, uint, uint) {\\n uint cTokenBalance = accountTokens[account];\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), cTokenBalance, borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @dev Function to simply retrieve block number\\n * This exists mainly for inheriting test contracts to stub this result.\\n */\\n function getBlockNumber() internal view returns (uint) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this cToken\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view returns (uint) {\\n return interestRateModel.getBorrowRate(getCashPrior(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this cToken\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view returns (uint) {\\n return interestRateModel.getSupplyRate(getCashPrior(), totalBorrows, totalReserves, reserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n require(err == MathError.NO_ERROR, \\\"borrowBalanceStored: borrowBalanceStoredInternal failed\\\");\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return (error code, the calculated balance or 0 if error code is non-zero)\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the CToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n require(err == MathError.NO_ERROR, \\\"exchangeRateStored: exchangeRateStoredInternal failed\\\");\\n return result;\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the CToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return (error code, calculated exchange rate scaled by 1e18)\\n */\\n function exchangeRateStoredInternal() internal view returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows - totalReserves) / totalSupply\\n */\\n uint totalCash = getCashPrior();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Get cash balance of this cToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage.\\n */\\n function accrueInterest() public returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = getBlockNumber();\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = getCashPrior();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n require(mathErr == MathError.NO_ERROR, \\\"could not calculate block delta\\\");\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({mantissa: borrowRateMantissa}), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(Exp({mantissa: reserveFactorMantissa}), interestAccumulated, reservesPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives cTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n struct MintLocalVars {\\n Error err;\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives cTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, 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's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the cToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of cTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.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 cTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED\\\");\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\\");\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender redeems cTokens in exchange for the underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemTokens The number of cTokens to redeem into underlying\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemInternal(uint redeemTokens) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(msg.sender, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems cTokens in exchange for a specified amount of underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemAmount The amount of underlying to receive from redeeming cTokens\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemUnderlyingInternal(uint redeemAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(msg.sender, 0, redeemAmount);\\n }\\n\\n struct RedeemLocalVars {\\n Error err;\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n /**\\n * @notice User redeems cTokens in exchange for the underlying asset\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param redeemTokensIn The number of cTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming cTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemFresh(address payable redeemer, uint redeemTokensIn, uint redeemAmountIn) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr));\\n }\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(Exp({mantissa: vars.exchangeRateMantissa}), redeemTokensIn);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(redeemAmountIn, Exp({mantissa: vars.exchangeRateMantissa}));\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REDEEM_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDEEM_FRESHNESS_CHECK);\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDEEM_TRANSFER_OUT_NOT_POSSIBLE);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We invoke doTransferOut for the redeemer and the redeemAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(redeemer, vars.redeemAmount);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n /* We call the defense hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender borrows assets from the protocol to their own address\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function borrowInternal(uint borrowAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(msg.sender, borrowAmount);\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n /**\\n * @notice Users borrow assets from the protocol to their own address\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function borrowFresh(address payable borrower, uint borrowAmount) internal returns (uint) {\\n /* Fail if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.BORROW_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.BORROW_FRESHNESS_CHECK);\\n }\\n\\n /* Fail gracefully if protocol has insufficient underlying cash */\\n if (getCashPrior() < borrowAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.BORROW_CASH_NOT_AVAILABLE);\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We invoke doTransferOut for the borrower and the borrowAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(borrower, borrowAmount);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to borrower\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer the account paying off the borrow\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount the amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED\\\");\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED\\\");\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this cToken to be liquidated\\n * @param cTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) 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 = cTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, cTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this cToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param cTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowFresh(address liquidator, address borrower, uint repayAmount, CTokenInterface cTokenCollateral) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(address(this), address(cTokenCollateral), liquidator, borrower, repayAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify cTokenCollateral market's block number equals current block number */\\n if (cTokenCollateral.accrualBlockNumber() != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = -1 */\\n if (repayAmount == uint(-1)) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & 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(cTokenCollateral), actualRepayAmount);\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(cTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(cTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = cTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(cTokenCollateral), seizeTokens);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.liquidateBorrowVerify(address(this), address(cTokenCollateral), liquidator, borrower, actualRepayAmount, seizeTokens);\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another cToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed cToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of cTokens to seize\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function seize(address liquidator, address borrower, uint seizeTokens) external nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n struct SeizeInternalLocalVars {\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n uint liquidatorSeizeTokens;\\n uint protocolSeizeTokens;\\n uint protocolSeizeAmount;\\n uint exchangeRateMantissa;\\n uint totalReservesNew;\\n uint totalSupplyNew;\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another CToken.\\n * Its absolutely critical to use msg.sender as the seizer cToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed cToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of cTokens to seize\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function seizeInternal(address seizerToken, address liquidator, address borrower, uint seizeTokens) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n SeizeInternalLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (vars.mathErr, vars.borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(vars.mathErr));\\n }\\n\\n vars.protocolSeizeTokens = mul_(seizeTokens, Exp({mantissa: protocolSeizeShareMantissa}));\\n vars.liquidatorSeizeTokens = sub_(seizeTokens, vars.protocolSeizeTokens);\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n require(vars.mathErr == MathError.NO_ERROR, \\\"exchange rate math error\\\");\\n\\n vars.protocolSeizeAmount = mul_ScalarTruncate(Exp({mantissa: vars.exchangeRateMantissa}), vars.protocolSeizeTokens);\\n\\n vars.totalReservesNew = add_(totalReserves, vars.protocolSeizeAmount);\\n vars.totalSupplyNew = sub_(totalSupply, vars.protocolSeizeTokens);\\n\\n (vars.mathErr, vars.liquidatorTokensNew) = addUInt(accountTokens[liquidator], vars.liquidatorSeizeTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(vars.mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n totalReserves = vars.totalReservesNew;\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[borrower] = vars.borrowerTokensNew;\\n accountTokens[liquidator] = vars.liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, vars.liquidatorSeizeTokens);\\n emit Transfer(borrower, address(this), vars.protocolSeizeTokens);\\n emit ReservesAdded(address(this), vars.protocolSeizeAmount, vars.totalReservesNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n\\n /*** Admin Functions ***/\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPendingAdmin(address payable newPendingAdmin) external returns (uint) {\\n // Check caller = admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\\n }\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptAdmin() external returns (uint) {\\n // Check caller is pendingAdmin and pendingAdmin \\u2260 address(0)\\n if (msg.sender != pendingAdmin || msg.sender == address(0)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = address(0);\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setComptroller(ComptrollerInterface newComptroller) public returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_COMPTROLLER_OWNER_CHECK);\\n }\\n\\n ComptrollerInterface oldComptroller = comptroller;\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(oldComptroller, newComptroller);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh\\n * @dev Admin function to accrue interest and set a new reserve factor\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setReserveFactor(uint newReserveFactorMantissa) external nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\\n * @dev Admin function to set a new reserve factor\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_RESERVE_FACTOR_ADMIN_CHECK);\\n }\\n\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring from msg.sender\\n * @param addAmount Amount of addition to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to admin\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _reduceReserves(uint reduceAmount) external nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to admin\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _reduceReservesFresh(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's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n totalReservesNew = totalReserves - reduceAmount;\\n // We checked reduceAmount <= totalReserves above, so this should never revert.\\n require(totalReservesNew <= 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't be sure if side effects occurred.\\n doTransferOut(admin, reduceAmount);\\n\\n emit ReservesReduced(admin, reduceAmount, totalReservesNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Admin function to accrue interest and update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel);\\n }\\n\\n /**\\n * @notice updates the interest rate model (*requires fresh interest accrual)\\n * @dev Admin function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal returns (uint) {\\n\\n // Used to store old model for use in the event that is emitted on success\\n InterestRateModel oldInterestRateModel;\\n\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_INTEREST_RATE_MODEL_OWNER_CHECK);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Track the market's current interest rate model\\n oldInterestRateModel = interestRateModel;\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view returns (uint);\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure tather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal;\\n\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n}\\n\",\"keccak256\":\"0x436ec2e309682995f8a82dfdd9e8f75928599c10a9a680dddbee6c275014008d\"},\"contracts/CTokenInterfaces.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./InterestRateModel.sol\\\";\\nimport \\\"./EIP20NonStandardInterface.sol\\\";\\n\\ncontract CTokenStorage {\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-cToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModel public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first CTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping (address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping (address => mapping (address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Share of seized collateral that is added to reserves\\n */\\n uint public constant protocolSeizeShareMantissa = 2.8e16; //2.8%\\n\\n}\\n\\ncontract CTokenInterface is CTokenStorage {\\n /**\\n * @notice Indicator that this is a CToken contract (for inspection)\\n */\\n bool public constant isCToken = true;\\n\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(address liquidator, address borrower, uint repayAmount, address cTokenCollateral, uint seizeTokens);\\n\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin is updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(InterestRateModel oldInterestRateModel, InterestRateModel newInterestRateModel);\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address admin, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Failure event\\n */\\n event Failure(uint error, uint info, uint detail);\\n\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external returns (bool);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function approve(address spender, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function balanceOfUnderlying(address owner) external returns (uint);\\n function getAccountSnapshot(address account) external view returns (uint, uint, uint, uint);\\n function borrowRatePerBlock() external view returns (uint);\\n function supplyRatePerBlock() external view returns (uint);\\n function totalBorrowsCurrent() external returns (uint);\\n function borrowBalanceCurrent(address account) external returns (uint);\\n function borrowBalanceStored(address account) public view returns (uint);\\n function exchangeRateCurrent() public returns (uint);\\n function exchangeRateStored() public view returns (uint);\\n function getCash() external view returns (uint);\\n function accrueInterest() public returns (uint);\\n function seize(address liquidator, address borrower, uint seizeTokens) external returns (uint);\\n\\n\\n /*** Admin Functions ***/\\n\\n function _setPendingAdmin(address payable newPendingAdmin) external returns (uint);\\n function _acceptAdmin() external returns (uint);\\n function _setComptroller(ComptrollerInterface newComptroller) public returns (uint);\\n function _setReserveFactor(uint newReserveFactorMantissa) external returns (uint);\\n function _reduceReserves(uint reduceAmount) external returns (uint);\\n function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint);\\n}\\n\\ncontract CErc20Storage {\\n /**\\n * @notice Underlying asset for this CToken\\n */\\n address public underlying;\\n}\\n\\ncontract CErc20Interface is CErc20Storage {\\n\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n function redeem(uint redeemTokens) external returns (uint);\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n function borrow(uint borrowAmount) external returns (uint);\\n function repayBorrow(uint repayAmount) external returns (uint);\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n function liquidateBorrow(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) external returns (uint);\\n function sweepToken(EIP20NonStandardInterface token) external;\\n\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ncontract CDelegationStorage {\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n}\\n\\ncontract CDelegatorInterface is CDelegationStorage {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(address implementation_, bool allowResign, bytes memory becomeImplementationData) public;\\n}\\n\\ncontract CDelegateInterface is CDelegationStorage {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) public;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() public;\\n}\\n\",\"keccak256\":\"0x963bbf60b4c0b76900b3fcb2db8c8be634934b37b4113f1055e57a308197d21a\"},\"contracts/CarefulMath.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Careful Math\\n * @author Compound\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c = a * b;\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n return (MathError.NO_ERROR, a - b);\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c = a + b;\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\",\"keccak256\":\"0x0647348f27e41d22555d99eebd217dee02a4d737df6accd7cce5347a7487c7de\"},\"contracts/ComptrollerG3.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.sol\\\";\\nimport \\\"./ErrorReporter.sol\\\";\\nimport \\\"./Exponential.sol\\\";\\nimport \\\"./PriceOracle.sol\\\";\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./ComptrollerStorage.sol\\\";\\nimport \\\"./Unitroller.sol\\\";\\nimport \\\"./Governance/Comp.sol\\\";\\n\\n/**\\n * @title Compound's Comptroller Contract\\n * @author Compound\\n */\\ncontract ComptrollerG3 is ComptrollerV3Storage, ComptrollerInterface, ComptrollerErrorReporter, Exponential {\\n /// @notice Emitted when an admin supports a market\\n event MarketListed(CToken cToken);\\n\\n /// @notice Emitted when an account enters a market\\n event MarketEntered(CToken cToken, address account);\\n\\n /// @notice Emitted when an account exits a market\\n event MarketExited(CToken cToken, 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(CToken cToken, 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 maxAssets is changed by admin\\n event NewMaxAssets(uint oldMaxAssets, uint newMaxAssets);\\n\\n /// @notice Emitted when price oracle is changed\\n event NewPriceOracle(PriceOracle oldPriceOracle, PriceOracle newPriceOracle);\\n\\n /// @notice Emitted when pause guardian is changed\\n event NewPauseGuardian(address oldPauseGuardian, address newPauseGuardian);\\n\\n /// @notice Emitted when an action is paused globally\\n event ActionPaused(string action, bool pauseState);\\n\\n /// @notice Emitted when an action is paused on a market\\n event ActionPaused(CToken cToken, string action, bool pauseState);\\n\\n /// @notice Emitted when market comped status is changed\\n event MarketComped(CToken cToken, bool isComped);\\n\\n /// @notice Emitted when COMP rate is changed\\n event NewCompRate(uint oldCompRate, uint newCompRate);\\n\\n /// @notice Emitted when a new COMP speed is calculated for a market\\n event CompSpeedUpdated(CToken indexed cToken, uint newSpeed);\\n\\n /// @notice Emitted when COMP is distributed to a supplier\\n event DistributedSupplierComp(CToken indexed cToken, address indexed supplier, uint compDelta, uint compSupplyIndex);\\n\\n /// @notice Emitted when COMP is distributed to a borrower\\n event DistributedBorrowerComp(CToken indexed cToken, address indexed borrower, uint compDelta, uint compBorrowIndex);\\n\\n /// @notice The threshold above which the flywheel transfers COMP, in wei\\n uint public constant compClaimThreshold = 0.001e18;\\n\\n /// @notice The initial COMP index for a market\\n uint224 public constant compInitialIndex = 1e36;\\n\\n // closeFactorMantissa must be strictly greater than this value\\n uint internal constant closeFactorMinMantissa = 0.05e18; // 0.05\\n\\n // closeFactorMantissa must not exceed this value\\n uint internal constant closeFactorMaxMantissa = 0.9e18; // 0.9\\n\\n // No collateralFactorMantissa may exceed this value\\n uint internal constant collateralFactorMaxMantissa = 0.9e18; // 0.9\\n\\n // liquidationIncentiveMantissa must be no less than this value\\n uint internal constant liquidationIncentiveMinMantissa = 1.0e18; // 1.0\\n\\n // liquidationIncentiveMantissa must be no greater than this value\\n uint internal constant liquidationIncentiveMaxMantissa = 1.5e18; // 1.5\\n\\n constructor() public {\\n admin = msg.sender;\\n }\\n\\n /*** Assets You Are In ***/\\n\\n /**\\n * @notice Returns the assets an account has entered\\n * @param account The address of the account to pull assets for\\n * @return A dynamic list with the assets the account has entered\\n */\\n function getAssetsIn(address account) external view returns (CToken[] memory) {\\n CToken[] memory assetsIn = accountAssets[account];\\n\\n return assetsIn;\\n }\\n\\n /**\\n * @notice Returns whether the given account is entered in the given asset\\n * @param account The address of the account to check\\n * @param cToken The cToken to check\\n * @return True if the account is in the asset, otherwise false.\\n */\\n function checkMembership(address account, CToken cToken) external view returns (bool) {\\n return markets[address(cToken)].accountMembership[account];\\n }\\n\\n /**\\n * @notice Add assets to be included in account liquidity calculation\\n * @param cTokens The list of addresses of the cToken markets to be enabled\\n * @return Success indicator for whether each corresponding market was entered\\n */\\n function enterMarkets(address[] memory cTokens) public returns (uint[] memory) {\\n uint len = cTokens.length;\\n\\n uint[] memory results = new uint[](len);\\n for (uint i = 0; i < len; i++) {\\n CToken cToken = CToken(cTokens[i]);\\n\\n results[i] = uint(addToMarketInternal(cToken, msg.sender));\\n }\\n\\n return results;\\n }\\n\\n /**\\n * @notice Add the market to the borrower's \\\"assets in\\\" for liquidity calculations\\n * @param cToken The market to enter\\n * @param borrower The address of the account to modify\\n * @return Success indicator for whether the market was entered\\n */\\n function addToMarketInternal(CToken cToken, address borrower) internal returns (Error) {\\n Market storage marketToJoin = markets[address(cToken)];\\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 if (accountAssets[borrower].length >= maxAssets) {\\n // no space, cannot join\\n return Error.TOO_MANY_ASSETS;\\n }\\n\\n // survived the gauntlet, add to list\\n // NOTE: we store these somewhat redundantly as a significant optimization\\n // this avoids having to iterate through the list for the most common use cases\\n // that is, only when we need to perform liquidity checks\\n // and not whenever we want to check if an account is in a particular market\\n marketToJoin.accountMembership[borrower] = true;\\n accountAssets[borrower].push(cToken);\\n\\n emit MarketEntered(cToken, borrower);\\n\\n return Error.NO_ERROR;\\n }\\n\\n /**\\n * @notice Removes asset from sender's account liquidity calculation\\n * @dev Sender must not have an outstanding borrow balance in the asset,\\n * or be providing neccessary collateral for an outstanding borrow.\\n * @param cTokenAddress The address of the asset to be removed\\n * @return Whether or not the account successfully exited the market\\n */\\n function exitMarket(address cTokenAddress) external returns (uint) {\\n CToken cToken = CToken(cTokenAddress);\\n /* Get sender tokensHeld and amountOwed underlying from the cToken */\\n (uint oErr, uint tokensHeld, uint amountOwed, ) = cToken.getAccountSnapshot(msg.sender);\\n require(oErr == 0, \\\"exitMarket: getAccountSnapshot failed\\\"); // semi-opaque error code\\n\\n /* Fail if the sender has a borrow balance */\\n if (amountOwed != 0) {\\n return fail(Error.NONZERO_BORROW_BALANCE, FailureInfo.EXIT_MARKET_BALANCE_OWED);\\n }\\n\\n /* Fail if the sender is not permitted to redeem all of their tokens */\\n uint allowed = redeemAllowedInternal(cTokenAddress, msg.sender, tokensHeld);\\n if (allowed != 0) {\\n return failOpaque(Error.REJECTION, FailureInfo.EXIT_MARKET_REJECTION, allowed);\\n }\\n\\n Market storage marketToExit = markets[address(cToken)];\\n\\n /* Return true if the sender is not already \\u2018in\\u2019 the market */\\n if (!marketToExit.accountMembership[msg.sender]) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Set cToken account membership to false */\\n delete marketToExit.accountMembership[msg.sender];\\n\\n /* Delete cToken from the account\\u2019s list of assets */\\n // load into memory for faster iteration\\n CToken[] memory userAssetList = accountAssets[msg.sender];\\n uint len = userAssetList.length;\\n uint assetIndex = len;\\n for (uint i = 0; i < len; i++) {\\n if (userAssetList[i] == cToken) {\\n assetIndex = i;\\n break;\\n }\\n }\\n\\n // We *must* have found the asset in the list or our redundant data structure is broken\\n assert(assetIndex < len);\\n\\n // copy last item in list to location of item to be removed, reduce length by 1\\n CToken[] storage storedList = accountAssets[msg.sender];\\n storedList[assetIndex] = storedList[storedList.length - 1];\\n storedList.length--;\\n\\n emit MarketExited(cToken, 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 cToken The market to verify the mint against\\n * @param minter The account which would get the minted tokens\\n * @param mintAmount The amount of underlying being supplied to the market in exchange for tokens\\n * @return 0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function mintAllowed(address cToken, address minter, uint mintAmount) external returns (uint) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n require(!mintGuardianPaused[cToken], \\\"mint is paused\\\");\\n\\n // Shh - currently unused\\n minter;\\n mintAmount;\\n\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n // Keep the flywheel moving\\n updateCompSupplyIndex(cToken);\\n distributeSupplierComp(cToken, minter, false);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates mint and reverts on rejection. May emit logs.\\n * @param cToken Asset being minted\\n * @param minter The address minting the tokens\\n * @param actualMintAmount The amount of the underlying asset being minted\\n * @param mintTokens The number of tokens being minted\\n */\\n function mintVerify(address cToken, address minter, uint actualMintAmount, uint mintTokens) external {\\n // Shh - currently unused\\n cToken;\\n minter;\\n actualMintAmount;\\n mintTokens;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to redeem tokens in the given market\\n * @param cToken The market to verify the redeem against\\n * @param redeemer The account which would redeem the tokens\\n * @param redeemTokens The number of cTokens to exchange for the underlying asset in the market\\n * @return 0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function redeemAllowed(address cToken, address redeemer, uint redeemTokens) external returns (uint) {\\n uint allowed = redeemAllowedInternal(cToken, redeemer, redeemTokens);\\n if (allowed != uint(Error.NO_ERROR)) {\\n return allowed;\\n }\\n\\n // Keep the flywheel moving\\n updateCompSupplyIndex(cToken);\\n distributeSupplierComp(cToken, redeemer, false);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n function redeemAllowedInternal(address cToken, address redeemer, uint redeemTokens) internal view returns (uint) {\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!markets[cToken].accountMembership[redeemer]) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n (Error err, , uint shortfall) = getHypotheticalAccountLiquidityInternal(redeemer, CToken(cToken), redeemTokens, 0);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n if (shortfall > 0) {\\n return uint(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates redeem and reverts on rejection. May emit logs.\\n * @param cToken Asset being redeemed\\n * @param redeemer The address redeeming the tokens\\n * @param redeemAmount The amount of the underlying asset being redeemed\\n * @param redeemTokens The number of tokens being redeemed\\n */\\n function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) external {\\n // Shh - currently unused\\n cToken;\\n redeemer;\\n\\n // Require tokens is zero or amount is also zero\\n if (redeemTokens == 0 && redeemAmount > 0) {\\n revert(\\\"redeemTokens zero\\\");\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to borrow the underlying asset of the given market\\n * @param cToken The market to verify the borrow against\\n * @param borrower The account which would borrow the asset\\n * @param borrowAmount The amount of underlying the account would borrow\\n * @return 0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function borrowAllowed(address cToken, address borrower, uint borrowAmount) external returns (uint) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n require(!borrowGuardianPaused[cToken], \\\"borrow is paused\\\");\\n\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n if (!markets[cToken].accountMembership[borrower]) {\\n // only cTokens may call borrowAllowed if borrower not in market\\n require(msg.sender == cToken, \\\"sender must be cToken\\\");\\n\\n // attempt to add borrower to the market\\n Error err = addToMarketInternal(CToken(msg.sender), borrower);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n\\n // it should be impossible to break the important invariant\\n assert(markets[cToken].accountMembership[borrower]);\\n }\\n\\n if (oracle.getUnderlyingPrice(CToken(cToken)) == 0) {\\n return uint(Error.PRICE_ERROR);\\n }\\n\\n (Error err, , uint shortfall) = getHypotheticalAccountLiquidityInternal(borrower, CToken(cToken), 0, borrowAmount);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n if (shortfall > 0) {\\n return uint(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n\\n // Keep the flywheel moving\\n Exp memory borrowIndex = Exp({mantissa: CToken(cToken).borrowIndex()});\\n updateCompBorrowIndex(cToken, borrowIndex);\\n distributeBorrowerComp(cToken, borrower, borrowIndex, false);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates borrow and reverts on rejection. May emit logs.\\n * @param cToken Asset whose underlying is being borrowed\\n * @param borrower The address borrowing the underlying\\n * @param borrowAmount The amount of the underlying asset requested to borrow\\n */\\n function borrowVerify(address cToken, address borrower, uint borrowAmount) external {\\n // Shh - currently unused\\n cToken;\\n borrower;\\n borrowAmount;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to repay a borrow in the given market\\n * @param cToken The market to verify the repay against\\n * @param payer The account which would repay the asset\\n * @param borrower The account which would borrowed the asset\\n * @param repayAmount The amount of the underlying asset the account would repay\\n * @return 0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function repayBorrowAllowed(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount) external returns (uint) {\\n // Shh - currently unused\\n payer;\\n borrower;\\n repayAmount;\\n\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n // Keep the flywheel moving\\n Exp memory borrowIndex = Exp({mantissa: CToken(cToken).borrowIndex()});\\n updateCompBorrowIndex(cToken, borrowIndex);\\n distributeBorrowerComp(cToken, borrower, borrowIndex, false);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates repayBorrow and reverts on rejection. May emit logs.\\n * @param cToken Asset being repaid\\n * @param payer The address repaying the borrow\\n * @param borrower The address of the borrower\\n * @param actualRepayAmount The amount of underlying being repaid\\n */\\n function repayBorrowVerify(\\n address cToken,\\n address payer,\\n address borrower,\\n uint actualRepayAmount,\\n uint borrowerIndex) external {\\n // Shh - currently unused\\n cToken;\\n payer;\\n borrower;\\n actualRepayAmount;\\n borrowerIndex;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the liquidation should be allowed to occur\\n * @param cTokenBorrowed Asset which was borrowed by the borrower\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param repayAmount The amount of underlying being repaid\\n */\\n function liquidateBorrowAllowed(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount) external returns (uint) {\\n // Shh - currently unused\\n liquidator;\\n\\n if (!markets[cTokenBorrowed].isListed || !markets[cTokenCollateral].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n /* The borrower must have shortfall in order to be liquidatable */\\n (Error err, , uint shortfall) = getAccountLiquidityInternal(borrower);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n if (shortfall == 0) {\\n return uint(Error.INSUFFICIENT_SHORTFALL);\\n }\\n\\n /* The liquidator may not repay more than what is allowed by the closeFactor */\\n uint borrowBalance = CToken(cTokenBorrowed).borrowBalanceStored(borrower);\\n (MathError mathErr, uint maxClose) = mulScalarTruncate(Exp({mantissa: closeFactorMantissa}), borrowBalance);\\n if (mathErr != MathError.NO_ERROR) {\\n return uint(Error.MATH_ERROR);\\n }\\n if (repayAmount > 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 cTokenBorrowed Asset which was borrowed by the borrower\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param actualRepayAmount The amount of underlying being repaid\\n */\\n function liquidateBorrowVerify(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint actualRepayAmount,\\n uint seizeTokens) external {\\n // Shh - currently unused\\n cTokenBorrowed;\\n cTokenCollateral;\\n liquidator;\\n borrower;\\n actualRepayAmount;\\n seizeTokens;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the seizing of assets should be allowed to occur\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param cTokenBorrowed Asset which was borrowed by the borrower\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param seizeTokens The number of collateral tokens to seize\\n */\\n function seizeAllowed(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external returns (uint) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n require(!seizeGuardianPaused, \\\"seize is paused\\\");\\n\\n // Shh - currently unused\\n seizeTokens;\\n\\n if (!markets[cTokenCollateral].isListed || !markets[cTokenBorrowed].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n if (CToken(cTokenCollateral).comptroller() != CToken(cTokenBorrowed).comptroller()) {\\n return uint(Error.COMPTROLLER_MISMATCH);\\n }\\n\\n // Keep the flywheel moving\\n updateCompSupplyIndex(cTokenCollateral);\\n distributeSupplierComp(cTokenCollateral, borrower, false);\\n distributeSupplierComp(cTokenCollateral, liquidator, false);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates seize and reverts on rejection. May emit logs.\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param cTokenBorrowed Asset which was borrowed by the borrower\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param seizeTokens The number of collateral tokens to seize\\n */\\n function seizeVerify(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external {\\n // Shh - currently unused\\n cTokenCollateral;\\n cTokenBorrowed;\\n liquidator;\\n borrower;\\n seizeTokens;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to transfer tokens in the given market\\n * @param cToken The market to verify the transfer against\\n * @param src The account which sources the tokens\\n * @param dst The account which receives the tokens\\n * @param transferTokens The number of cTokens to transfer\\n * @return 0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function transferAllowed(address cToken, address src, address dst, uint transferTokens) external returns (uint) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n require(!transferGuardianPaused, \\\"transfer is paused\\\");\\n\\n // Currently the only consideration is whether or not\\n // the src is allowed to redeem this many tokens\\n uint allowed = redeemAllowedInternal(cToken, src, transferTokens);\\n if (allowed != uint(Error.NO_ERROR)) {\\n return allowed;\\n }\\n\\n // Keep the flywheel moving\\n updateCompSupplyIndex(cToken);\\n distributeSupplierComp(cToken, src, false);\\n distributeSupplierComp(cToken, dst, false);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates transfer and reverts on rejection. May emit logs.\\n * @param cToken Asset being transferred\\n * @param src The account which sources the tokens\\n * @param dst The account which receives the tokens\\n * @param transferTokens The number of cTokens to transfer\\n */\\n function transferVerify(address cToken, address src, address dst, uint transferTokens) external {\\n // Shh - currently unused\\n cToken;\\n src;\\n dst;\\n transferTokens;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n /**\\n * @dev Local vars for avoiding stack-depth limits in calculating account liquidity.\\n * Note that `cTokenBalance` is the number of cTokens the account owns in the market,\\n * whereas `borrowBalance` is the amount of underlying that the account has borrowed.\\n */\\n struct AccountLiquidityLocalVars {\\n uint sumCollateral;\\n uint sumBorrowPlusEffects;\\n uint cTokenBalance;\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n uint oraclePriceMantissa;\\n Exp collateralFactor;\\n Exp exchangeRate;\\n Exp oraclePrice;\\n Exp tokensToDenom;\\n }\\n\\n /**\\n * @notice Determine the current account liquidity wrt collateral requirements\\n * @return (possible error code (semi-opaque),\\n account liquidity in excess of collateral requirements,\\n * account shortfall below collateral requirements)\\n */\\n function getAccountLiquidity(address account) public view returns (uint, uint, uint) {\\n (Error err, uint liquidity, uint shortfall) = getHypotheticalAccountLiquidityInternal(account, CToken(0), 0, 0);\\n\\n return (uint(err), liquidity, shortfall);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity wrt collateral requirements\\n * @return (possible error code,\\n account liquidity in excess of collateral requirements,\\n * account shortfall below collateral requirements)\\n */\\n function getAccountLiquidityInternal(address account) internal view returns (Error, uint, uint) {\\n return getHypotheticalAccountLiquidityInternal(account, CToken(0), 0, 0);\\n }\\n\\n /**\\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\\n * @param cTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @return (possible error code (semi-opaque),\\n hypothetical account liquidity in excess of collateral requirements,\\n * hypothetical account shortfall below collateral requirements)\\n */\\n function getHypotheticalAccountLiquidity(\\n address account,\\n address cTokenModify,\\n uint redeemTokens,\\n uint borrowAmount) public view returns (uint, uint, uint) {\\n (Error err, uint liquidity, uint shortfall) = getHypotheticalAccountLiquidityInternal(account, CToken(cTokenModify), 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 cTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @dev Note that we calculate the exchangeRateStored for each collateral cToken using stored data,\\n * without calculating accumulated interest.\\n * @return (possible error code,\\n hypothetical account liquidity in excess of collateral requirements,\\n * hypothetical account shortfall below collateral requirements)\\n */\\n function getHypotheticalAccountLiquidityInternal(\\n address account,\\n CToken cTokenModify,\\n uint redeemTokens,\\n uint borrowAmount) internal view returns (Error, uint, uint) {\\n\\n AccountLiquidityLocalVars memory vars; // Holds all our calculation results\\n uint oErr;\\n MathError mErr;\\n\\n // For each asset the account is in\\n CToken[] memory assets = accountAssets[account];\\n for (uint i = 0; i < assets.length; i++) {\\n CToken asset = assets[i];\\n\\n // Read the balances and exchange rate from the cToken\\n (oErr, vars.cTokenBalance, vars.borrowBalance, vars.exchangeRateMantissa) = asset.getAccountSnapshot(account);\\n if (oErr != 0) { // semi-opaque error code, we assume NO_ERROR == 0 is invariant between upgrades\\n return (Error.SNAPSHOT_ERROR, 0, 0);\\n }\\n vars.collateralFactor = Exp({mantissa: markets[address(asset)].collateralFactorMantissa});\\n vars.exchangeRate = Exp({mantissa: vars.exchangeRateMantissa});\\n\\n // Get the normalized price of the asset\\n vars.oraclePriceMantissa = oracle.getUnderlyingPrice(asset);\\n if (vars.oraclePriceMantissa == 0) {\\n return (Error.PRICE_ERROR, 0, 0);\\n }\\n vars.oraclePrice = Exp({mantissa: vars.oraclePriceMantissa});\\n\\n // Pre-compute a conversion factor from tokens -> 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 * cTokenBalance\\n (mErr, vars.sumCollateral) = mulScalarTruncateAddUInt(vars.tokensToDenom, vars.cTokenBalance, 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 cTokenModify\\n if (asset == cTokenModify) {\\n // redeem effect\\n // sumBorrowPlusEffects += tokensToDenom * redeemTokens\\n (mErr, vars.sumBorrowPlusEffects) = mulScalarTruncateAddUInt(vars.tokensToDenom, redeemTokens, vars.sumBorrowPlusEffects);\\n if (mErr != MathError.NO_ERROR) {\\n return (Error.MATH_ERROR, 0, 0);\\n }\\n\\n // borrow effect\\n // sumBorrowPlusEffects += oraclePrice * borrowAmount\\n (mErr, vars.sumBorrowPlusEffects) = mulScalarTruncateAddUInt(vars.oraclePrice, borrowAmount, vars.sumBorrowPlusEffects);\\n if (mErr != MathError.NO_ERROR) {\\n return (Error.MATH_ERROR, 0, 0);\\n }\\n }\\n }\\n\\n // These are safe, as the underflow condition is checked first\\n if (vars.sumCollateral > vars.sumBorrowPlusEffects) {\\n return (Error.NO_ERROR, vars.sumCollateral - vars.sumBorrowPlusEffects, 0);\\n } else {\\n return (Error.NO_ERROR, 0, vars.sumBorrowPlusEffects - vars.sumCollateral);\\n }\\n }\\n\\n /**\\n * @notice Calculate number of tokens of collateral asset to seize given an underlying amount\\n * @dev Used in liquidation (called in cToken.liquidateBorrowFresh)\\n * @param cTokenBorrowed The address of the borrowed cToken\\n * @param cTokenCollateral The address of the collateral cToken\\n * @param actualRepayAmount The amount of cTokenBorrowed underlying to convert into cTokenCollateral tokens\\n * @return (errorCode, number of cTokenCollateral tokens to be seized in a liquidation)\\n */\\n function liquidateCalculateSeizeTokens(address cTokenBorrowed, address cTokenCollateral, uint actualRepayAmount) external view returns (uint, uint) {\\n /* Read oracle prices for borrowed and collateral markets */\\n uint priceBorrowedMantissa = oracle.getUnderlyingPrice(CToken(cTokenBorrowed));\\n uint priceCollateralMantissa = oracle.getUnderlyingPrice(CToken(cTokenCollateral));\\n if (priceBorrowedMantissa == 0 || priceCollateralMantissa == 0) {\\n return (uint(Error.PRICE_ERROR), 0);\\n }\\n\\n /*\\n * Get the exchange rate and calculate the number of collateral tokens to seize:\\n * seizeAmount = actualRepayAmount * liquidationIncentive * priceBorrowed / priceCollateral\\n * seizeTokens = seizeAmount / exchangeRate\\n * = actualRepayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate)\\n */\\n uint exchangeRateMantissa = CToken(cTokenCollateral).exchangeRateStored(); // Note: reverts on error\\n uint seizeTokens;\\n Exp memory numerator;\\n Exp memory denominator;\\n Exp memory ratio;\\n MathError mathErr;\\n\\n (mathErr, numerator) = mulExp(liquidationIncentiveMantissa, priceBorrowedMantissa);\\n if (mathErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0);\\n }\\n\\n (mathErr, denominator) = mulExp(priceCollateralMantissa, exchangeRateMantissa);\\n if (mathErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0);\\n }\\n\\n (mathErr, ratio) = divExp(numerator, denominator);\\n if (mathErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0);\\n }\\n\\n (mathErr, seizeTokens) = mulScalarTruncate(ratio, actualRepayAmount);\\n if (mathErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0);\\n }\\n\\n return (uint(Error.NO_ERROR), seizeTokens);\\n }\\n\\n /*** Admin Functions ***/\\n\\n /**\\n * @notice Sets a new price oracle for the comptroller\\n * @dev Admin function to set a new price oracle\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPriceOracle(PriceOracle newOracle) public returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PRICE_ORACLE_OWNER_CHECK);\\n }\\n\\n // Track the old oracle for the comptroller\\n PriceOracle oldOracle = oracle;\\n\\n // Set comptroller's oracle to newOracle\\n oracle = newOracle;\\n\\n // Emit NewPriceOracle(oldOracle, newOracle)\\n emit NewPriceOracle(oldOracle, newOracle);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets the closeFactor used when liquidating borrows\\n * @dev Admin function to set closeFactor\\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\\n * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function _setCloseFactor(uint newCloseFactorMantissa) external returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_CLOSE_FACTOR_OWNER_CHECK);\\n }\\n\\n Exp memory newCloseFactorExp = Exp({mantissa: newCloseFactorMantissa});\\n Exp memory lowLimit = Exp({mantissa: closeFactorMinMantissa});\\n if (lessThanOrEqualExp(newCloseFactorExp, lowLimit)) {\\n return fail(Error.INVALID_CLOSE_FACTOR, FailureInfo.SET_CLOSE_FACTOR_VALIDATION);\\n }\\n\\n Exp memory highLimit = Exp({mantissa: closeFactorMaxMantissa});\\n if (lessThanExp(highLimit, newCloseFactorExp)) {\\n return fail(Error.INVALID_CLOSE_FACTOR, FailureInfo.SET_CLOSE_FACTOR_VALIDATION);\\n }\\n\\n uint oldCloseFactorMantissa = closeFactorMantissa;\\n closeFactorMantissa = newCloseFactorMantissa;\\n emit NewCloseFactor(oldCloseFactorMantissa, closeFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets the collateralFactor for a market\\n * @dev Admin function to set per-market collateralFactor\\n * @param cToken The market to set the factor on\\n * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18\\n * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function _setCollateralFactor(CToken cToken, 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(cToken)];\\n if (!market.isListed) {\\n return fail(Error.MARKET_NOT_LISTED, FailureInfo.SET_COLLATERAL_FACTOR_NO_EXISTS);\\n }\\n\\n Exp memory newCollateralFactorExp = Exp({mantissa: newCollateralFactorMantissa});\\n\\n // Check collateral factor <= 0.9\\n Exp memory highLimit = Exp({mantissa: collateralFactorMaxMantissa});\\n if (lessThanExp(highLimit, newCollateralFactorExp)) {\\n return fail(Error.INVALID_COLLATERAL_FACTOR, FailureInfo.SET_COLLATERAL_FACTOR_VALIDATION);\\n }\\n\\n // If collateral factor != 0, fail if price == 0\\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(cToken) == 0) {\\n return fail(Error.PRICE_ERROR, FailureInfo.SET_COLLATERAL_FACTOR_WITHOUT_PRICE);\\n }\\n\\n // Set market's collateral factor to new collateral factor, remember old value\\n uint oldCollateralFactorMantissa = market.collateralFactorMantissa;\\n market.collateralFactorMantissa = newCollateralFactorMantissa;\\n\\n // Emit event with asset, old collateral factor, and new collateral factor\\n emit NewCollateralFactor(cToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets maxAssets which controls how many markets can be entered\\n * @dev Admin function to set maxAssets\\n * @param newMaxAssets New max assets\\n * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function _setMaxAssets(uint newMaxAssets) external returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_MAX_ASSETS_OWNER_CHECK);\\n }\\n\\n uint oldMaxAssets = maxAssets;\\n maxAssets = newMaxAssets;\\n emit NewMaxAssets(oldMaxAssets, newMaxAssets);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets liquidationIncentive\\n * @dev Admin function to set liquidationIncentive\\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\\n * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function _setLiquidationIncentive(uint newLiquidationIncentiveMantissa) external returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_LIQUIDATION_INCENTIVE_OWNER_CHECK);\\n }\\n\\n // Check de-scaled min <= newLiquidationIncentive <= max\\n Exp memory newLiquidationIncentive = Exp({mantissa: newLiquidationIncentiveMantissa});\\n Exp memory minLiquidationIncentive = Exp({mantissa: liquidationIncentiveMinMantissa});\\n if (lessThanExp(newLiquidationIncentive, minLiquidationIncentive)) {\\n return fail(Error.INVALID_LIQUIDATION_INCENTIVE, FailureInfo.SET_LIQUIDATION_INCENTIVE_VALIDATION);\\n }\\n\\n Exp memory maxLiquidationIncentive = Exp({mantissa: liquidationIncentiveMaxMantissa});\\n if (lessThanExp(maxLiquidationIncentive, newLiquidationIncentive)) {\\n return fail(Error.INVALID_LIQUIDATION_INCENTIVE, FailureInfo.SET_LIQUIDATION_INCENTIVE_VALIDATION);\\n }\\n\\n // Save current value for use in log\\n uint oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa;\\n\\n // Set liquidation incentive to new incentive\\n liquidationIncentiveMantissa = newLiquidationIncentiveMantissa;\\n\\n // Emit event with old incentive, new incentive\\n emit NewLiquidationIncentive(oldLiquidationIncentiveMantissa, newLiquidationIncentiveMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Add the market to the markets mapping and set it as listed\\n * @dev Admin function to set isListed and add support for the market\\n * @param cToken The address of the market (token) to list\\n * @return uint 0=success, otherwise a failure. (See enum Error for details)\\n */\\n function _supportMarket(CToken cToken) external returns (uint) {\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SUPPORT_MARKET_OWNER_CHECK);\\n }\\n\\n if (markets[address(cToken)].isListed) {\\n return fail(Error.MARKET_ALREADY_LISTED, FailureInfo.SUPPORT_MARKET_EXISTS);\\n }\\n\\n cToken.isCToken(); // Sanity check to make sure its really a CToken\\n\\n markets[address(cToken)] = Market({isListed: true, isComped: false, collateralFactorMantissa: 0});\\n\\n _addMarketInternal(address(cToken));\\n\\n emit MarketListed(cToken);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n function _addMarketInternal(address cToken) internal {\\n for (uint i = 0; i < allMarkets.length; i ++) {\\n require(allMarkets[i] != CToken(cToken), \\\"market already added\\\");\\n }\\n allMarkets.push(CToken(cToken));\\n }\\n\\n /**\\n * @notice Admin function to change the Pause Guardian\\n * @param newPauseGuardian The address of the new Pause Guardian\\n * @return uint 0=success, otherwise a failure. (See enum Error for details)\\n */\\n function _setPauseGuardian(address newPauseGuardian) public returns (uint) {\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PAUSE_GUARDIAN_OWNER_CHECK);\\n }\\n\\n // Save current value for inclusion in log\\n address oldPauseGuardian = pauseGuardian;\\n\\n // Store pauseGuardian with value newPauseGuardian\\n pauseGuardian = newPauseGuardian;\\n\\n // Emit NewPauseGuardian(OldPauseGuardian, NewPauseGuardian)\\n emit NewPauseGuardian(oldPauseGuardian, pauseGuardian);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n function _setMintPaused(CToken cToken, bool state) public returns (bool) {\\n require(markets[address(cToken)].isListed, \\\"cannot pause a market that is not listed\\\");\\n require(msg.sender == pauseGuardian || msg.sender == admin, \\\"only pause guardian and admin can pause\\\");\\n require(msg.sender == admin || state == true, \\\"only admin can unpause\\\");\\n\\n mintGuardianPaused[address(cToken)] = state;\\n emit ActionPaused(cToken, \\\"Mint\\\", state);\\n return state;\\n }\\n\\n function _setBorrowPaused(CToken cToken, bool state) public returns (bool) {\\n require(markets[address(cToken)].isListed, \\\"cannot pause a market that is not listed\\\");\\n require(msg.sender == pauseGuardian || msg.sender == admin, \\\"only pause guardian and admin can pause\\\");\\n require(msg.sender == admin || state == true, \\\"only admin can unpause\\\");\\n\\n borrowGuardianPaused[address(cToken)] = state;\\n emit ActionPaused(cToken, \\\"Borrow\\\", state);\\n return state;\\n }\\n\\n function _setTransferPaused(bool state) public returns (bool) {\\n require(msg.sender == pauseGuardian || msg.sender == admin, \\\"only pause guardian and admin can pause\\\");\\n require(msg.sender == admin || state == true, \\\"only admin can unpause\\\");\\n\\n transferGuardianPaused = state;\\n emit ActionPaused(\\\"Transfer\\\", state);\\n return state;\\n }\\n\\n function _setSeizePaused(bool state) public returns (bool) {\\n require(msg.sender == pauseGuardian || msg.sender == admin, \\\"only pause guardian and admin can pause\\\");\\n require(msg.sender == admin || state == true, \\\"only admin can unpause\\\");\\n\\n seizeGuardianPaused = state;\\n emit ActionPaused(\\\"Seize\\\", state);\\n return state;\\n }\\n\\n function _become(Unitroller unitroller, uint compRate_, address[] memory compMarketsToAdd, address[] memory otherMarketsToAdd) public {\\n require(msg.sender == unitroller.admin(), \\\"only unitroller admin can change brains\\\");\\n require(unitroller._acceptImplementation() == 0, \\\"change not authorized\\\");\\n\\n ComptrollerG3(address(unitroller))._becomeG3(compRate_, compMarketsToAdd, otherMarketsToAdd);\\n }\\n\\n function _becomeG3(uint compRate_, address[] memory compMarketsToAdd, address[] memory otherMarketsToAdd) public {\\n require(msg.sender == comptrollerImplementation, \\\"only brains can become itself\\\");\\n\\n for (uint i = 0; i < compMarketsToAdd.length; i++) {\\n _addMarketInternal(address(compMarketsToAdd[i]));\\n }\\n\\n for (uint i = 0; i < otherMarketsToAdd.length; i++) {\\n _addMarketInternal(address(otherMarketsToAdd[i]));\\n }\\n\\n _setCompRate(compRate_);\\n _addCompMarkets(compMarketsToAdd);\\n }\\n\\n /**\\n * @notice Checks caller is admin, or this contract is becoming the new implementation\\n */\\n function adminOrInitializing() internal view returns (bool) {\\n return msg.sender == admin || msg.sender == comptrollerImplementation;\\n }\\n\\n /*** Comp Distribution ***/\\n\\n /**\\n * @notice Recalculate and update COMP speeds for all COMP markets\\n */\\n function refreshCompSpeeds() public {\\n CToken[] memory allMarkets_ = allMarkets;\\n\\n for (uint i = 0; i < allMarkets_.length; i++) {\\n CToken cToken = allMarkets_[i];\\n Exp memory borrowIndex = Exp({mantissa: cToken.borrowIndex()});\\n updateCompSupplyIndex(address(cToken));\\n updateCompBorrowIndex(address(cToken), borrowIndex);\\n }\\n\\n Exp memory totalUtility = Exp({mantissa: 0});\\n Exp[] memory utilities = new Exp[](allMarkets_.length);\\n for (uint i = 0; i < allMarkets_.length; i++) {\\n CToken cToken = allMarkets_[i];\\n if (markets[address(cToken)].isComped) {\\n Exp memory assetPrice = Exp({mantissa: oracle.getUnderlyingPrice(cToken)});\\n Exp memory interestPerBlock = mul_(Exp({mantissa: cToken.borrowRatePerBlock()}), cToken.totalBorrows());\\n Exp memory utility = mul_(interestPerBlock, assetPrice);\\n utilities[i] = utility;\\n totalUtility = add_(totalUtility, utility);\\n }\\n }\\n\\n for (uint i = 0; i < allMarkets_.length; i++) {\\n CToken cToken = allMarkets[i];\\n uint newSpeed = totalUtility.mantissa > 0 ? mul_(compRate, div_(utilities[i], totalUtility)) : 0;\\n compSpeeds[address(cToken)] = newSpeed;\\n emit CompSpeedUpdated(cToken, newSpeed);\\n }\\n }\\n\\n /**\\n * @notice Accrue COMP to the market by updating the supply index\\n * @param cToken The market whose supply index to update\\n */\\n function updateCompSupplyIndex(address cToken) internal {\\n CompMarketState storage supplyState = compSupplyState[cToken];\\n uint supplySpeed = compSpeeds[cToken];\\n uint blockNumber = getBlockNumber();\\n uint deltaBlocks = sub_(blockNumber, uint(supplyState.block));\\n if (deltaBlocks > 0 && supplySpeed > 0) {\\n uint supplyTokens = CToken(cToken).totalSupply();\\n uint compAccrued = mul_(deltaBlocks, supplySpeed);\\n Double memory ratio = supplyTokens > 0 ? fraction(compAccrued, supplyTokens) : Double({mantissa: 0});\\n Double memory index = add_(Double({mantissa: supplyState.index}), ratio);\\n compSupplyState[cToken] = CompMarketState({\\n index: safe224(index.mantissa, \\\"new index exceeds 224 bits\\\"),\\n block: safe32(blockNumber, \\\"block number exceeds 32 bits\\\")\\n });\\n } else if (deltaBlocks > 0) {\\n supplyState.block = safe32(blockNumber, \\\"block number exceeds 32 bits\\\");\\n }\\n }\\n\\n /**\\n * @notice Accrue COMP to the market by updating the borrow index\\n * @param cToken The market whose borrow index to update\\n */\\n function updateCompBorrowIndex(address cToken, Exp memory marketBorrowIndex) internal {\\n CompMarketState storage borrowState = compBorrowState[cToken];\\n uint borrowSpeed = compSpeeds[cToken];\\n uint blockNumber = getBlockNumber();\\n uint deltaBlocks = sub_(blockNumber, uint(borrowState.block));\\n if (deltaBlocks > 0 && borrowSpeed > 0) {\\n uint borrowAmount = div_(CToken(cToken).totalBorrows(), marketBorrowIndex);\\n uint compAccrued = mul_(deltaBlocks, borrowSpeed);\\n Double memory ratio = borrowAmount > 0 ? fraction(compAccrued, borrowAmount) : Double({mantissa: 0});\\n Double memory index = add_(Double({mantissa: borrowState.index}), ratio);\\n compBorrowState[cToken] = CompMarketState({\\n index: safe224(index.mantissa, \\\"new index exceeds 224 bits\\\"),\\n block: safe32(blockNumber, \\\"block number exceeds 32 bits\\\")\\n });\\n } else if (deltaBlocks > 0) {\\n borrowState.block = safe32(blockNumber, \\\"block number exceeds 32 bits\\\");\\n }\\n }\\n\\n /**\\n * @notice Calculate COMP accrued by a supplier and possibly transfer it to them\\n * @param cToken The market in which the supplier is interacting\\n * @param supplier The address of the supplier to distribute COMP to\\n */\\n function distributeSupplierComp(address cToken, address supplier, bool distributeAll) internal {\\n CompMarketState storage supplyState = compSupplyState[cToken];\\n Double memory supplyIndex = Double({mantissa: supplyState.index});\\n Double memory supplierIndex = Double({mantissa: compSupplierIndex[cToken][supplier]});\\n compSupplierIndex[cToken][supplier] = supplyIndex.mantissa;\\n\\n if (supplierIndex.mantissa == 0 && supplyIndex.mantissa > 0) {\\n supplierIndex.mantissa = compInitialIndex;\\n }\\n\\n Double memory deltaIndex = sub_(supplyIndex, supplierIndex);\\n uint supplierTokens = CToken(cToken).balanceOf(supplier);\\n uint supplierDelta = mul_(supplierTokens, deltaIndex);\\n uint supplierAccrued = add_(compAccrued[supplier], supplierDelta);\\n compAccrued[supplier] = transferComp(supplier, supplierAccrued, distributeAll ? 0 : compClaimThreshold);\\n emit DistributedSupplierComp(CToken(cToken), supplier, supplierDelta, supplyIndex.mantissa);\\n }\\n\\n /**\\n * @notice Calculate COMP accrued by a borrower and possibly transfer it to them\\n * @dev Borrowers will not begin to accrue until after the first interaction with the protocol.\\n * @param cToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute COMP to\\n */\\n function distributeBorrowerComp(address cToken, address borrower, Exp memory marketBorrowIndex, bool distributeAll) internal {\\n CompMarketState storage borrowState = compBorrowState[cToken];\\n Double memory borrowIndex = Double({mantissa: borrowState.index});\\n Double memory borrowerIndex = Double({mantissa: compBorrowerIndex[cToken][borrower]});\\n compBorrowerIndex[cToken][borrower] = borrowIndex.mantissa;\\n\\n if (borrowerIndex.mantissa > 0) {\\n Double memory deltaIndex = sub_(borrowIndex, borrowerIndex);\\n uint borrowerAmount = div_(CToken(cToken).borrowBalanceStored(borrower), marketBorrowIndex);\\n uint borrowerDelta = mul_(borrowerAmount, deltaIndex);\\n uint borrowerAccrued = add_(compAccrued[borrower], borrowerDelta);\\n compAccrued[borrower] = transferComp(borrower, borrowerAccrued, distributeAll ? 0 : compClaimThreshold);\\n emit DistributedBorrowerComp(CToken(cToken), borrower, borrowerDelta, borrowIndex.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Transfer COMP to the user, if they are above the threshold\\n * @dev Note: If there is not enough COMP, we do not perform the transfer all.\\n * @param user The address of the user to transfer COMP to\\n * @param userAccrued The amount of COMP to (possibly) transfer\\n * @return The amount of COMP which was NOT transferred to the user\\n */\\n function transferComp(address user, uint userAccrued, uint threshold) internal returns (uint) {\\n if (userAccrued >= threshold && userAccrued > 0) {\\n Comp comp = Comp(getCompAddress());\\n uint compRemaining = comp.balanceOf(address(this));\\n if (userAccrued <= compRemaining) {\\n comp.transfer(user, userAccrued);\\n return 0;\\n }\\n }\\n return userAccrued;\\n }\\n\\n /**\\n * @notice Claim all the comp accrued by holder in all markets\\n * @param holder The address to claim COMP for\\n */\\n function claimComp(address holder) public {\\n return claimComp(holder, allMarkets);\\n }\\n\\n /**\\n * @notice Claim all the comp accrued by holder in the specified markets\\n * @param holder The address to claim COMP for\\n * @param cTokens The list of markets to claim COMP in\\n */\\n function claimComp(address holder, CToken[] memory cTokens) public {\\n address[] memory holders = new address[](1);\\n holders[0] = holder;\\n claimComp(holders, cTokens, true, true);\\n }\\n\\n /**\\n * @notice Claim all comp accrued by the holders\\n * @param holders The addresses to claim COMP for\\n * @param cTokens The list of markets to claim COMP in\\n * @param borrowers Whether or not to claim COMP earned by borrowing\\n * @param suppliers Whether or not to claim COMP earned by supplying\\n */\\n function claimComp(address[] memory holders, CToken[] memory cTokens, bool borrowers, bool suppliers) public {\\n for (uint i = 0; i < cTokens.length; i++) {\\n CToken cToken = cTokens[i];\\n require(markets[address(cToken)].isListed, \\\"market must be listed\\\");\\n if (borrowers == true) {\\n Exp memory borrowIndex = Exp({mantissa: cToken.borrowIndex()});\\n updateCompBorrowIndex(address(cToken), borrowIndex);\\n for (uint j = 0; j < holders.length; j++) {\\n distributeBorrowerComp(address(cToken), holders[j], borrowIndex, true);\\n }\\n }\\n if (suppliers == true) {\\n updateCompSupplyIndex(address(cToken));\\n for (uint j = 0; j < holders.length; j++) {\\n distributeSupplierComp(address(cToken), holders[j], true);\\n }\\n }\\n }\\n }\\n\\n /*** Comp Distribution Admin ***/\\n\\n /**\\n * @notice Set the amount of COMP distributed per block\\n * @param compRate_ The amount of COMP wei per block to distribute\\n */\\n function _setCompRate(uint compRate_) public {\\n require(adminOrInitializing(), \\\"only admin can change comp rate\\\");\\n\\n uint oldRate = compRate;\\n compRate = compRate_;\\n emit NewCompRate(oldRate, compRate_);\\n\\n refreshCompSpeeds();\\n }\\n\\n /**\\n * @notice Add markets to compMarkets, allowing them to earn COMP in the flywheel\\n * @param cTokens The addresses of the markets to add\\n */\\n function _addCompMarkets(address[] memory cTokens) public {\\n require(adminOrInitializing(), \\\"only admin can add comp market\\\");\\n\\n for (uint i = 0; i < cTokens.length; i++) {\\n _addCompMarketInternal(cTokens[i]);\\n }\\n\\n refreshCompSpeeds();\\n }\\n\\n function _addCompMarketInternal(address cToken) internal {\\n Market storage market = markets[cToken];\\n require(market.isListed == true, \\\"comp market is not listed\\\");\\n require(market.isComped == false, \\\"comp market already added\\\");\\n\\n market.isComped = true;\\n emit MarketComped(CToken(cToken), true);\\n\\n if (compSupplyState[cToken].index == 0 && compSupplyState[cToken].block == 0) {\\n compSupplyState[cToken] = CompMarketState({\\n index: compInitialIndex,\\n block: safe32(getBlockNumber(), \\\"block number exceeds 32 bits\\\")\\n });\\n }\\n\\n if (compBorrowState[cToken].index == 0 && compBorrowState[cToken].block == 0) {\\n compBorrowState[cToken] = CompMarketState({\\n index: compInitialIndex,\\n block: safe32(getBlockNumber(), \\\"block number exceeds 32 bits\\\")\\n });\\n }\\n }\\n\\n /**\\n * @notice Remove a market from compMarkets, preventing it from earning COMP in the flywheel\\n * @param cToken The address of the market to drop\\n */\\n function _dropCompMarket(address cToken) public {\\n require(msg.sender == admin, \\\"only admin can drop comp market\\\");\\n\\n Market storage market = markets[cToken];\\n require(market.isComped == true, \\\"market is not a comp market\\\");\\n\\n market.isComped = false;\\n emit MarketComped(CToken(cToken), false);\\n\\n refreshCompSpeeds();\\n }\\n\\n /**\\n * @notice Return all of the markets\\n * @dev The automatic getter may be used to access an individual market.\\n * @return The list of market addresses\\n */\\n function getAllMarkets() public view returns (CToken[] memory) {\\n return allMarkets;\\n }\\n\\n function getBlockNumber() public view returns (uint) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Return the address of the COMP token\\n * @return The address of COMP\\n */\\n function getCompAddress() public view returns (address) {\\n return 0xc00e94Cb662C3520282E6f5717214004A7f26888;\\n }\\n}\\n\",\"keccak256\":\"0x82424556429ca183d7a25069151e77c81007fe7c6cd75d8360c3a2bf7c03db9d\"},\"contracts/ComptrollerInterface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\ncontract ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n bool public constant isComptroller = true;\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata cTokens) external returns (uint[] memory);\\n function exitMarket(address cToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address cToken, address minter, uint mintAmount) external returns (uint);\\n function mintVerify(address cToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address cToken, address redeemer, uint redeemTokens) external returns (uint);\\n function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address cToken, address borrower, uint borrowAmount) external returns (uint);\\n function borrowVerify(address cToken, address borrower, uint borrowAmount) external;\\n\\n function repayBorrowAllowed(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount) external returns (uint);\\n function repayBorrowVerify(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex) external;\\n\\n function liquidateBorrowAllowed(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount) external returns (uint);\\n function liquidateBorrowVerify(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens) external;\\n\\n function seizeAllowed(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external returns (uint);\\n function seizeVerify(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external;\\n\\n function transferAllowed(address cToken, address src, address dst, uint transferTokens) external returns (uint);\\n function transferVerify(address cToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n uint repayAmount) external view returns (uint, uint);\\n}\\n\",\"keccak256\":\"0xede7670d2dd7b25d0187aecd2c28b7b5ca7d7c1bdac144fbedecf5d4bdd92a6b\"},\"contracts/ComptrollerStorage.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.sol\\\";\\nimport \\\"./PriceOracle.sol\\\";\\n\\ncontract UnitrollerAdminStorage {\\n /**\\n * @notice Administrator for this contract\\n */\\n address public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address public pendingAdmin;\\n\\n /**\\n * @notice Active brains of Unitroller\\n */\\n address public comptrollerImplementation;\\n\\n /**\\n * @notice Pending brains of Unitroller\\n */\\n address public pendingComptrollerImplementation;\\n}\\n\\ncontract ComptrollerV1Storage is UnitrollerAdminStorage {\\n\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n PriceOracle public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives\\n */\\n uint public liquidationIncentiveMantissa;\\n\\n /**\\n * @notice Max number of assets a single account can participate in (borrow or use as collateral)\\n */\\n uint public maxAssets;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\\n */\\n mapping(address => CToken[]) public accountAssets;\\n\\n}\\n\\ncontract ComptrollerV2Storage is ComptrollerV1Storage {\\n struct Market {\\n /// @notice Whether or not this market is listed\\n bool isListed;\\n\\n /**\\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\\n * For instance, 0.9 to allow borrowing 90% of collateral value.\\n * Must be between 0 and 1, and stored as a mantissa.\\n */\\n uint collateralFactorMantissa;\\n\\n /// @notice Per-market mapping of \\\"accounts in this asset\\\"\\n mapping(address => bool) accountMembership;\\n\\n /// @notice Whether or not this market receives COMP\\n bool isComped;\\n }\\n\\n /**\\n * @notice Official mapping of cTokens -> Market metadata\\n * @dev Used e.g. to determine if a market is supported\\n */\\n mapping(address => Market) public markets;\\n\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n * Actions which allow users to remove their own assets cannot be paused.\\n * Liquidation / seizing / transfer can only be paused globally, not by market.\\n */\\n address public pauseGuardian;\\n bool public _mintGuardianPaused;\\n bool public _borrowGuardianPaused;\\n bool public transferGuardianPaused;\\n bool public seizeGuardianPaused;\\n mapping(address => bool) public mintGuardianPaused;\\n mapping(address => bool) public borrowGuardianPaused;\\n}\\n\\ncontract ComptrollerV3Storage is ComptrollerV2Storage {\\n struct CompMarketState {\\n /// @notice The market's last updated compBorrowIndex or compSupplyIndex\\n uint224 index;\\n\\n /// @notice The block number the index was last updated at\\n uint32 block;\\n }\\n\\n /// @notice A list of all markets\\n CToken[] public allMarkets;\\n\\n /// @notice The rate at which the flywheel distributes COMP, per block\\n uint public compRate;\\n\\n /// @notice The portion of compRate that each market currently receives\\n mapping(address => uint) public compSpeeds;\\n\\n /// @notice The COMP market supply state for each market\\n mapping(address => CompMarketState) public compSupplyState;\\n\\n /// @notice The COMP market borrow state for each market\\n mapping(address => CompMarketState) public compBorrowState;\\n\\n /// @notice The COMP borrow index for each market for each supplier as of the last time they accrued COMP\\n mapping(address => mapping(address => uint)) public compSupplierIndex;\\n\\n /// @notice The COMP borrow index for each market for each borrower as of the last time they accrued COMP\\n mapping(address => mapping(address => uint)) public compBorrowerIndex;\\n\\n /// @notice The COMP accrued but not yet transferred to each user\\n mapping(address => uint) public compAccrued;\\n}\\n\\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\\n // @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\\n address public borrowCapGuardian;\\n\\n // @notice Borrow caps enforced by borrowAllowed for each cToken address. Defaults to zero which corresponds to unlimited borrowing.\\n mapping(address => uint) public borrowCaps;\\n}\\n\\ncontract ComptrollerV5Storage is ComptrollerV4Storage {\\n /// @notice The portion of COMP that each contributor receives per block\\n mapping(address => uint) public compContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's COMP rewards have been allocated\\n mapping(address => uint) public lastContributorBlock;\\n}\\n\",\"keccak256\":\"0x5db970485549f493618b5e36bfd4d799d4f8701a136bf71ed6e0117e1ed8c254\"},\"contracts/EIP20Interface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title ERC 20 Token Standard Interface\\n * https://eips.ethereum.org/EIPS/eip-20\\n */\\ninterface EIP20Interface {\\n function name() external view returns (string memory);\\n function symbol() external view returns (string memory);\\n function decimals() external view returns (uint8);\\n\\n /**\\n * @notice Get the total number of tokens in circulation\\n * @return The supply of tokens\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @notice Gets the balance of the specified address\\n * @param owner The address from which the balance will be retrieved\\n * @return The balance\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transfer(address dst, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferFrom(address src, address dst, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (-1 means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (-1 means infinite)\\n */\\n function allowance(address owner, address spender) external view returns (uint256 remaining);\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n}\\n\",\"keccak256\":\"0xfd8ed2eac6d0b4d9ee6b32628ba68bae17544b66f190a5f7ce0c6ad024579dc8\"},\"contracts/EIP20NonStandardInterface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title EIP20NonStandardInterface\\n * @dev Version of ERC20 with no return values for `transfer` and `transferFrom`\\n * See https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\\n */\\ninterface EIP20NonStandardInterface {\\n\\n /**\\n * @notice Get the total number of tokens in circulation\\n * @return The supply of tokens\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @notice Gets the balance of the specified address\\n * @param owner The address from which the balance will be retrieved\\n * @return The balance\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n ///\\n /// !!!!!!!!!!!!!!\\n /// !!! NOTICE !!! `transfer` does not return a value, in violation of the ERC-20 specification\\n /// !!!!!!!!!!!!!!\\n ///\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n */\\n function transfer(address dst, uint256 amount) external;\\n\\n ///\\n /// !!!!!!!!!!!!!!\\n /// !!! NOTICE !!! `transferFrom` does not return a value, in violation of the ERC-20 specification\\n /// !!!!!!!!!!!!!!\\n ///\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n */\\n function transferFrom(address src, address dst, uint256 amount) external;\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent\\n */\\n function allowance(address owner, address spender) external view returns (uint256 remaining);\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n}\\n\",\"keccak256\":\"0x9719f12e4b80b51147ac195553a198cf8b0c516e7e4d04fc324a23ed15cbafb2\"},\"contracts/ErrorReporter.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\ncontract ComptrollerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\",\"keccak256\":\"0x5179afb1071c0fd555e5c1f1d2565f72dbe1740cc3dd02f6e52037f150afc5c9\"},\"contracts/Exponential.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CarefulMath.sol\\\";\\nimport \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @dev Legacy contract for compatibility reasons with existing contracts that still use MathError\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: rational}));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({mantissa: result}));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({mantissa: result}));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: scaledMantissa}));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: descaledMantissa}));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) pure internal returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({mantissa: 0}));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({mantissa: product}));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) pure internal returns (MathError, Exp memory) {\\n return mulExp(Exp({mantissa: a}), Exp({mantissa: b}));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) pure internal returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6ff054d65a0289dbb43c9f437d6909f9cf1207c9b8f984b3cb8e97a9de76a434\"},\"contracts/ExponentialNoError.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\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 Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) pure internal returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) pure internal returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) pure internal returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) pure internal returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) pure internal returns (uint224) {\\n require(n < 2**224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) pure internal returns (uint32) {\\n require(n < 2**32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: add_(a.mantissa, b.mantissa)});\\n }\\n\\n function add_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: add_(a.mantissa, b.mantissa)});\\n }\\n\\n function add_(uint a, uint b) pure internal returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: sub_(a.mantissa, b.mantissa)});\\n }\\n\\n function sub_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: sub_(a.mantissa, b.mantissa)});\\n }\\n\\n function sub_(uint a, uint b) pure internal returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: mul_(a.mantissa, b.mantissa) / expScale});\\n }\\n\\n function mul_(Exp memory a, uint b) pure internal returns (Exp memory) {\\n return Exp({mantissa: mul_(a.mantissa, b)});\\n }\\n\\n function mul_(uint a, Exp memory b) pure internal returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: mul_(a.mantissa, b.mantissa) / doubleScale});\\n }\\n\\n function mul_(Double memory a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: mul_(a.mantissa, b)});\\n }\\n\\n function mul_(uint a, Double memory b) pure internal returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) pure internal returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) pure internal 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) pure internal returns (Exp memory) {\\n return Exp({mantissa: div_(mul_(a.mantissa, expScale), b.mantissa)});\\n }\\n\\n function div_(Exp memory a, uint b) pure internal returns (Exp memory) {\\n return Exp({mantissa: div_(a.mantissa, b)});\\n }\\n\\n function div_(uint a, Exp memory b) pure internal returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa)});\\n }\\n\\n function div_(Double memory a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(a.mantissa, b)});\\n }\\n\\n function div_(uint a, Double memory b) pure internal returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) pure internal returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(mul_(a, doubleScale), b)});\\n }\\n}\\n\",\"keccak256\":\"0x7cb184b7cee71a5e707053dfba7eebbd46f11974004028100510ccce19b6694d\"},\"contracts/Governance/Comp.sol\":{\"content\":\"pragma solidity ^0.5.16;\\npragma experimental ABIEncoderV2;\\n\\ncontract Comp {\\n /// @notice EIP-20 token name for this token\\n string public constant name = \\\"Compound\\\";\\n\\n /// @notice EIP-20 token symbol for this token\\n string public constant symbol = \\\"COMP\\\";\\n\\n /// @notice EIP-20 token decimals for this token\\n uint8 public constant decimals = 18;\\n\\n /// @notice Total number of tokens in circulation\\n uint public constant totalSupply = 10000000e18; // 10 million Comp\\n\\n /// @notice Allowance amounts on behalf of others\\n mapping (address => mapping (address => uint96)) internal allowances;\\n\\n /// @notice Official record of token balances for each account\\n mapping (address => uint96) internal balances;\\n\\n /// @notice A record of each accounts delegate\\n mapping (address => address) public delegates;\\n\\n /// @notice A checkpoint for marking number of votes from a given block\\n struct Checkpoint {\\n uint32 fromBlock;\\n uint96 votes;\\n }\\n\\n /// @notice A record of votes checkpoints for each account, by index\\n mapping (address => mapping (uint32 => Checkpoint)) public checkpoints;\\n\\n /// @notice The number of checkpoints for each account\\n mapping (address => uint32) public numCheckpoints;\\n\\n /// @notice The EIP-712 typehash for the contract's domain\\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\\\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\\\");\\n\\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\\\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\\\");\\n\\n /// @notice A record of states for signing / validating signatures\\n mapping (address => uint) public nonces;\\n\\n /// @notice An event thats emitted when an account changes its delegate\\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\\n\\n /// @notice An event thats emitted when a delegate account's vote balance changes\\n event DelegateVotesChanged(address indexed delegate, uint previousBalance, uint newBalance);\\n\\n /// @notice The standard EIP-20 transfer event\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n\\n /// @notice The standard EIP-20 approval event\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n\\n /**\\n * @notice Construct a new Comp token\\n * @param account The initial account to grant all the tokens\\n */\\n constructor(address account) public {\\n balances[account] = uint96(totalSupply);\\n emit Transfer(address(0), account, totalSupply);\\n }\\n\\n /**\\n * @notice Get the number of tokens `spender` is approved to spend on behalf of `account`\\n * @param account The address of the account holding the funds\\n * @param spender The address of the account spending the funds\\n * @return The number of tokens approved\\n */\\n function allowance(address account, address spender) external view returns (uint) {\\n return allowances[account][spender];\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param rawAmount The number of tokens that are approved (2^256-1 means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint rawAmount) external returns (bool) {\\n uint96 amount;\\n if (rawAmount == uint(-1)) {\\n amount = uint96(-1);\\n } else {\\n amount = safe96(rawAmount, \\\"Comp::approve: amount exceeds 96 bits\\\");\\n }\\n\\n allowances[msg.sender][spender] = amount;\\n\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the number of tokens held by the `account`\\n * @param account The address of the account to get the balance of\\n * @return The number of tokens held\\n */\\n function balanceOf(address account) external view returns (uint) {\\n return balances[account];\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param rawAmount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transfer(address dst, uint rawAmount) external returns (bool) {\\n uint96 amount = safe96(rawAmount, \\\"Comp::transfer: amount exceeds 96 bits\\\");\\n _transferTokens(msg.sender, dst, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param rawAmount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferFrom(address src, address dst, uint rawAmount) external returns (bool) {\\n address spender = msg.sender;\\n uint96 spenderAllowance = allowances[src][spender];\\n uint96 amount = safe96(rawAmount, \\\"Comp::approve: amount exceeds 96 bits\\\");\\n\\n if (spender != src && spenderAllowance != uint96(-1)) {\\n uint96 newAllowance = sub96(spenderAllowance, amount, \\\"Comp::transferFrom: transfer amount exceeds spender allowance\\\");\\n allowances[src][spender] = newAllowance;\\n\\n emit Approval(src, spender, newAllowance);\\n }\\n\\n _transferTokens(src, dst, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Delegate votes from `msg.sender` to `delegatee`\\n * @param delegatee The address to delegate votes to\\n */\\n function delegate(address delegatee) public {\\n return _delegate(msg.sender, delegatee);\\n }\\n\\n /**\\n * @notice Delegates votes from signatory to `delegatee`\\n * @param delegatee The address to delegate votes to\\n * @param nonce The contract state required to match the signature\\n * @param expiry The time at which to expire the signature\\n * @param v The recovery byte of the signature\\n * @param r Half of the ECDSA signature pair\\n * @param s Half of the ECDSA signature pair\\n */\\n function delegateBySig(address delegatee, uint nonce, uint expiry, uint8 v, bytes32 r, bytes32 s) public {\\n bytes32 domainSeparator = keccak256(abi.encode(DOMAIN_TYPEHASH, keccak256(bytes(name)), getChainId(), address(this)));\\n bytes32 structHash = keccak256(abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry));\\n bytes32 digest = keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash));\\n address signatory = ecrecover(digest, v, r, s);\\n require(signatory != address(0), \\\"Comp::delegateBySig: invalid signature\\\");\\n require(nonce == nonces[signatory]++, \\\"Comp::delegateBySig: invalid nonce\\\");\\n require(now <= expiry, \\\"Comp::delegateBySig: signature expired\\\");\\n return _delegate(signatory, delegatee);\\n }\\n\\n /**\\n * @notice Gets the current votes balance for `account`\\n * @param account The address to get votes balance\\n * @return The number of current votes for `account`\\n */\\n function getCurrentVotes(address account) external view returns (uint96) {\\n uint32 nCheckpoints = numCheckpoints[account];\\n return nCheckpoints > 0 ? checkpoints[account][nCheckpoints - 1].votes : 0;\\n }\\n\\n /**\\n * @notice Determine the prior number of votes for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param account The address of the account to check\\n * @param blockNumber The block number to get the vote balance at\\n * @return The number of votes the account had as of the given block\\n */\\n function getPriorVotes(address account, uint blockNumber) public view returns (uint96) {\\n require(blockNumber < block.number, \\\"Comp::getPriorVotes: not yet determined\\\");\\n\\n uint32 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (checkpoints[account][nCheckpoints - 1].fromBlock <= blockNumber) {\\n return checkpoints[account][nCheckpoints - 1].votes;\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[account][0].fromBlock > blockNumber) {\\n return 0;\\n }\\n\\n uint32 lower = 0;\\n uint32 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[account][center];\\n if (cp.fromBlock == blockNumber) {\\n return cp.votes;\\n } else if (cp.fromBlock < blockNumber) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return checkpoints[account][lower].votes;\\n }\\n\\n function _delegate(address delegator, address delegatee) internal {\\n address currentDelegate = delegates[delegator];\\n uint96 delegatorBalance = balances[delegator];\\n delegates[delegator] = delegatee;\\n\\n emit DelegateChanged(delegator, currentDelegate, delegatee);\\n\\n _moveDelegates(currentDelegate, delegatee, delegatorBalance);\\n }\\n\\n function _transferTokens(address src, address dst, uint96 amount) internal {\\n require(src != address(0), \\\"Comp::_transferTokens: cannot transfer from the zero address\\\");\\n require(dst != address(0), \\\"Comp::_transferTokens: cannot transfer to the zero address\\\");\\n\\n balances[src] = sub96(balances[src], amount, \\\"Comp::_transferTokens: transfer amount exceeds balance\\\");\\n balances[dst] = add96(balances[dst], amount, \\\"Comp::_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 && amount > 0) {\\n if (srcRep != address(0)) {\\n uint32 srcRepNum = numCheckpoints[srcRep];\\n uint96 srcRepOld = srcRepNum > 0 ? checkpoints[srcRep][srcRepNum - 1].votes : 0;\\n uint96 srcRepNew = sub96(srcRepOld, amount, \\\"Comp::_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 > 0 ? checkpoints[dstRep][dstRepNum - 1].votes : 0;\\n uint96 dstRepNew = add96(dstRepOld, amount, \\\"Comp::_moveVotes: vote amount overflows\\\");\\n _writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew);\\n }\\n }\\n }\\n\\n function _writeCheckpoint(address delegatee, uint32 nCheckpoints, uint96 oldVotes, uint96 newVotes) internal {\\n uint32 blockNumber = safe32(block.number, \\\"Comp::_writeCheckpoint: block number exceeds 32 bits\\\");\\n\\n if (nCheckpoints > 0 && checkpoints[delegatee][nCheckpoints - 1].fromBlock == blockNumber) {\\n checkpoints[delegatee][nCheckpoints - 1].votes = newVotes;\\n } else {\\n checkpoints[delegatee][nCheckpoints] = Checkpoint(blockNumber, newVotes);\\n numCheckpoints[delegatee] = nCheckpoints + 1;\\n }\\n\\n emit DelegateVotesChanged(delegatee, oldVotes, newVotes);\\n }\\n\\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\\n require(n < 2**32, errorMessage);\\n return uint32(n);\\n }\\n\\n function safe96(uint n, string memory errorMessage) internal pure returns (uint96) {\\n require(n < 2**96, errorMessage);\\n return uint96(n);\\n }\\n\\n function add96(uint96 a, uint96 b, string memory errorMessage) internal pure returns (uint96) {\\n uint96 c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub96(uint96 a, uint96 b, string memory errorMessage) internal pure returns (uint96) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function getChainId() internal pure returns (uint) {\\n uint256 chainId;\\n assembly { chainId := chainid() }\\n return chainId;\\n }\\n}\\n\",\"keccak256\":\"0x539f7158013dd91efd3ad42dc6a56e0f7aebdca06063d40ce7b6e9a981b726a3\"},\"contracts/InterestRateModel.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Compound's InterestRateModel Interface\\n * @author Compound\\n */\\ncontract InterestRateModel {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint cash, uint borrows, uint reserves) external view returns (uint);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) external view returns (uint);\\n\\n}\\n\",\"keccak256\":\"0x929282d73c79e6d700ebe79f9fafc1e414b3848acff5a56d6740afd1dc908678\"},\"contracts/PriceOracle.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.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 cToken asset\\n * @param cToken The cToken to get the underlying price of\\n * @return The underlying asset price mantissa (scaled by 1e18).\\n * Zero means the price is unavailable.\\n */\\n function getUnderlyingPrice(CToken cToken) external view returns (uint);\\n}\\n\",\"keccak256\":\"0xe79ebc23bba508eb2479e7b3340abf566da1ab62131f106aee1aac3dc53816ef\"},\"contracts/Unitroller.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ErrorReporter.sol\\\";\\nimport \\\"./ComptrollerStorage.sol\\\";\\n/**\\n * @title ComptrollerCore\\n * @dev Storage for the comptroller is at this address, while execution is delegated to the `comptrollerImplementation`.\\n * CTokens should reference this contract as their comptroller.\\n */\\ncontract Unitroller is UnitrollerAdminStorage, ComptrollerErrorReporter {\\n\\n /**\\n * @notice Emitted when pendingComptrollerImplementation is changed\\n */\\n event NewPendingImplementation(address oldPendingImplementation, address newPendingImplementation);\\n\\n /**\\n * @notice Emitted when pendingComptrollerImplementation is accepted, which means comptroller implementation is updated\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Emitted when pendingAdmin is accepted, which means admin is updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n constructor() public {\\n // Set admin to caller\\n admin = msg.sender;\\n }\\n\\n /*** Admin Functions ***/\\n function _setPendingImplementation(address newPendingImplementation) public returns (uint) {\\n\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_IMPLEMENTATION_OWNER_CHECK);\\n }\\n\\n address oldPendingImplementation = pendingComptrollerImplementation;\\n\\n pendingComptrollerImplementation = newPendingImplementation;\\n\\n emit NewPendingImplementation(oldPendingImplementation, pendingComptrollerImplementation);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts new implementation of comptroller. msg.sender must be pendingImplementation\\n * @dev Admin function for new implementation to accept it's role as implementation\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptImplementation() public returns (uint) {\\n // Check caller is pendingImplementation and pendingImplementation \\u2260 address(0)\\n if (msg.sender != pendingComptrollerImplementation || pendingComptrollerImplementation == address(0)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldImplementation = comptrollerImplementation;\\n address oldPendingImplementation = pendingComptrollerImplementation;\\n\\n comptrollerImplementation = pendingComptrollerImplementation;\\n\\n pendingComptrollerImplementation = address(0);\\n\\n emit NewImplementation(oldImplementation, comptrollerImplementation);\\n emit NewPendingImplementation(oldPendingImplementation, pendingComptrollerImplementation);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPendingAdmin(address newPendingAdmin) public returns (uint) {\\n // Check caller = admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\\n }\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptAdmin() public returns (uint) {\\n // Check caller is pendingAdmin and pendingAdmin \\u2260 address(0)\\n if (msg.sender != pendingAdmin || msg.sender == address(0)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = address(0);\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return 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 () payable external {\\n // delegate all other functions to current implementation\\n (bool success, ) = comptrollerImplementation.delegatecall(msg.data);\\n\\n assembly {\\n let free_mem_ptr := mload(0x40)\\n returndatacopy(free_mem_ptr, 0, returndatasize)\\n\\n switch success\\n case 0 { revert(free_mem_ptr, returndatasize) }\\n default { return(free_mem_ptr, returndatasize) }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x51f81451eab9d5c4849507e724f2b2c53e41f54e5359fdbeae89432a727c16df\"},\"tests/Contracts/ComptrollerScenarioG3.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"../../contracts/ComptrollerG3.sol\\\";\\n\\ncontract ComptrollerScenarioG3 is ComptrollerG3 {\\n uint public blockNumber;\\n address public compAddress;\\n\\n constructor() ComptrollerG3() public {}\\n\\n function setCompAddress(address compAddress_) public {\\n compAddress = compAddress_;\\n }\\n\\n function getCompAddress() public view returns (address) {\\n return compAddress;\\n }\\n\\n function membershipLength(CToken cToken) public view returns (uint) {\\n return accountAssets[address(cToken)].length;\\n }\\n\\n function fastForward(uint blocks) public returns (uint) {\\n blockNumber += blocks;\\n\\n return blockNumber;\\n }\\n\\n function setBlockNumber(uint number) public {\\n blockNumber = number;\\n }\\n\\n function getBlockNumber() public view returns (uint) {\\n return blockNumber;\\n }\\n\\n function getCompMarkets() public view returns (address[] memory) {\\n uint m = allMarkets.length;\\n uint n = 0;\\n for (uint i = 0; i < m; i++) {\\n if (markets[address(allMarkets[i])].isComped) {\\n n++;\\n }\\n }\\n\\n address[] memory compMarkets = new address[](n);\\n uint k = 0;\\n for (uint i = 0; i < m; i++) {\\n if (markets[address(allMarkets[i])].isComped) {\\n compMarkets[k++] = address(allMarkets[i]);\\n }\\n }\\n return compMarkets;\\n }\\n\\n function unlist(CToken cToken) public {\\n markets[address(cToken)].isListed = false;\\n }\\n}\\n\",\"keccak256\":\"0x9e8906d8da0548daa5ce1411bf8ffe3cdd66552834d4c189c675f2cad23938d6\"}},\"version\":1}" + }, + "tests/Contracts/ComptrollerScenarioG4.sol:ComptrollerScenarioG4": { + "abi": "[{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"action\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"pauseState\",\"type\":\"bool\"}],\"name\":\"ActionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"action\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"pauseState\",\"type\":\"bool\"}],\"name\":\"ActionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSpeed\",\"type\":\"uint256\"}],\"name\":\"CompSpeedUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compBorrowIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedBorrowerComp\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"supplier\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compSupplyIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedSupplierComp\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isComped\",\"type\":\"bool\"}],\"name\":\"MarketComped\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketEntered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketExited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"MarketListed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCloseFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCloseFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCollateralFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCollateralFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCompRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCompRate\",\"type\":\"uint256\"}],\"name\":\"NewCompRate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldLiquidationIncentiveMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"NewLiquidationIncentive\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMaxAssets\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMaxAssets\",\"type\":\"uint256\"}],\"name\":\"NewMaxAssets\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldPauseGuardian\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"NewPauseGuardian\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"oldPriceOracle\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"newPriceOracle\",\"type\":\"address\"}],\"name\":\"NewPriceOracle\",\"type\":\"event\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"_addCompMarkets\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract Unitroller\",\"name\":\"unitroller\",\"type\":\"address\"}],\"name\":\"_become\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"_dropCompMarket\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setBorrowPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCloseFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCollateralFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"compRate_\",\"type\":\"uint256\"}],\"name\":\"_setCompRate\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"_setLiquidationIncentive\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newMaxAssets\",\"type\":\"uint256\"}],\"name\":\"_setMaxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setMintPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"_setPauseGuardian\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"newOracle\",\"type\":\"address\"}],\"name\":\"_setPriceOracle\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setSeizePaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setTransferPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"_supportMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allMarkets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"blockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"checkMembership\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"},{\"internalType\":\"contract CToken[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"holders\",\"type\":\"address[]\"},{\"internalType\":\"contract CToken[]\",\"name\":\"cTokens\",\"type\":\"address[]\"},{\"internalType\":\"bool\",\"name\":\"borrowers\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"suppliers\",\"type\":\"bool\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compAccrued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compBorrowState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compBorrowerIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compClaimThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compInitialIndex\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSupplierIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSupplyState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"enterMarkets\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenAddress\",\"type\":\"address\"}],\"name\":\"exitMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blocks\",\"type\":\"uint256\"}],\"name\":\"fastForward\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getAllMarkets\",\"outputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAssetsIn\",\"outputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getCompAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenModify\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"getHypotheticalAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"isComptroller\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateCalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"liquidationIncentiveMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"markets\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isComped\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"membershipLength\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"mintAmount\",\"type\":\"uint256\"}],\"name\":\"mintAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualMintAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"mintTokens\",\"type\":\"uint256\"}],\"name\":\"mintVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"refreshCompSpeeds\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"repayBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowerIndex\",\"type\":\"uint256\"}],\"name\":\"repayBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"seizeGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"}],\"name\":\"setBlockNumber\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"transferGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"unlist\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + "bin": "608060405234801561001057600080fd5b50600080546001600160a01b03191633179055615b8680620000336000396000f3fe608060405234801561001057600080fd5b506004361061045e5760003560e01c8063747026c91161024c578063bdcdc25811610146578063dce15449116100c3578063e9af029211610087578063e9af02921461118d578063eabe7d91146111b3578063ede4edd0146111e9578063f851a4401461120f578063fccbe7f6146112175761045e565b8063dce154491461111d578063dcfbc0c714611149578063e4028eee14611151578063e6653f3d1461117d578063e8755446146111855761045e565b8063cc7ebdc41161010a578063cc7ebdc414610fbd578063ce485c5e14610fe3578063d02f735114611084578063d9226ced146110ca578063da3d454c146110e75761045e565b8063bdcdc25814610e3d578063bde3672d14610e79578063c299823814610e9f578063c488847b14610f40578063ca0af04314610f8f5761045e565b80639d1b5a0a116101d4578063abfceffc11610198578063abfceffc14610d81578063ac0b0bb714610df7578063b0772d0b14610dff578063b21be7fd14610e07578063bb82aa5e14610e355761045e565b80639d1b5a0a14610d0a578063a76b3fda14610d12578063a7f0e23114610d38578063a8c3c85014610d5c578063aa90075414610d795761045e565b80638c57804e1161021b5780638c57804e14610c475780638e8f294b14610c6d5780638ebf636414610cb5578063929fe9a114610cd457806394b2294b14610d025761045e565b8063747026c914610c275780637d3ab61a14610c2f5780637dc0d1d014610c3757806387f7630314610c3f5761045e565b80634d8e50371161035d5780635ec88c79116102e55780636a56947e116102a95780636a56947e14610b0b5780636b79c38d14610b475780636d154ea514610b955780636d35bf9114610bbb578063731f0c2b14610c015761045e565b80635ec88c79146109305780635f5af1aa146109565780635fc7e71e1461097c5780636810dfa6146109c25780636a49111214610aee5761045e565b806351dff9891161032c57806351dff9891461087357806352d84d1e146108af57806355ee1fe1146108cc57806357e871e7146108f25780635c778605146108fa5761045e565b80634d8e5037146107be5780634e79238f146107c65780634ef4c3e1146108205780634fd42e17146108565761045e565b80632d70db78116103eb57806341c728b9116103af57806341c728b91461070057806342cbb15c1461073c57806347ef3b3b146107445780634ada90af146107905780634bca0d8c146107985761045e565b80632d70db7814610668578063317b0b77146106875780633aa729b4146106a45780633bcf7ec1146106ca5780633c94786f146106f85761045e565b80631d7b33d7116104325780631d7b33d7146105865780631ededc91146105be57806324008a621461060057806324a3d6221461063c57806326782247146106605761045e565b80627e3dd21461046357806318c882a51461047f5780631c3db2e0146104ad5780631d504dc614610560575b600080fd5b61046b611234565b604080519115158252519081900360200190f35b61046b6004803603604081101561049557600080fd5b506001600160a01b0381351690602001351515611239565b61055e600480360360408110156104c357600080fd5b6001600160a01b038235169190810190604081016020820135600160201b8111156104ed57600080fd5b8201836020820111156104ff57600080fd5b803590602001918460208302840111600160201b8311171561052057600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295506113d9945050505050565b005b61055e6004803603602081101561057657600080fd5b50356001600160a01b031661143b565b6105ac6004803603602081101561059c57600080fd5b50356001600160a01b031661159a565b60408051918252519081900360200190f35b61055e600480360360a08110156105d457600080fd5b506001600160a01b038135811691602081013582169160408201351690606081013590608001356115ac565b6105ac6004803603608081101561061657600080fd5b506001600160a01b038135811691602081013582169160408201351690606001356115b3565b61064461167c565b604080516001600160a01b039092168252519081900360200190f35b61064461168b565b61046b6004803603602081101561067e57600080fd5b5035151561169a565b6105ac6004803603602081101561069d57600080fd5b50356117d4565b61055e600480360360208110156106ba57600080fd5b50356001600160a01b03166118e5565b61046b600480360360408110156106e057600080fd5b506001600160a01b0381351690602001351515611a16565b61046b611bb1565b61055e6004803603608081101561071657600080fd5b506001600160a01b03813581169160208101359091169060408101359060600135611bc1565b6105ac611bc7565b61055e600480360360c081101561075a57600080fd5b506001600160a01b0381358116916020810135821691604082013581169160608101359091169060808101359060a00135611bcc565b6105ac611bd4565b6105ac600480360360208110156107ae57600080fd5b50356001600160a01b0316611bda565b61055e611bf5565b610802600480360360808110156107dc57600080fd5b506001600160a01b03813581169160208101359091169060408101359060600135611c3d565b60408051938452602084019290925282820152519081900360600190f35b6105ac6004803603606081101561083657600080fd5b506001600160a01b03813581169160208101359091169060400135611c77565b6105ac6004803603602081101561086c57600080fd5b5035611d22565b61055e6004803603608081101561088957600080fd5b506001600160a01b03813581169160208101359091169060408101359060600135611e16565b610644600480360360208110156108c557600080fd5b5035611e6a565b6105ac600480360360208110156108e257600080fd5b50356001600160a01b0316611e91565b6105ac611f18565b61055e6004803603606081101561091057600080fd5b506001600160a01b03813581169160208101359091169060400135611f1e565b6108026004803603602081101561094657600080fd5b50356001600160a01b0316611f23565b6105ac6004803603602081101561096c57600080fd5b50356001600160a01b0316611f58565b6105ac600480360360a081101561099257600080fd5b506001600160a01b0381358116916020810135821691604082013581169160608101359091169060800135611fdc565b61055e600480360360808110156109d857600080fd5b810190602081018135600160201b8111156109f257600080fd5b820183602082011115610a0457600080fd5b803590602001918460208302840111600160201b83111715610a2557600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b811115610a7457600080fd5b820183602082011115610a8657600080fd5b803590602001918460208302840111600160201b83111715610aa757600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550505050803515159150602001351515612163565b61055e60048036036020811015610b0457600080fd5b503561230c565b61055e60048036036080811015610b2157600080fd5b506001600160a01b03813581169160208101358216916040820135169060600135611bc1565b610b6d60048036036020811015610b5d57600080fd5b50356001600160a01b03166123b0565b604080516001600160e01b03909316835263ffffffff90911660208301528051918290030190f35b61046b60048036036020811015610bab57600080fd5b50356001600160a01b03166123da565b61055e600480360360a0811015610bd157600080fd5b506001600160a01b03813581169160208101358216916040820135811691606081013590911690608001356115ac565b61046b60048036036020811015610c1757600080fd5b50356001600160a01b03166123ef565b6105ac612404565b61064461240f565b61064461241e565b61046b61242d565b610b6d60048036036020811015610c5d57600080fd5b50356001600160a01b031661243d565b610c9360048036036020811015610c8357600080fd5b50356001600160a01b0316612467565b6040805193151584526020840192909252151582820152519081900360600190f35b61046b60048036036020811015610ccb57600080fd5b5035151561248d565b61046b60048036036040811015610cea57600080fd5b506001600160a01b03813581169160200135166125c6565b6105ac6125f9565b6106446125ff565b6105ac60048036036020811015610d2857600080fd5b50356001600160a01b0316612617565b610d40612774565b604080516001600160e01b039092168252519081900360200190f35b61055e60048036036020811015610d7257600080fd5b5035612787565b6105ac61278c565b610da760048036036020811015610d9757600080fd5b50356001600160a01b0316612792565b60408051602080825283518183015283519192839290830191858101910280838360005b83811015610de3578181015183820152602001610dcb565b505050509050019250505060405180910390f35b61046b61281b565b610da761282b565b6105ac60048036036040811015610e1d57600080fd5b506001600160a01b038135811691602001351661288d565b6106446128aa565b6105ac60048036036080811015610e5357600080fd5b506001600160a01b038135811691602081013582169160408201351690606001356128b9565b61055e60048036036020811015610e8f57600080fd5b50356001600160a01b031661294d565b610da760048036036020811015610eb557600080fd5b810190602081018135600160201b811115610ecf57600080fd5b820183602082011115610ee157600080fd5b803590602001918460208302840111600160201b83111715610f0257600080fd5b91908080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525092955061296e945050505050565b610f7660048036036060811015610f5657600080fd5b506001600160a01b03813581169160208101359091169060400135612a05565b6040805192835260208301919091528051918290030190f35b6105ac60048036036040811015610fa557600080fd5b506001600160a01b0381358116916020013516612c7a565b6105ac60048036036020811015610fd357600080fd5b50356001600160a01b0316612c97565b61055e60048036036020811015610ff957600080fd5b810190602081018135600160201b81111561101357600080fd5b82018360208201111561102557600080fd5b803590602001918460208302840111600160201b8311171561104657600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550612ca9945050505050565b6105ac600480360360a081101561109a57600080fd5b506001600160a01b0381358116916020810135821691604082013581169160608101359091169060800135612d3b565b6105ac600480360360208110156110e057600080fd5b5035612ef3565b6105ac600480360360608110156110fd57600080fd5b506001600160a01b03813581169160208101359091169060400135612f5c565b6106446004803603604081101561113357600080fd5b506001600160a01b038135169060200135613249565b61064461327e565b6105ac6004803603604081101561116757600080fd5b506001600160a01b03813516906020013561328d565b61046b61343d565b6105ac61344d565b61055e600480360360208110156111a357600080fd5b50356001600160a01b0316613453565b6105ac600480360360608110156111c957600080fd5b506001600160a01b038135811691602081013590911690604001356134b7565b6105ac600480360360208110156111ff57600080fd5b50356001600160a01b03166134f4565b610644613807565b6105ac6004803603602081101561122d57600080fd5b5035613816565b600181565b6001600160a01b03821660009081526009602052604081205460ff166112905760405162461bcd60e51b8152600401808060200182810382526028815260200180615a666028913960400191505060405180910390fd5b600a546001600160a01b03163314806112b357506000546001600160a01b031633145b6112ee5760405162461bcd60e51b8152600401808060200182810382526027815260200180615abf6027913960400191505060405180910390fd5b6000546001600160a01b031633148061130957506001821515145b611353576040805162461bcd60e51b81526020600482015260166024820152756f6e6c792061646d696e2063616e20756e706175736560501b604482015290519081900360640190fd5b6001600160a01b0383166000818152600c6020908152604091829020805486151560ff199091168117909155825193845283830152606090830181905260069083015265426f72726f7760d01b6080830152517f71aec636243f9709bb0007ae15e9afb8150ab01716d75fd7573be5cc096e03b09181900360a00190a150805b92915050565b60408051600180825281830190925260609160208083019080388339019050509050828160008151811061140957fe5b60200260200101906001600160a01b031690816001600160a01b0316815250506114368183600180612163565b505050565b806001600160a01b031663f851a4406040518163ffffffff1660e01b815260040160206040518083038186803b15801561147457600080fd5b505afa158015611488573d6000803e3d6000fd5b505050506040513d602081101561149e57600080fd5b50516001600160a01b031633146114e65760405162461bcd60e51b8152600401808060200182810382526027815260200180615b2b6027913960400191505060405180910390fd5b806001600160a01b031663c1e803346040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561152157600080fd5b505af1158015611535573d6000803e3d6000fd5b505050506040513d602081101561154b57600080fd5b505115611597576040805162461bcd60e51b815260206004820152601560248201527418da185b99d9481b9bdd08185d5d1a1bdc9a5e9959605a1b604482015290519081900360640190fd5b50565b600f6020526000908152604090205481565b5050505050565b6001600160a01b03841660009081526009602052604081205460ff166115db57506009611674565b6115e36159a6565b6040518060200160405280876001600160a01b031663aa5af0fd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561162757600080fd5b505afa15801561163b573d6000803e3d6000fd5b505050506040513d602081101561165157600080fd5b5051905290506116618682613825565b61166e8685836000613aad565b60009150505b949350505050565b600a546001600160a01b031681565b6001546001600160a01b031681565b600a546000906001600160a01b03163314806116c057506000546001600160a01b031633145b6116fb5760405162461bcd60e51b8152600401808060200182810382526027815260200180615abf6027913960400191505060405180910390fd5b6000546001600160a01b031633148061171657506001821515145b611760576040805162461bcd60e51b81526020600482015260166024820152756f6e6c792061646d696e2063616e20756e706175736560501b604482015290519081900360640190fd5b600a8054831515600160b81b810260ff60b81b1990921691909117909155604080516020810192909252808252600582820152645365697a6560d81b6060830152517fef159d9a32b2472e32b098f954f3ce62d232939f1c207070b584df1814de2de09181900360800190a150805b919050565b600080546001600160a01b031633146117fa576117f360016004613c98565b90506117cf565b6118026159a6565b5060408051602081019091528281526118196159a6565b50604080516020810190915266b1a2bc2ec5000081526118398282613cfe565b1561185257611849600580613c98565b925050506117cf565b61185a6159a6565b506040805160208101909152670c7d713b49da0000815261187b8184613d06565b156118955761188b600580613c98565b93505050506117cf565b6005805490869055604080518281526020810188905281517f3b9670cf975d26958e754b57098eaa2ac914d8d2a31b83257997b9f346110fd9929181900390910190a160005b9695505050505050565b6000546001600160a01b03163314611944576040805162461bcd60e51b815260206004820152601f60248201527f6f6e6c792061646d696e2063616e2064726f7020636f6d70206d61726b657400604482015290519081900360640190fd5b6001600160a01b0381166000908152600960205260409020600381015460ff1615156001146119ba576040805162461bcd60e51b815260206004820152601b60248201527f6d61726b6574206973206e6f74206120636f6d70206d61726b65740000000000604482015290519081900360640190fd5b60038101805460ff19169055604080516001600160a01b03841681526000602082015281517f93c1f3e36ed71139f466a4ce8c9751790e2e33f5afb2df0dcfb3aeabe55d5aa2929181900390910190a1611a12613d0d565b5050565b6001600160a01b03821660009081526009602052604081205460ff16611a6d5760405162461bcd60e51b8152600401808060200182810382526028815260200180615a666028913960400191505060405180910390fd5b600a546001600160a01b0316331480611a9057506000546001600160a01b031633145b611acb5760405162461bcd60e51b8152600401808060200182810382526027815260200180615abf6027913960400191505060405180910390fd5b6000546001600160a01b0316331480611ae657506001821515145b611b30576040805162461bcd60e51b81526020600482015260166024820152756f6e6c792061646d696e2063616e20756e706175736560501b604482015290519081900360640190fd5b6001600160a01b0383166000818152600b6020908152604091829020805486151560ff199091168117909155825193845283830152606090830181905260049083015263135a5b9d60e21b6080830152517f71aec636243f9709bb0007ae15e9afb8150ab01716d75fd7573be5cc096e03b09181900360a00190a150919050565b600a54600160a01b900460ff1681565b50505050565b435b90565b505050505050565b60065481565b6001600160a01b031660009081526008602052604090205490565b333214611c335760405162461bcd60e51b8152600401808060200182810382526031815260200180615a8e6031913960400191505060405180910390fd5b611c3b613d0d565b565b600080600080600080611c528a8a8a8a6140d2565b925092509250826011811115611c6457fe5b95509093509150505b9450945094915050565b6001600160a01b0383166000908152600b602052604081205460ff1615611cd6576040805162461bcd60e51b815260206004820152600e60248201526d1b5a5b9d081a5cc81c185d5cd95960921b604482015290519081900360640190fd5b6001600160a01b03841660009081526009602052604090205460ff16611d005760095b9050611d1b565b611d09846144ed565b611d158484600061476b565b60005b90505b9392505050565b600080546001600160a01b03163314611d41576117f36001600b613c98565b611d496159a6565b506040805160208101909152828152611d606159a6565b506040805160208101909152670de0b6b3a76400008152611d818282613d06565b15611d92576118496007600c613c98565b611d9a6159a6565b5060408051602081019091526714d1120d7b1600008152611dbb8184613d06565b15611dcc5761188b6007600c613c98565b6006805490869055604080518281526020810188905281517faeba5a6c40a8ac138134bff1aaa65debf25971188a58804bad717f82f0ec1316929181900390910190a160006118db565b80158015611e245750600082115b15611bc1576040805162461bcd60e51b815260206004820152601160248201527072656465656d546f6b656e73207a65726f60781b604482015290519081900360640190fd5b600d8181548110611e7757fe5b6000918252602090912001546001600160a01b0316905081565b600080546001600160a01b03163314611eb0576117f360016010613c98565b600480546001600160a01b038481166001600160a01b0319831681179093556040805191909216808252602082019390935281517fd52b2b9b7e9ee655fcb95d2e5b9e0c9f69e7ef2b8e9d2d0ea78402d576d22e22929181900390910190a160009392505050565b60155481565b611436565b600080600080600080611f3a8760008060006140d2565b925092509250826011811115611f4c57fe5b97919650945092505050565b600080546001600160a01b03163314611f77576117f360016013613c98565b600a80546001600160a01b038481166001600160a01b0319831617928390556040805192821680845293909116602083015280517f0613b6ee6a04f0d09f390e4d9318894b9f6ac7fd83897cd8d18896ba579c401e9281900390910190a16000611d1b565b6001600160a01b03851660009081526009602052604081205460ff16158061201d57506001600160a01b03851660009081526009602052604090205460ff16155b1561202c5760095b905061215a565b60008061203885614963565b9193509091506000905082601181111561204e57fe5b146120685781601181111561205f57fe5b9250505061215a565b8061207457600361205f565b6000886001600160a01b03166395dd9193876040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b1580156120cc57600080fd5b505afa1580156120e0573d6000803e3d6000fd5b505050506040513d60208110156120f657600080fd5b505160408051602081019091526005548152909150600090819061211a9084614983565b9092509050600082600381111561212d57fe5b1461214157600b5b9550505050505061215a565b80871115612150576011612135565b6000955050505050505b95945050505050565b60005b83518110156115ac57600084828151811061217d57fe5b6020908102919091018101516001600160a01b0381166000908152600990925260409091205490915060ff166121f2576040805162461bcd60e51b81526020600482015260156024820152741b585c9ad95d081b5d5cdd081899481b1a5cdd1959605a1b604482015290519081900360640190fd5b600184151514156122ba576122056159a6565b6040518060200160405280836001600160a01b031663aa5af0fd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561224957600080fd5b505afa15801561225d573d6000803e3d6000fd5b505050506040513d602081101561227357600080fd5b5051905290506122838282613825565b60005b87518110156122b7576122af8389838151811061229f57fe5b6020026020010151846001613aad565b600101612286565b50505b60018315151415612303576122ce816144ed565b60005b8651811015612301576122f9828883815181106122ea57fe5b6020026020010151600161476b565b6001016122d1565b505b50600101612166565b6123146149d7565b612365576040805162461bcd60e51b815260206004820152601f60248201527f6f6e6c792061646d696e2063616e206368616e676520636f6d70207261746500604482015290519081900360640190fd5b600e805490829055604080518281526020810184905281517fc227c9272633c3a307d9845bf2bc2509cefb20d655b5f3c1002d8e1e3f22c8b0929181900390910190a1611a12613d0d565b6010602052600090815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b600c6020526000908152604090205460ff1681565b600b6020526000908152604090205460ff1681565b66038d7ea4c6800081565b6016546001600160a01b031681565b6004546001600160a01b031681565b600a54600160b01b900460ff1681565b6011602052600090815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b60096020526000908152604090208054600182015460039092015460ff91821692911683565b600a546000906001600160a01b03163314806124b357506000546001600160a01b031633145b6124ee5760405162461bcd60e51b8152600401808060200182810382526027815260200180615abf6027913960400191505060405180910390fd5b6000546001600160a01b031633148061250957506001821515145b612553576040805162461bcd60e51b81526020600482015260166024820152756f6e6c792061646d696e2063616e20756e706175736560501b604482015290519081900360640190fd5b600a8054831515600160b01b810260ff60b01b1990921691909117909155604080516020810192909252808252600882820152672a3930b739b332b960c11b6060830152517fef159d9a32b2472e32b098f954f3ce62d232939f1c207070b584df1814de2de09181900360800190a15090565b6001600160a01b038082166000908152600960209081526040808320938616835260029093019052205460ff1692915050565b60075481565b73c00e94cb662c3520282e6f5717214004a7f2688890565b600080546001600160a01b03163314612636576117f360016012613c98565b6001600160a01b03821660009081526009602052604090205460ff1615612663576117f3600a6011613c98565b816001600160a01b031663fe9c44ae6040518163ffffffff1660e01b815260040160206040518083038186803b15801561269c57600080fd5b505afa1580156126b0573d6000803e3d6000fd5b505050506040513d60208110156126c657600080fd5b5050604080516060810182526001808252600060208381018281528486018381526001600160a01b03891684526009909252949091209251835490151560ff1991821617845593519183019190915551600390910180549115159190921617905561273082614a00565b604080516001600160a01b038416815290517fcf583bb0c569eb967f806b11601c4cb93c10310485c67add5f8362c2f212321f9181900360200190a1600092915050565b6ec097ce7bc90715b34b9f100000000081565b601555565b600e5481565b60608060086000846001600160a01b03166001600160a01b0316815260200190815260200160002080548060200260200160405190810160405280929190818152602001828054801561280e57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116127f0575b5093979650505050505050565b600a54600160b81b900460ff1681565b6060600d80548060200260200160405190810160405280929190818152602001828054801561288357602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612865575b5050505050905090565b601260209081526000928352604080842090915290825290205481565b6002546001600160a01b031681565b600a54600090600160b01b900460ff1615612910576040805162461bcd60e51b81526020600482015260126024820152711d1c985b9cd9995c881a5cc81c185d5cd95960721b604482015290519081900360640190fd5b600061291d868685614ade565b9050801561292c579050611674565b612935866144ed565b6129418686600061476b565b61166e8685600061476b565b6001600160a01b03166000908152600960205260409020805460ff19169055565b60606000825190506060816040519080825280602002602001820160405280156129a2578160200160208202803883390190505b50905060005b828110156129fd5760008582815181106129be57fe5b602002602001015190506129d28133614b81565b60118111156129dd57fe5b8383815181106129e957fe5b6020908102919091010152506001016129a8565b509392505050565b600480546040805163fc57d4df60e01b81526001600160a01b038781169482019490945290516000938493849391169163fc57d4df91602480820192602092909190829003018186803b158015612a5b57600080fd5b505afa158015612a6f573d6000803e3d6000fd5b505050506040513d6020811015612a8557600080fd5b5051600480546040805163fc57d4df60e01b81526001600160a01b038a8116948201949094529051939450600093929091169163fc57d4df91602480820192602092909190829003018186803b158015612ade57600080fd5b505afa158015612af2573d6000803e3d6000fd5b505050506040513d6020811015612b0857600080fd5b50519050811580612b17575080155b15612b2c57600d935060009250612c72915050565b6000866001600160a01b031663182df0f56040518163ffffffff1660e01b815260040160206040518083038186803b158015612b6757600080fd5b505afa158015612b7b573d6000803e3d6000fd5b505050506040513d6020811015612b9157600080fd5b505190506000612b9f6159a6565b612ba76159a6565b612baf6159a6565b6000612bbd60065489614ca2565b945090506000816003811115612bcf57fe5b14612beb57600b5b995060009850612c72975050505050505050565b612bf58787614ca2565b935090506000816003811115612c0757fe5b14612c1357600b612bd7565b612c1d8484614cdd565b925090506000816003811115612c2f57fe5b14612c3b57600b612bd7565b612c45828c614983565b955090506000816003811115612c5757fe5b14612c6357600b612bd7565b60009950939750505050505050505b935093915050565b601360209081526000928352604080842090915290825290205481565b60146020526000908152604090205481565b612cb16149d7565b612d02576040805162461bcd60e51b815260206004820152601e60248201527f6f6e6c792061646d696e2063616e2061646420636f6d70206d61726b65740000604482015290519081900360640190fd5b60005b8151811015612d3257612d2a828281518110612d1d57fe5b6020026020010151614cf5565b600101612d05565b50611597613d0d565b600a54600090600160b81b900460ff1615612d8f576040805162461bcd60e51b815260206004820152600f60248201526e1cd95a5e99481a5cc81c185d5cd959608a1b604482015290519081900360640190fd5b6001600160a01b03861660009081526009602052604090205460ff161580612dd057506001600160a01b03851660009081526009602052604090205460ff16155b15612ddc576009612025565b846001600160a01b0316635fe3b5676040518163ffffffff1660e01b815260040160206040518083038186803b158015612e1557600080fd5b505afa158015612e29573d6000803e3d6000fd5b505050506040513d6020811015612e3f57600080fd5b505160408051635fe3b56760e01b815290516001600160a01b0392831692891691635fe3b567916004808301926020929190829003018186803b158015612e8557600080fd5b505afa158015612e99573d6000803e3d6000fd5b505050506040513d6020811015612eaf57600080fd5b50516001600160a01b031614612ec6576002612025565b612ecf866144ed565b612edb8684600061476b565b612ee78685600061476b565b60009695505050505050565b600080546001600160a01b03163314612f12576117f36001600d613c98565b6007805490839055604080518281526020810185905281517f7093cf1eb653f749c3ff531d6df7f92764536a7fa0d13530cd26e070780c32ea929181900390910190a16000611d1b565b6001600160a01b0383166000908152600c602052604081205460ff1615612fbd576040805162461bcd60e51b815260206004820152601060248201526f189bdc9c9bddc81a5cc81c185d5cd95960821b604482015290519081900360640190fd5b6001600160a01b03841660009081526009602052604090205460ff16612fe4576009611cf9565b6001600160a01b038085166000908152600960209081526040808320938716835260029093019052205460ff166130d457336001600160a01b0385161461306a576040805162461bcd60e51b815260206004820152601560248201527439b2b73232b91036bab9ba1031329031aa37b5b2b760591b604482015290519081900360640190fd5b60006130763385614b81565b9050600081601181111561308657fe5b1461309f5780601181111561309757fe5b915050611d1b565b6001600160a01b038086166000908152600960209081526040808320938816835260029093019052205460ff166130d257fe5b505b600480546040805163fc57d4df60e01b81526001600160a01b03888116948201949094529051929091169163fc57d4df91602480820192602092909190829003018186803b15801561312557600080fd5b505afa158015613139573d6000803e3d6000fd5b505050506040513d602081101561314f57600080fd5b505161315c57600d611cf9565b60008061316c85876000876140d2565b9193509091506000905082601181111561318257fe5b1461319c5781601181111561319357fe5b92505050611d1b565b80156131a9576004613193565b6131b16159a6565b6040518060200160405280886001600160a01b031663aa5af0fd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156131f557600080fd5b505afa158015613209573d6000803e3d6000fd5b505050506040513d602081101561321f57600080fd5b50519052905061322f8782613825565b61323c8787836000613aad565b6000979650505050505050565b6008602052816000526040600020818154811061326257fe5b6000918252602090912001546001600160a01b03169150829050565b6003546001600160a01b031681565b600080546001600160a01b031633146132b3576132ac60016006613c98565b90506113d3565b6001600160a01b0383166000908152600960205260409020805460ff166132e8576132e060096007613c98565b9150506113d3565b6132f06159a6565b5060408051602081019091528381526133076159a6565b506040805160208101909152670c7d713b49da000081526133288183613d06565b156133435761333960066008613c98565b93505050506113d3565b84158015906133cc5750600480546040805163fc57d4df60e01b81526001600160a01b038a8116948201949094529051929091169163fc57d4df91602480820192602092909190829003018186803b15801561339e57600080fd5b505afa1580156133b2573d6000803e3d6000fd5b505050506040513d60208110156133c857600080fd5b5051155b156133dd57613339600d6009613c98565b60018301805490869055604080516001600160a01b03891681526020810183905280820188905290517f70483e6592cd5182d45ac970e05bc62cdcc90e9d8ef2c2dbe686cf383bcd7fc59181900360600190a16000979650505050505050565b600a54600160a81b900460ff1681565b60055481565b61159781600d8054806020026020016040519081016040528092919081815260200182805480156134ad57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161348f575b50505050506113d9565b6000806134c5858585614ade565b905080156134d4579050611d1b565b6134dd856144ed565b6134e98585600061476b565b600095945050505050565b6000808290506000806000836001600160a01b031663c37f68e2336040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060806040518083038186803b15801561355557600080fd5b505afa158015613569573d6000803e3d6000fd5b505050506040513d608081101561357f57600080fd5b5080516020820151604090920151909450909250905082156135d25760405162461bcd60e51b8152600401808060200182810382526025815260200180615ae66025913960400191505060405180910390fd5b80156135ef576135e4600c6002613c98565b9450505050506117cf565b60006135fc873385614ade565b9050801561361d57613611600e600383615010565b955050505050506117cf565b6001600160a01b0385166000908152600960209081526040808320338452600281019092529091205460ff1661365c57600096505050505050506117cf565b3360009081526002820160209081526040808320805460ff1916905560088252918290208054835181840281018401909452808452606093928301828280156136ce57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116136b0575b5050835193945083925060009150505b8281101561372357896001600160a01b03168482815181106136fc57fe5b60200260200101516001600160a01b0316141561371b57809150613723565b6001016136de565b5081811061372d57fe5b33600090815260086020526040902080548190600019810190811061374e57fe5b9060005260206000200160009054906101000a90046001600160a01b031681838154811061377857fe5b600091825260209091200180546001600160a01b0319166001600160a01b039290921691909117905580546137b18260001983016159b9565b50604080516001600160a01b038c16815233602082015281517fe699a64c18b07ac5b7301aa273f36a2287239eb9501d81950672794afba29a0d929181900390910190a160009c9b505050505050505050505050565b6000546001600160a01b031681565b60158054820190819055919050565b6001600160a01b0382166000908152601160209081526040808320600f9092528220549091613852611bc7565b8354909150600090613872908390600160e01b900463ffffffff16615076565b90506000811180156138845750600083115b15613a535760006138f9876001600160a01b03166347bd37186040518163ffffffff1660e01b815260040160206040518083038186803b1580156138c757600080fd5b505afa1580156138db573d6000803e3d6000fd5b505050506040513d60208110156138f157600080fd5b5051876150b0565b9050600061390783866150ce565b90506139116159a6565b6000831161392e5760405180602001604052806000815250613938565b6139388284615110565b90506139426159a6565b604080516020810190915288546001600160e01b03168152613964908361514e565b905060405180604001604052806139b483600001516040518060400160405280601a81526020017f6e657720696e6465782065786365656473203232342062697473000000000000815250615173565b6001600160e01b031681526020016139ef886040518060400160405280601c8152602001600080516020615b0b83398151915281525061520d565b63ffffffff9081169091526001600160a01b038c166000908152601160209081526040909120835181549490920151909216600160e01b026001600160e01b039182166001600160e01b0319909416939093171691909117905550611bcc92505050565b8015611bcc57613a86826040518060400160405280601c8152602001600080516020615b0b83398151915281525061520d565b845463ffffffff91909116600160e01b026001600160e01b03909116178455505050505050565b6001600160a01b0384166000908152601160205260409020613acd6159a6565b50604080516020810190915281546001600160e01b03168152613aee6159a6565b5060408051602080820183526001600160a01b03808a16600090815260138352848120918a1680825282845294812080548552865195909152915291909155805115613c8f57613b3c6159a6565b613b468383615262565b90506000613bd5896001600160a01b03166395dd91938a6040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015613ba357600080fd5b505afa158015613bb7573d6000803e3d6000fd5b505050506040513d6020811015613bcd57600080fd5b5051886150b0565b90506000613be38284615287565b6001600160a01b038a1660009081526014602052604081205491925090613c0a90836152b6565b9050613c2b8a828a613c235766038d7ea4c68000613c26565b60005b6152ec565b6001600160a01b03808c1660008181526014602090815260409182902094909455895181518781529485015280519193928f16927f1fc3ecc087d8d2d15e23d0032af5a47059c3892d003d8e139fdcb6bb327c99a6929081900390910190a3505050505b50505050505050565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0836011811115613cc757fe5b836013811115613cd357fe5b604080519283526020830191909152600082820152519081900360600190a1826011811115611d1b57fe5b519051111590565b5190511090565b6060600d805480602002602001604051908101604052809291908181526020018280548015613d6557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311613d47575b50939450600093505050505b8151811015613e2b576000828281518110613d8857fe5b60200260200101519050613d9a6159a6565b6040518060200160405280836001600160a01b031663aa5af0fd6040518163ffffffff1660e01b815260040160206040518083038186803b158015613dde57600080fd5b505afa158015613df2573d6000803e3d6000fd5b505050506040513d6020811015613e0857600080fd5b505190529050613e17826144ed565b613e218282613825565b5050600101613d71565b50613e346159a6565b60405180602001604052806000815250905060608251604051908082528060200260200182016040528015613e8357816020015b613e706159a6565b815260200190600190039081613e685790505b50905060005b8351811015614009576000848281518110613ea057fe5b6020908102919091018101516001600160a01b0381166000908152600990925260409091206003015490915060ff161561400057613edc6159a6565b60408051602080820180845260045463fc57d4df60e01b9091526001600160a01b03868116602485015293519293849391169163fc57d4df916044808601929190818703018186803b158015613f3157600080fd5b505afa158015613f45573d6000803e3d6000fd5b505050506040513d6020811015613f5b57600080fd5b505190529050613f696159a6565b613fd782846001600160a01b03166347bd37186040518163ffffffff1660e01b815260040160206040518083038186803b158015613fa657600080fd5b505afa158015613fba573d6000803e3d6000fd5b505050506040513d6020811015613fd057600080fd5b5051615431565b905080858581518110613fe657fe5b6020026020010181905250613ffb868261514e565b955050505b50600101613e89565b5060005b8351811015611bc1576000600d828154811061402557fe5b600091825260208220015485516001600160a01b03909116925061404a576000614072565b614072600e5461406d86868151811061405f57fe5b602002602001015188615452565b615485565b6001600160a01b0383166000818152600f60209081526040918290208490558151848152915193945091927f2ab93f65628379309f36cb125e90d7c902454a545c4f8b8cb0794af75c24b807929181900390910190a2505060010161400d565b60008060006140df6159dd565b6001600160a01b03881660009081526008602090815260408083208054825181850281018501909352808352849360609392919083018282801561414c57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161412e575b50939450600093505050505b81518110156144a857600082828151811061416f57fe5b60200260200101519050806001600160a01b031663c37f68e28e6040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060806040518083038186803b1580156141cf57600080fd5b505afa1580156141e3573d6000803e3d6000fd5b505050506040513d60808110156141f957600080fd5b508051602082015160408084015160609485015160808c0152938a0193909352918801919091529450841561423f5750600f975060009650869550611c6d945050505050565b60408051602080820183526001600160a01b0380851660008181526009845285902060010154845260c08b01939093528351808301855260808b0151815260e08b015260048054855163fc57d4df60e01b815291820194909452935192169263fc57d4df9260248083019392829003018186803b1580156142bf57600080fd5b505afa1580156142d3573d6000803e3d6000fd5b505050506040513d60208110156142e957600080fd5b505160a0870181905261430d5750600d975060009650869550611c6d945050505050565b604080516020810190915260a08701518152610100870181905260c087015160e088015161433a9261549e565b6101208801529350600084600381111561435057fe5b1461436c5750600b975060009650869550611c6d945050505050565b614384866101200151876040015188600001516154f6565b87529350600084600381111561439657fe5b146143b25750600b975060009650869550611c6d945050505050565b6143ca866101000151876060015188602001516154f6565b6020880152935060008460038111156143df57fe5b146143fb5750600b975060009650869550611c6d945050505050565b8b6001600160a01b0316816001600160a01b0316141561449f576144298661012001518c88602001516154f6565b60208801529350600084600381111561443e57fe5b1461445a5750600b975060009650869550611c6d945050505050565b61446e8661010001518b88602001516154f6565b60208801529350600084600381111561448357fe5b1461449f5750600b975060009650869550611c6d945050505050565b50600101614158565b506020840151845111156144cf575050506020810151905160009450039150829050611c6d565b5050815160209092015160009550859450919091039150611c6d9050565b6001600160a01b0381166000908152601060209081526040808320600f909252822054909161451a611bc7565b835490915060009061453a908390600160e01b900463ffffffff16615076565b905060008111801561454c5750600083115b15614712576000856001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561458c57600080fd5b505afa1580156145a0573d6000803e3d6000fd5b505050506040513d60208110156145b657600080fd5b5051905060006145c683866150ce565b90506145d06159a6565b600083116145ed57604051806020016040528060008152506145f7565b6145f78284615110565b90506146016159a6565b604080516020810190915288546001600160e01b03168152614623908361514e565b9050604051806040016040528061467383600001516040518060400160405280601a81526020017f6e657720696e6465782065786365656473203232342062697473000000000000815250615173565b6001600160e01b031681526020016146ae886040518060400160405280601c8152602001600080516020615b0b83398151915281525061520d565b63ffffffff9081169091526001600160a01b038b166000908152601060209081526040909120835181549490920151909216600160e01b026001600160e01b039182166001600160e01b03199094169390931716919091179055506115ac92505050565b80156115ac57614745826040518060400160405280601c8152602001600080516020615b0b83398151915281525061520d565b845463ffffffff91909116600160e01b026001600160e01b039091161784555050505050565b6001600160a01b038316600090815260106020526040902061478b6159a6565b50604080516020810190915281546001600160e01b031681526147ac6159a6565b5060408051602080820183526001600160a01b038089166000908152601283528481209189168082528284529481208054855286519590915291529190915580511580156147fa5750815115155b15614812576ec097ce7bc90715b34b9f100000000081525b61481a6159a6565b6148248383615262565b90506000876001600160a01b03166370a08231886040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561487e57600080fd5b505afa158015614892573d6000803e3d6000fd5b505050506040513d60208110156148a857600080fd5b5051905060006148b88284615287565b6001600160a01b038916600090815260146020526040812054919250906148df90836152b6565b90506148f889828a613c235766038d7ea4c68000613c26565b6001600160a01b03808b1660008181526014602090815260409182902094909455895181518781529485015280519193928e16927f2caecd17d02f56fa897705dcc740da2d237c373f70686f4e0d9bd3bf0400ea7a929081900390910190a350505050505050505050565b60008060006149768460008060006140d2565b9250925092509193909250565b60008060006149906159a6565b61499a8686615543565b909250905060008260038111156149ad57fe5b146149be57509150600090506149d0565b60006149c9826155ab565b9350935050505b9250929050565b600080546001600160a01b03163314806149fb57506002546001600160a01b031633145b905090565b60005b600d54811015614a8b57816001600160a01b0316600d8281548110614a2457fe5b6000918252602090912001546001600160a01b03161415614a83576040805162461bcd60e51b81526020600482015260146024820152731b585c9ad95d08185b1c9958591e48185919195960621b604482015290519081900360640190fd5b600101614a03565b50600d80546001810182556000919091527fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb50180546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b03831660009081526009602052604081205460ff16614b05576009611cf9565b6001600160a01b038085166000908152600960209081526040808320938716835260029093019052205460ff16614b3d576000611cf9565b600080614b4d85878660006140d2565b91935090915060009050826011811115614b6357fe5b14614b745781601181111561319357fe5b8015612ee7576004613193565b6001600160a01b0382166000908152600960205260408120805460ff16614bac5760099150506113d3565b6001600160a01b038316600090815260028201602052604090205460ff16151560011415614bde5760009150506113d3565b6007546001600160a01b03841660009081526008602052604090205410614c095760109150506113d3565b6001600160a01b0380841660008181526002840160209081526040808320805460ff19166001908117909155600883528184208054918201815584529282902090920180549489166001600160a01b031990951685179055815193845283019190915280517f3ab23ab0d51cccc0c3085aec51f99228625aa1a922b3a8ca89a26b0f2027a1a59281900390910190a15060009392505050565b6000614cac6159a6565b614cd26040518060200160405280868152506040518060200160405280868152506155ba565b915091509250929050565b6000614ce76159a6565b83518351614cd291906156a3565b6001600160a01b0381166000908152600960205260409020805460ff161515600114614d68576040805162461bcd60e51b815260206004820152601960248201527f636f6d70206d61726b6574206973206e6f74206c697374656400000000000000604482015290519081900360640190fd5b600381015460ff1615614dc2576040805162461bcd60e51b815260206004820152601960248201527f636f6d70206d61726b657420616c726561647920616464656400000000000000604482015290519081900360640190fd5b60038101805460ff19166001908117909155604080516001600160a01b0385168152602081019290925280517f93c1f3e36ed71139f466a4ce8c9751790e2e33f5afb2df0dcfb3aeabe55d5aa29281900390910190a16001600160a01b0382166000908152601060205260409020546001600160e01b0316158015614e6a57506001600160a01b038216600090815260106020526040902054600160e01b900463ffffffff16155b15614f275760405180604001604052806ec097ce7bc90715b34b9f10000000006001600160e01b03168152602001614ecc614ea3611bc7565b6040518060400160405280601c8152602001600080516020615b0b83398151915281525061520d565b63ffffffff9081169091526001600160a01b0384166000908152601060209081526040909120835181549490920151909216600160e01b026001600160e01b039182166001600160e01b031990941693909317169190911790555b6001600160a01b0382166000908152601160205260409020546001600160e01b0316158015614f7957506001600160a01b038216600090815260116020526040902054600160e01b900463ffffffff16155b15611a125760405180604001604052806ec097ce7bc90715b34b9f10000000006001600160e01b03168152602001614fb2614ea3611bc7565b63ffffffff9081169091526001600160a01b0384166000908152601160209081526040909120835181549490920151909216600160e01b026001600160e01b039182166001600160e01b031990941693909317169190911790555050565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa084601181111561503f57fe5b84601381111561504b57fe5b604080519283526020830191909152818101859052519081900360600190a1836011811115611d1857fe5b6000611d1b8383604051806040016040528060158152602001747375627472616374696f6e20756e646572666c6f7760581b815250615753565b6000611d1b6150c784670de0b6b3a76400006150ce565b83516157ad565b6000611d1b83836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f770000000000000000008152506157e0565b6151186159a6565b604051806020016040528061514561513f866ec097ce7bc90715b34b9f10000000006150ce565b856157ad565b90529392505050565b6151566159a6565b6040518060200160405280615145856000015185600001516152b6565b600081600160e01b84106152055760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156151ca5781810151838201526020016151b2565b50505050905090810190601f1680156151f75780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b509192915050565b600081600160201b84106152055760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156151ca5781810151838201526020016151b2565b61526a6159a6565b604051806020016040528061514585600001518560000151615076565b60006ec097ce7bc90715b34b9f10000000006152a78484600001516150ce565b816152ae57fe5b049392505050565b6000611d1b8383604051806040016040528060118152602001706164646974696f6e206f766572666c6f7760781b81525061585f565b60008183101580156152fe5750600083115b1561542957600061530d6125ff565b604080516370a0823160e01b815230600482015290519192506000916001600160a01b038416916370a08231916024808301926020929190829003018186803b15801561535957600080fd5b505afa15801561536d573d6000803e3d6000fd5b505050506040513d602081101561538357600080fd5b5051905080851161542657816001600160a01b031663a9059cbb87876040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b1580156153ee57600080fd5b505af1158015615402573d6000803e3d6000fd5b505050506040513d602081101561541857600080fd5b5060009350611d1b92505050565b50505b509092915050565b6154396159a6565b60405180602001604052806151458560000151856150ce565b61545a6159a6565b604051806020016040528061514561547e8660000151670de0b6b3a76400006150ce565b85516157ad565b6000670de0b6b3a76400006152a78484600001516150ce565b60006154a86159a6565b60006154b26159a6565b6154bc87876155ba565b909250905060008260038111156154cf57fe5b146154de579092509050612c72565b6154e881866155ba565b935093505050935093915050565b60008060006155036159a6565b61550d8787615543565b9092509050600082600381111561552057fe5b146155315750915060009050612c72565b6154e861553d826155ab565b866158b4565b600061554d6159a6565b60008061555e8660000151866158da565b9092509050600082600381111561557157fe5b14615590575060408051602081019091526000815290925090506149d0565b60408051602081019091529081526000969095509350505050565b51670de0b6b3a7640000900490565b60006155c46159a6565b6000806155d9866000015186600001516158da565b909250905060008260038111156155ec57fe5b1461560b575060408051602081019091526000815290925090506149d0565b6000806156206706f05b59d3b20000846158b4565b9092509050600082600381111561563357fe5b14615655575060408051602081019091526000815290945092506149d0915050565b60008061566a83670de0b6b3a7640000615919565b9092509050600082600381111561567d57fe5b1461568457fe5b604080516020810190915290815260009a909950975050505050505050565b60006156ad6159a6565b6000806156c286670de0b6b3a76400006158da565b909250905060008260038111156156d557fe5b146156f4575060408051602081019091526000815290925090506149d0565b6000806157018388615919565b9092509050600082600381111561571457fe5b14615736575060408051602081019091526000815290945092506149d0915050565b604080516020810190915290815260009890975095505050505050565b600081848411156157a55760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156151ca5781810151838201526020016151b2565b505050900390565b6000611d1b83836040518060400160405280600e81526020016d646976696465206279207a65726f60901b815250615944565b60008315806157ed575082155b156157fa57506000611d1b565b8383028385828161580757fe5b041483906158565760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156151ca5781810151838201526020016151b2565b50949350505050565b600083830182858210156158565760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156151ca5781810151838201526020016151b2565b6000808383018481106158cc576000925090506149d0565b5060029150600090506149d0565b600080836158ed575060009050806149d0565b838302838582816158fa57fe5b041461590e575060029150600090506149d0565b6000925090506149d0565b6000808261592d57506001905060006149d0565b600083858161593857fe5b04915091509250929050565b600081836159935760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156151ca5781810151838201526020016151b2565b5082848161599d57fe5b04949350505050565b6040518060200160405280600081525090565b81548183558181111561143657600083815260209020611436918101908301615a47565b604051806101400160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001615a1b6159a6565b8152602001615a286159a6565b8152602001615a356159a6565b8152602001615a426159a6565b905290565b611bc991905b80821115615a615760008155600101615a4d565b509056fe63616e6e6f742070617573652061206d61726b65742074686174206973206e6f74206c69737465646f6e6c792065787465726e616c6c79206f776e6564206163636f756e7473206d61792072656672657368207370656564736f6e6c7920706175736520677561726469616e20616e642061646d696e2063616e207061757365657869744d61726b65743a206765744163636f756e74536e617073686f74206661696c6564626c6f636b206e756d62657220657863656564732033322062697473000000006f6e6c7920756e6974726f6c6c65722061646d696e2063616e206368616e676520627261696e73a265627a7a723158201bad72aa659c10cc67aa1fc210bd593abc17469036fc4b521889977a00379b0764736f6c63430005100032", + "metadata": "{\"compiler\":{\"version\":\"0.5.16+commit.9c3226ce\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"action\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"pauseState\",\"type\":\"bool\"}],\"name\":\"ActionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"action\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"pauseState\",\"type\":\"bool\"}],\"name\":\"ActionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSpeed\",\"type\":\"uint256\"}],\"name\":\"CompSpeedUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compBorrowIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedBorrowerComp\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"supplier\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compSupplyIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedSupplierComp\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isComped\",\"type\":\"bool\"}],\"name\":\"MarketComped\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketEntered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketExited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"MarketListed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCloseFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCloseFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCollateralFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCollateralFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCompRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCompRate\",\"type\":\"uint256\"}],\"name\":\"NewCompRate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldLiquidationIncentiveMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"NewLiquidationIncentive\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMaxAssets\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMaxAssets\",\"type\":\"uint256\"}],\"name\":\"NewMaxAssets\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldPauseGuardian\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"NewPauseGuardian\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"oldPriceOracle\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"newPriceOracle\",\"type\":\"address\"}],\"name\":\"NewPriceOracle\",\"type\":\"event\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"_addCompMarkets\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract Unitroller\",\"name\":\"unitroller\",\"type\":\"address\"}],\"name\":\"_become\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"_dropCompMarket\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setBorrowPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCloseFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCollateralFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"compRate_\",\"type\":\"uint256\"}],\"name\":\"_setCompRate\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"_setLiquidationIncentive\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newMaxAssets\",\"type\":\"uint256\"}],\"name\":\"_setMaxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setMintPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"_setPauseGuardian\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"newOracle\",\"type\":\"address\"}],\"name\":\"_setPriceOracle\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setSeizePaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setTransferPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"_supportMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allMarkets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"blockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"checkMembership\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"},{\"internalType\":\"contract CToken[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"holders\",\"type\":\"address[]\"},{\"internalType\":\"contract CToken[]\",\"name\":\"cTokens\",\"type\":\"address[]\"},{\"internalType\":\"bool\",\"name\":\"borrowers\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"suppliers\",\"type\":\"bool\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compAccrued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compBorrowState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compBorrowerIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compClaimThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compInitialIndex\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSupplierIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSupplyState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"enterMarkets\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenAddress\",\"type\":\"address\"}],\"name\":\"exitMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blocks\",\"type\":\"uint256\"}],\"name\":\"fastForward\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getAllMarkets\",\"outputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAssetsIn\",\"outputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getCompAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenModify\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"getHypotheticalAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"isComptroller\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateCalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"liquidationIncentiveMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"markets\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isComped\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"membershipLength\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"mintAmount\",\"type\":\"uint256\"}],\"name\":\"mintAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualMintAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"mintTokens\",\"type\":\"uint256\"}],\"name\":\"mintVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"refreshCompSpeeds\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"repayBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowerIndex\",\"type\":\"uint256\"}],\"name\":\"repayBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"seizeGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"}],\"name\":\"setBlockNumber\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"transferGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"unlist\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"methods\":{\"_addCompMarkets(address[])\":{\"params\":{\"cTokens\":\"The addresses of the markets to add\"}},\"_dropCompMarket(address)\":{\"params\":{\"cToken\":\"The address of the market to drop\"}},\"_setCloseFactor(uint256)\":{\"details\":\"Admin function to set closeFactor\",\"params\":{\"newCloseFactorMantissa\":\"New close factor, scaled by 1e18\"},\"return\":\"uint 0=success, otherwise a failure. (See ErrorReporter for details)\"},\"_setCollateralFactor(address,uint256)\":{\"details\":\"Admin function to set per-market collateralFactor\",\"params\":{\"cToken\":\"The market to set the factor on\",\"newCollateralFactorMantissa\":\"The new collateral factor, scaled by 1e18\"},\"return\":\"uint 0=success, otherwise a failure. (See ErrorReporter for details)\"},\"_setCompRate(uint256)\":{\"params\":{\"compRate_\":\"The amount of COMP wei per block to distribute\"}},\"_setLiquidationIncentive(uint256)\":{\"details\":\"Admin function to set liquidationIncentive\",\"params\":{\"newLiquidationIncentiveMantissa\":\"New liquidationIncentive scaled by 1e18\"},\"return\":\"uint 0=success, otherwise a failure. (See ErrorReporter for details)\"},\"_setMaxAssets(uint256)\":{\"details\":\"Admin function to set maxAssets\",\"params\":{\"newMaxAssets\":\"New max assets\"},\"return\":\"uint 0=success, otherwise a failure. (See ErrorReporter for details)\"},\"_setPauseGuardian(address)\":{\"params\":{\"newPauseGuardian\":\"The address of the new Pause Guardian\"},\"return\":\"uint 0=success, otherwise a failure. (See enum Error for details)\"},\"_setPriceOracle(address)\":{\"details\":\"Admin function to set a new price oracle\",\"return\":\"uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\"},\"_supportMarket(address)\":{\"details\":\"Admin function to set isListed and add support for the market\",\"params\":{\"cToken\":\"The address of the market (token) to list\"},\"return\":\"uint 0=success, otherwise a failure. (See enum Error for details)\"},\"borrowAllowed(address,address,uint256)\":{\"params\":{\"borrowAmount\":\"The amount of underlying the account would borrow\",\"borrower\":\"The account which would borrow the asset\",\"cToken\":\"The market to verify the borrow against\"},\"return\":\"0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"borrowVerify(address,address,uint256)\":{\"params\":{\"borrowAmount\":\"The amount of the underlying asset requested to borrow\",\"borrower\":\"The address borrowing the underlying\",\"cToken\":\"Asset whose underlying is being borrowed\"}},\"checkMembership(address,address)\":{\"params\":{\"account\":\"The address of the account to check\",\"cToken\":\"The cToken to check\"},\"return\":\"True if the account is in the asset, otherwise false.\"},\"claimComp(address)\":{\"params\":{\"holder\":\"The address to claim COMP for\"}},\"claimComp(address,address[])\":{\"params\":{\"cTokens\":\"The list of markets to claim COMP in\",\"holder\":\"The address to claim COMP for\"}},\"claimComp(address[],address[],bool,bool)\":{\"params\":{\"borrowers\":\"Whether or not to claim COMP earned by borrowing\",\"cTokens\":\"The list of markets to claim COMP in\",\"holders\":\"The addresses to claim COMP for\",\"suppliers\":\"Whether or not to claim COMP earned by supplying\"}},\"enterMarkets(address[])\":{\"params\":{\"cTokens\":\"The list of addresses of the cToken markets to be enabled\"},\"return\":\"Success indicator for whether each corresponding market was entered\"},\"exitMarket(address)\":{\"details\":\"Sender must not have an outstanding borrow balance in the asset, or be providing necessary collateral for an outstanding borrow.\",\"params\":{\"cTokenAddress\":\"The address of the asset to be removed\"},\"return\":\"Whether or not the account successfully exited the market\"},\"getAccountLiquidity(address)\":{\"return\":\"(possible error code (semi-opaque), account liquidity in excess of collateral requirements, account shortfall below collateral requirements)\"},\"getAllMarkets()\":{\"details\":\"The automatic getter may be used to access an individual market.\",\"return\":\"The list of market addresses\"},\"getAssetsIn(address)\":{\"params\":{\"account\":\"The address of the account to pull assets for\"},\"return\":\"A dynamic list with the assets the account has entered\"},\"getCompAddress()\":{\"return\":\"The address of COMP\"},\"getHypotheticalAccountLiquidity(address,address,uint256,uint256)\":{\"params\":{\"account\":\"The account to determine liquidity for\",\"borrowAmount\":\"The amount of underlying to hypothetically borrow\",\"cTokenModify\":\"The market to hypothetically redeem/borrow in\",\"redeemTokens\":\"The number of tokens to hypothetically redeem\"},\"return\":\"(possible error code (semi-opaque), hypothetical account liquidity in excess of collateral requirements, hypothetical account shortfall below collateral requirements)\"},\"liquidateBorrowAllowed(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"repayAmount\":\"The amount of underlying being repaid\"}},\"liquidateBorrowVerify(address,address,address,address,uint256,uint256)\":{\"params\":{\"actualRepayAmount\":\"The amount of underlying being repaid\",\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\"}},\"liquidateCalculateSeizeTokens(address,address,uint256)\":{\"details\":\"Used in liquidation (called in cToken.liquidateBorrowFresh)\",\"params\":{\"actualRepayAmount\":\"The amount of cTokenBorrowed underlying to convert into cTokenCollateral tokens\",\"cTokenBorrowed\":\"The address of the borrowed cToken\",\"cTokenCollateral\":\"The address of the collateral cToken\"},\"return\":\"(errorCode, number of cTokenCollateral tokens to be seized in a liquidation)\"},\"mintAllowed(address,address,uint256)\":{\"params\":{\"cToken\":\"The market to verify the mint against\",\"mintAmount\":\"The amount of underlying being supplied to the market in exchange for tokens\",\"minter\":\"The account which would get the minted tokens\"},\"return\":\"0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"mintVerify(address,address,uint256,uint256)\":{\"params\":{\"actualMintAmount\":\"The amount of the underlying asset being minted\",\"cToken\":\"Asset being minted\",\"mintTokens\":\"The number of tokens being minted\",\"minter\":\"The address minting the tokens\"}},\"redeemAllowed(address,address,uint256)\":{\"params\":{\"cToken\":\"The market to verify the redeem against\",\"redeemTokens\":\"The number of cTokens to exchange for the underlying asset in the market\",\"redeemer\":\"The account which would redeem the tokens\"},\"return\":\"0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"redeemVerify(address,address,uint256,uint256)\":{\"params\":{\"cToken\":\"Asset being redeemed\",\"redeemAmount\":\"The amount of the underlying asset being redeemed\",\"redeemTokens\":\"The number of tokens being redeemed\",\"redeemer\":\"The address redeeming the tokens\"}},\"repayBorrowAllowed(address,address,address,uint256)\":{\"params\":{\"borrower\":\"The account which would borrowed the asset\",\"cToken\":\"The market to verify the repay against\",\"payer\":\"The account which would repay the asset\",\"repayAmount\":\"The amount of the underlying asset the account would repay\"},\"return\":\"0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"repayBorrowVerify(address,address,address,uint256,uint256)\":{\"params\":{\"actualRepayAmount\":\"The amount of underlying being repaid\",\"borrower\":\"The address of the borrower\",\"cToken\":\"Asset being repaid\",\"payer\":\"The address repaying the borrow\"}},\"seizeAllowed(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"seizeTokens\":\"The number of collateral tokens to seize\"}},\"seizeVerify(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"seizeTokens\":\"The number of collateral tokens to seize\"}},\"transferAllowed(address,address,address,uint256)\":{\"params\":{\"cToken\":\"The market to verify the transfer against\",\"dst\":\"The account which receives the tokens\",\"src\":\"The account which sources the tokens\",\"transferTokens\":\"The number of cTokens to transfer\"},\"return\":\"0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"transferVerify(address,address,address,uint256)\":{\"params\":{\"cToken\":\"Asset being transferred\",\"dst\":\"The account which receives the tokens\",\"src\":\"The account which sources the tokens\",\"transferTokens\":\"The number of cTokens to transfer\"}}}},\"userdoc\":{\"methods\":{\"_addCompMarkets(address[])\":{\"notice\":\"Add markets to compMarkets, allowing them to earn COMP in the flywheel\"},\"_dropCompMarket(address)\":{\"notice\":\"Remove a market from compMarkets, preventing it from earning COMP in the flywheel\"},\"_setCloseFactor(uint256)\":{\"notice\":\"Sets the closeFactor used when liquidating borrows\"},\"_setCollateralFactor(address,uint256)\":{\"notice\":\"Sets the collateralFactor for a market\"},\"_setCompRate(uint256)\":{\"notice\":\"Set the amount of COMP distributed per block\"},\"_setLiquidationIncentive(uint256)\":{\"notice\":\"Sets liquidationIncentive\"},\"_setMaxAssets(uint256)\":{\"notice\":\"Sets maxAssets which controls how many markets can be entered\"},\"_setPauseGuardian(address)\":{\"notice\":\"Admin function to change the Pause Guardian\"},\"_setPriceOracle(address)\":{\"notice\":\"Sets a new price oracle for the comptroller\"},\"_supportMarket(address)\":{\"notice\":\"Add the market to the markets mapping and set it as listed\"},\"borrowAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to borrow the underlying asset of the given market\"},\"borrowVerify(address,address,uint256)\":{\"notice\":\"Validates borrow and reverts on rejection. May emit logs.\"},\"checkMembership(address,address)\":{\"notice\":\"Returns whether the given account is entered in the given asset\"},\"claimComp(address)\":{\"notice\":\"Claim all the comp accrued by holder in all markets\"},\"claimComp(address,address[])\":{\"notice\":\"Claim all the comp accrued by holder in the specified markets\"},\"claimComp(address[],address[],bool,bool)\":{\"notice\":\"Claim all comp accrued by the holders\"},\"enterMarkets(address[])\":{\"notice\":\"Add assets to be included in account liquidity calculation\"},\"exitMarket(address)\":{\"notice\":\"Removes asset from sender's account liquidity calculation\"},\"getAccountLiquidity(address)\":{\"notice\":\"Determine the current account liquidity wrt collateral requirements\"},\"getAllMarkets()\":{\"notice\":\"Return all of the markets\"},\"getAssetsIn(address)\":{\"notice\":\"Returns the assets an account has entered\"},\"getCompAddress()\":{\"notice\":\"Return the address of the COMP token\"},\"getHypotheticalAccountLiquidity(address,address,uint256,uint256)\":{\"notice\":\"Determine what the account liquidity would be if the given amounts were redeemed/borrowed\"},\"liquidateBorrowAllowed(address,address,address,address,uint256)\":{\"notice\":\"Checks if the liquidation should be allowed to occur\"},\"liquidateBorrowVerify(address,address,address,address,uint256,uint256)\":{\"notice\":\"Validates liquidateBorrow and reverts on rejection. May emit logs.\"},\"liquidateCalculateSeizeTokens(address,address,uint256)\":{\"notice\":\"Calculate number of tokens of collateral asset to seize given an underlying amount\"},\"mintAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to mint tokens in the given market\"},\"mintVerify(address,address,uint256,uint256)\":{\"notice\":\"Validates mint and reverts on rejection. May emit logs.\"},\"redeemAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to redeem tokens in the given market\"},\"redeemVerify(address,address,uint256,uint256)\":{\"notice\":\"Validates redeem and reverts on rejection. May emit logs.\"},\"refreshCompSpeeds()\":{\"notice\":\"Recalculate and update COMP speeds for all COMP markets\"},\"repayBorrowAllowed(address,address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to repay a borrow in the given market\"},\"repayBorrowVerify(address,address,address,uint256,uint256)\":{\"notice\":\"Validates repayBorrow and reverts on rejection. May emit logs.\"},\"seizeAllowed(address,address,address,address,uint256)\":{\"notice\":\"Checks if the seizing of assets should be allowed to occur\"},\"seizeVerify(address,address,address,address,uint256)\":{\"notice\":\"Validates seize and reverts on rejection. May emit logs.\"},\"transferAllowed(address,address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to transfer tokens in the given market\"},\"transferVerify(address,address,address,uint256)\":{\"notice\":\"Validates transfer and reverts on rejection. May emit logs.\"}}}},\"settings\":{\"compilationTarget\":{\"tests/Contracts/ComptrollerScenarioG4.sol\":\"ComptrollerScenarioG4\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/CToken.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./CTokenInterfaces.sol\\\";\\nimport \\\"./ErrorReporter.sol\\\";\\nimport \\\"./Exponential.sol\\\";\\nimport \\\"./EIP20Interface.sol\\\";\\nimport \\\"./InterestRateModel.sol\\\";\\n\\n/**\\n * @title Compound's CToken Contract\\n * @notice Abstract base for CTokens\\n * @author Compound\\n */\\ncontract CToken is CTokenInterface, Exponential, TokenErrorReporter {\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_) public {\\n require(msg.sender == admin, \\\"only admin may initialize the market\\\");\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = getBlockNumber();\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Transfer `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = uint(-1);\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srcTokensNew;\\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, srcTokensNew) = 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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srcTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != uint(-1)) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n // unused function\\n // comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transfer(address dst, uint256 amount) external nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferFrom(address src, address dst, uint256 amount) external nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (-1 means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool) {\\n address src = msg.sender;\\n transferAllowances[src][spender] = amount;\\n emit Approval(src, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (-1 means infinite)\\n */\\n function allowance(address owner, address spender) external view returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external returns (uint) {\\n Exp memory exchangeRate = Exp({mantissa: exchangeRateCurrent()});\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n require(mErr == MathError.NO_ERROR, \\\"balance could not be calculated\\\");\\n return balance;\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view returns (uint, uint, uint, uint) {\\n uint cTokenBalance = accountTokens[account];\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), cTokenBalance, borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @dev Function to simply retrieve block number\\n * This exists mainly for inheriting test contracts to stub this result.\\n */\\n function getBlockNumber() internal view returns (uint) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this cToken\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view returns (uint) {\\n return interestRateModel.getBorrowRate(getCashPrior(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this cToken\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view returns (uint) {\\n return interestRateModel.getSupplyRate(getCashPrior(), totalBorrows, totalReserves, reserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n require(err == MathError.NO_ERROR, \\\"borrowBalanceStored: borrowBalanceStoredInternal failed\\\");\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return (error code, the calculated balance or 0 if error code is non-zero)\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the CToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n require(err == MathError.NO_ERROR, \\\"exchangeRateStored: exchangeRateStoredInternal failed\\\");\\n return result;\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the CToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return (error code, calculated exchange rate scaled by 1e18)\\n */\\n function exchangeRateStoredInternal() internal view returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows - totalReserves) / totalSupply\\n */\\n uint totalCash = getCashPrior();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Get cash balance of this cToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage.\\n */\\n function accrueInterest() public returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = getBlockNumber();\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = getCashPrior();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n require(mathErr == MathError.NO_ERROR, \\\"could not calculate block delta\\\");\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({mantissa: borrowRateMantissa}), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(Exp({mantissa: reserveFactorMantissa}), interestAccumulated, reservesPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives cTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n struct MintLocalVars {\\n Error err;\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives cTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, 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's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the cToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of cTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.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 cTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED\\\");\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\\");\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender redeems cTokens in exchange for the underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemTokens The number of cTokens to redeem into underlying\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemInternal(uint redeemTokens) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(msg.sender, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems cTokens in exchange for a specified amount of underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemAmount The amount of underlying to receive from redeeming cTokens\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemUnderlyingInternal(uint redeemAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(msg.sender, 0, redeemAmount);\\n }\\n\\n struct RedeemLocalVars {\\n Error err;\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n /**\\n * @notice User redeems cTokens in exchange for the underlying asset\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param redeemTokensIn The number of cTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming cTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemFresh(address payable redeemer, uint redeemTokensIn, uint redeemAmountIn) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr));\\n }\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(Exp({mantissa: vars.exchangeRateMantissa}), redeemTokensIn);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(redeemAmountIn, Exp({mantissa: vars.exchangeRateMantissa}));\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REDEEM_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDEEM_FRESHNESS_CHECK);\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDEEM_TRANSFER_OUT_NOT_POSSIBLE);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We invoke doTransferOut for the redeemer and the redeemAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(redeemer, vars.redeemAmount);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n /* We call the defense hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender borrows assets from the protocol to their own address\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function borrowInternal(uint borrowAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(msg.sender, borrowAmount);\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n /**\\n * @notice Users borrow assets from the protocol to their own address\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function borrowFresh(address payable borrower, uint borrowAmount) internal returns (uint) {\\n /* Fail if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.BORROW_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.BORROW_FRESHNESS_CHECK);\\n }\\n\\n /* Fail gracefully if protocol has insufficient underlying cash */\\n if (getCashPrior() < borrowAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.BORROW_CASH_NOT_AVAILABLE);\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We invoke doTransferOut for the borrower and the borrowAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(borrower, borrowAmount);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to borrower\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer the account paying off the borrow\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount the amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED\\\");\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED\\\");\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this cToken to be liquidated\\n * @param cTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) 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 = cTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, cTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this cToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param cTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowFresh(address liquidator, address borrower, uint repayAmount, CTokenInterface cTokenCollateral) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(address(this), address(cTokenCollateral), liquidator, borrower, repayAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify cTokenCollateral market's block number equals current block number */\\n if (cTokenCollateral.accrualBlockNumber() != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = -1 */\\n if (repayAmount == uint(-1)) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & 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(cTokenCollateral), actualRepayAmount);\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(cTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(cTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = cTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(cTokenCollateral), seizeTokens);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.liquidateBorrowVerify(address(this), address(cTokenCollateral), liquidator, borrower, actualRepayAmount, seizeTokens);\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another cToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed cToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of cTokens to seize\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function seize(address liquidator, address borrower, uint seizeTokens) external nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n struct SeizeInternalLocalVars {\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n uint liquidatorSeizeTokens;\\n uint protocolSeizeTokens;\\n uint protocolSeizeAmount;\\n uint exchangeRateMantissa;\\n uint totalReservesNew;\\n uint totalSupplyNew;\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another CToken.\\n * Its absolutely critical to use msg.sender as the seizer cToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed cToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of cTokens to seize\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function seizeInternal(address seizerToken, address liquidator, address borrower, uint seizeTokens) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n SeizeInternalLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (vars.mathErr, vars.borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(vars.mathErr));\\n }\\n\\n vars.protocolSeizeTokens = mul_(seizeTokens, Exp({mantissa: protocolSeizeShareMantissa}));\\n vars.liquidatorSeizeTokens = sub_(seizeTokens, vars.protocolSeizeTokens);\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n require(vars.mathErr == MathError.NO_ERROR, \\\"exchange rate math error\\\");\\n\\n vars.protocolSeizeAmount = mul_ScalarTruncate(Exp({mantissa: vars.exchangeRateMantissa}), vars.protocolSeizeTokens);\\n\\n vars.totalReservesNew = add_(totalReserves, vars.protocolSeizeAmount);\\n vars.totalSupplyNew = sub_(totalSupply, vars.protocolSeizeTokens);\\n\\n (vars.mathErr, vars.liquidatorTokensNew) = addUInt(accountTokens[liquidator], vars.liquidatorSeizeTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(vars.mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n totalReserves = vars.totalReservesNew;\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[borrower] = vars.borrowerTokensNew;\\n accountTokens[liquidator] = vars.liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, vars.liquidatorSeizeTokens);\\n emit Transfer(borrower, address(this), vars.protocolSeizeTokens);\\n emit ReservesAdded(address(this), vars.protocolSeizeAmount, vars.totalReservesNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n\\n /*** Admin Functions ***/\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPendingAdmin(address payable newPendingAdmin) external returns (uint) {\\n // Check caller = admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\\n }\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptAdmin() external returns (uint) {\\n // Check caller is pendingAdmin and pendingAdmin \\u2260 address(0)\\n if (msg.sender != pendingAdmin || msg.sender == address(0)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = address(0);\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setComptroller(ComptrollerInterface newComptroller) public returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_COMPTROLLER_OWNER_CHECK);\\n }\\n\\n ComptrollerInterface oldComptroller = comptroller;\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(oldComptroller, newComptroller);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh\\n * @dev Admin function to accrue interest and set a new reserve factor\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setReserveFactor(uint newReserveFactorMantissa) external nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\\n * @dev Admin function to set a new reserve factor\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_RESERVE_FACTOR_ADMIN_CHECK);\\n }\\n\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring from msg.sender\\n * @param addAmount Amount of addition to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to admin\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _reduceReserves(uint reduceAmount) external nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to admin\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _reduceReservesFresh(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's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n totalReservesNew = totalReserves - reduceAmount;\\n // We checked reduceAmount <= totalReserves above, so this should never revert.\\n require(totalReservesNew <= 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't be sure if side effects occurred.\\n doTransferOut(admin, reduceAmount);\\n\\n emit ReservesReduced(admin, reduceAmount, totalReservesNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Admin function to accrue interest and update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel);\\n }\\n\\n /**\\n * @notice updates the interest rate model (*requires fresh interest accrual)\\n * @dev Admin function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal returns (uint) {\\n\\n // Used to store old model for use in the event that is emitted on success\\n InterestRateModel oldInterestRateModel;\\n\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_INTEREST_RATE_MODEL_OWNER_CHECK);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Track the market's current interest rate model\\n oldInterestRateModel = interestRateModel;\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view returns (uint);\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure tather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal;\\n\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n}\\n\",\"keccak256\":\"0x436ec2e309682995f8a82dfdd9e8f75928599c10a9a680dddbee6c275014008d\"},\"contracts/CTokenInterfaces.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./InterestRateModel.sol\\\";\\nimport \\\"./EIP20NonStandardInterface.sol\\\";\\n\\ncontract CTokenStorage {\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-cToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModel public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first CTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping (address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping (address => mapping (address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Share of seized collateral that is added to reserves\\n */\\n uint public constant protocolSeizeShareMantissa = 2.8e16; //2.8%\\n\\n}\\n\\ncontract CTokenInterface is CTokenStorage {\\n /**\\n * @notice Indicator that this is a CToken contract (for inspection)\\n */\\n bool public constant isCToken = true;\\n\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(address liquidator, address borrower, uint repayAmount, address cTokenCollateral, uint seizeTokens);\\n\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin is updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(InterestRateModel oldInterestRateModel, InterestRateModel newInterestRateModel);\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address admin, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Failure event\\n */\\n event Failure(uint error, uint info, uint detail);\\n\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external returns (bool);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function approve(address spender, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function balanceOfUnderlying(address owner) external returns (uint);\\n function getAccountSnapshot(address account) external view returns (uint, uint, uint, uint);\\n function borrowRatePerBlock() external view returns (uint);\\n function supplyRatePerBlock() external view returns (uint);\\n function totalBorrowsCurrent() external returns (uint);\\n function borrowBalanceCurrent(address account) external returns (uint);\\n function borrowBalanceStored(address account) public view returns (uint);\\n function exchangeRateCurrent() public returns (uint);\\n function exchangeRateStored() public view returns (uint);\\n function getCash() external view returns (uint);\\n function accrueInterest() public returns (uint);\\n function seize(address liquidator, address borrower, uint seizeTokens) external returns (uint);\\n\\n\\n /*** Admin Functions ***/\\n\\n function _setPendingAdmin(address payable newPendingAdmin) external returns (uint);\\n function _acceptAdmin() external returns (uint);\\n function _setComptroller(ComptrollerInterface newComptroller) public returns (uint);\\n function _setReserveFactor(uint newReserveFactorMantissa) external returns (uint);\\n function _reduceReserves(uint reduceAmount) external returns (uint);\\n function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint);\\n}\\n\\ncontract CErc20Storage {\\n /**\\n * @notice Underlying asset for this CToken\\n */\\n address public underlying;\\n}\\n\\ncontract CErc20Interface is CErc20Storage {\\n\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n function redeem(uint redeemTokens) external returns (uint);\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n function borrow(uint borrowAmount) external returns (uint);\\n function repayBorrow(uint repayAmount) external returns (uint);\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n function liquidateBorrow(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) external returns (uint);\\n function sweepToken(EIP20NonStandardInterface token) external;\\n\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ncontract CDelegationStorage {\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n}\\n\\ncontract CDelegatorInterface is CDelegationStorage {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(address implementation_, bool allowResign, bytes memory becomeImplementationData) public;\\n}\\n\\ncontract CDelegateInterface is CDelegationStorage {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) public;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() public;\\n}\\n\",\"keccak256\":\"0x963bbf60b4c0b76900b3fcb2db8c8be634934b37b4113f1055e57a308197d21a\"},\"contracts/CarefulMath.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Careful Math\\n * @author Compound\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c = a * b;\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n return (MathError.NO_ERROR, a - b);\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c = a + b;\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\",\"keccak256\":\"0x0647348f27e41d22555d99eebd217dee02a4d737df6accd7cce5347a7487c7de\"},\"contracts/ComptrollerG4.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.sol\\\";\\nimport \\\"./ErrorReporter.sol\\\";\\nimport \\\"./Exponential.sol\\\";\\nimport \\\"./PriceOracle.sol\\\";\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./ComptrollerStorage.sol\\\";\\nimport \\\"./Unitroller.sol\\\";\\nimport \\\"./Governance/Comp.sol\\\";\\n\\n/**\\n * @title Compound's Comptroller Contract\\n * @author Compound\\n */\\ncontract ComptrollerG4 is ComptrollerV3Storage, ComptrollerInterface, ComptrollerErrorReporter, Exponential {\\n /// @notice Emitted when an admin supports a market\\n event MarketListed(CToken cToken);\\n\\n /// @notice Emitted when an account enters a market\\n event MarketEntered(CToken cToken, address account);\\n\\n /// @notice Emitted when an account exits a market\\n event MarketExited(CToken cToken, 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(CToken cToken, 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 maxAssets is changed by admin\\n event NewMaxAssets(uint oldMaxAssets, uint newMaxAssets);\\n\\n /// @notice Emitted when price oracle is changed\\n event NewPriceOracle(PriceOracle oldPriceOracle, PriceOracle newPriceOracle);\\n\\n /// @notice Emitted when pause guardian is changed\\n event NewPauseGuardian(address oldPauseGuardian, address newPauseGuardian);\\n\\n /// @notice Emitted when an action is paused globally\\n event ActionPaused(string action, bool pauseState);\\n\\n /// @notice Emitted when an action is paused on a market\\n event ActionPaused(CToken cToken, string action, bool pauseState);\\n\\n /// @notice Emitted when market comped status is changed\\n event MarketComped(CToken cToken, bool isComped);\\n\\n /// @notice Emitted when COMP rate is changed\\n event NewCompRate(uint oldCompRate, uint newCompRate);\\n\\n /// @notice Emitted when a new COMP speed is calculated for a market\\n event CompSpeedUpdated(CToken indexed cToken, uint newSpeed);\\n\\n /// @notice Emitted when COMP is distributed to a supplier\\n event DistributedSupplierComp(CToken indexed cToken, address indexed supplier, uint compDelta, uint compSupplyIndex);\\n\\n /// @notice Emitted when COMP is distributed to a borrower\\n event DistributedBorrowerComp(CToken indexed cToken, address indexed borrower, uint compDelta, uint compBorrowIndex);\\n\\n /// @notice The threshold above which the flywheel transfers COMP, in wei\\n uint public constant compClaimThreshold = 0.001e18;\\n\\n /// @notice The initial COMP index for a market\\n uint224 public constant compInitialIndex = 1e36;\\n\\n // closeFactorMantissa must be strictly greater than this value\\n uint internal constant closeFactorMinMantissa = 0.05e18; // 0.05\\n\\n // closeFactorMantissa must not exceed this value\\n uint internal constant closeFactorMaxMantissa = 0.9e18; // 0.9\\n\\n // No collateralFactorMantissa may exceed this value\\n uint internal constant collateralFactorMaxMantissa = 0.9e18; // 0.9\\n\\n // liquidationIncentiveMantissa must be no less than this value\\n uint internal constant liquidationIncentiveMinMantissa = 1.0e18; // 1.0\\n\\n // liquidationIncentiveMantissa must be no greater than this value\\n uint internal constant liquidationIncentiveMaxMantissa = 1.5e18; // 1.5\\n\\n constructor() public {\\n admin = msg.sender;\\n }\\n\\n /*** Assets You Are In ***/\\n\\n /**\\n * @notice Returns the assets an account has entered\\n * @param account The address of the account to pull assets for\\n * @return A dynamic list with the assets the account has entered\\n */\\n function getAssetsIn(address account) external view returns (CToken[] memory) {\\n CToken[] memory assetsIn = accountAssets[account];\\n\\n return assetsIn;\\n }\\n\\n /**\\n * @notice Returns whether the given account is entered in the given asset\\n * @param account The address of the account to check\\n * @param cToken The cToken to check\\n * @return True if the account is in the asset, otherwise false.\\n */\\n function checkMembership(address account, CToken cToken) external view returns (bool) {\\n return markets[address(cToken)].accountMembership[account];\\n }\\n\\n /**\\n * @notice Add assets to be included in account liquidity calculation\\n * @param cTokens The list of addresses of the cToken markets to be enabled\\n * @return Success indicator for whether each corresponding market was entered\\n */\\n function enterMarkets(address[] memory cTokens) public returns (uint[] memory) {\\n uint len = cTokens.length;\\n\\n uint[] memory results = new uint[](len);\\n for (uint i = 0; i < len; i++) {\\n CToken cToken = CToken(cTokens[i]);\\n\\n results[i] = uint(addToMarketInternal(cToken, msg.sender));\\n }\\n\\n return results;\\n }\\n\\n /**\\n * @notice Add the market to the borrower's \\\"assets in\\\" for liquidity calculations\\n * @param cToken The market to enter\\n * @param borrower The address of the account to modify\\n * @return Success indicator for whether the market was entered\\n */\\n function addToMarketInternal(CToken cToken, address borrower) internal returns (Error) {\\n Market storage marketToJoin = markets[address(cToken)];\\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 if (accountAssets[borrower].length >= maxAssets) {\\n // no space, cannot join\\n return Error.TOO_MANY_ASSETS;\\n }\\n\\n // survived the gauntlet, add to list\\n // NOTE: we store these somewhat redundantly as a significant optimization\\n // this avoids having to iterate through the list for the most common use cases\\n // that is, only when we need to perform liquidity checks\\n // and not whenever we want to check if an account is in a particular market\\n marketToJoin.accountMembership[borrower] = true;\\n accountAssets[borrower].push(cToken);\\n\\n emit MarketEntered(cToken, borrower);\\n\\n return Error.NO_ERROR;\\n }\\n\\n /**\\n * @notice Removes asset from sender's 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 cTokenAddress The address of the asset to be removed\\n * @return Whether or not the account successfully exited the market\\n */\\n function exitMarket(address cTokenAddress) external returns (uint) {\\n CToken cToken = CToken(cTokenAddress);\\n /* Get sender tokensHeld and amountOwed underlying from the cToken */\\n (uint oErr, uint tokensHeld, uint amountOwed, ) = cToken.getAccountSnapshot(msg.sender);\\n require(oErr == 0, \\\"exitMarket: getAccountSnapshot failed\\\"); // semi-opaque error code\\n\\n /* Fail if the sender has a borrow balance */\\n if (amountOwed != 0) {\\n return fail(Error.NONZERO_BORROW_BALANCE, FailureInfo.EXIT_MARKET_BALANCE_OWED);\\n }\\n\\n /* Fail if the sender is not permitted to redeem all of their tokens */\\n uint allowed = redeemAllowedInternal(cTokenAddress, msg.sender, tokensHeld);\\n if (allowed != 0) {\\n return failOpaque(Error.REJECTION, FailureInfo.EXIT_MARKET_REJECTION, allowed);\\n }\\n\\n Market storage marketToExit = markets[address(cToken)];\\n\\n /* Return true if the sender is not already \\u2018in\\u2019 the market */\\n if (!marketToExit.accountMembership[msg.sender]) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Set cToken account membership to false */\\n delete marketToExit.accountMembership[msg.sender];\\n\\n /* Delete cToken from the account\\u2019s list of assets */\\n // load into memory for faster iteration\\n CToken[] memory userAssetList = accountAssets[msg.sender];\\n uint len = userAssetList.length;\\n uint assetIndex = len;\\n for (uint i = 0; i < len; i++) {\\n if (userAssetList[i] == cToken) {\\n assetIndex = i;\\n break;\\n }\\n }\\n\\n // We *must* have found the asset in the list or our redundant data structure is broken\\n assert(assetIndex < len);\\n\\n // copy last item in list to location of item to be removed, reduce length by 1\\n CToken[] storage storedList = accountAssets[msg.sender];\\n storedList[assetIndex] = storedList[storedList.length - 1];\\n storedList.length--;\\n\\n emit MarketExited(cToken, 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 cToken The market to verify the mint against\\n * @param minter The account which would get the minted tokens\\n * @param mintAmount The amount of underlying being supplied to the market in exchange for tokens\\n * @return 0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function mintAllowed(address cToken, address minter, uint mintAmount) external returns (uint) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n require(!mintGuardianPaused[cToken], \\\"mint is paused\\\");\\n\\n // Shh - currently unused\\n minter;\\n mintAmount;\\n\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n // Keep the flywheel moving\\n updateCompSupplyIndex(cToken);\\n distributeSupplierComp(cToken, minter, false);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates mint and reverts on rejection. May emit logs.\\n * @param cToken Asset being minted\\n * @param minter The address minting the tokens\\n * @param actualMintAmount The amount of the underlying asset being minted\\n * @param mintTokens The number of tokens being minted\\n */\\n function mintVerify(address cToken, address minter, uint actualMintAmount, uint mintTokens) external {\\n // Shh - currently unused\\n cToken;\\n minter;\\n actualMintAmount;\\n mintTokens;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to redeem tokens in the given market\\n * @param cToken The market to verify the redeem against\\n * @param redeemer The account which would redeem the tokens\\n * @param redeemTokens The number of cTokens to exchange for the underlying asset in the market\\n * @return 0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function redeemAllowed(address cToken, address redeemer, uint redeemTokens) external returns (uint) {\\n uint allowed = redeemAllowedInternal(cToken, redeemer, redeemTokens);\\n if (allowed != uint(Error.NO_ERROR)) {\\n return allowed;\\n }\\n\\n // Keep the flywheel moving\\n updateCompSupplyIndex(cToken);\\n distributeSupplierComp(cToken, redeemer, false);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n function redeemAllowedInternal(address cToken, address redeemer, uint redeemTokens) internal view returns (uint) {\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!markets[cToken].accountMembership[redeemer]) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n (Error err, , uint shortfall) = getHypotheticalAccountLiquidityInternal(redeemer, CToken(cToken), redeemTokens, 0);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n if (shortfall > 0) {\\n return uint(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates redeem and reverts on rejection. May emit logs.\\n * @param cToken Asset being redeemed\\n * @param redeemer The address redeeming the tokens\\n * @param redeemAmount The amount of the underlying asset being redeemed\\n * @param redeemTokens The number of tokens being redeemed\\n */\\n function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) external {\\n // Shh - currently unused\\n cToken;\\n redeemer;\\n\\n // Require tokens is zero or amount is also zero\\n if (redeemTokens == 0 && redeemAmount > 0) {\\n revert(\\\"redeemTokens zero\\\");\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to borrow the underlying asset of the given market\\n * @param cToken The market to verify the borrow against\\n * @param borrower The account which would borrow the asset\\n * @param borrowAmount The amount of underlying the account would borrow\\n * @return 0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function borrowAllowed(address cToken, address borrower, uint borrowAmount) external returns (uint) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n require(!borrowGuardianPaused[cToken], \\\"borrow is paused\\\");\\n\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n if (!markets[cToken].accountMembership[borrower]) {\\n // only cTokens may call borrowAllowed if borrower not in market\\n require(msg.sender == cToken, \\\"sender must be cToken\\\");\\n\\n // attempt to add borrower to the market\\n Error err = addToMarketInternal(CToken(msg.sender), borrower);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n\\n // it should be impossible to break the important invariant\\n assert(markets[cToken].accountMembership[borrower]);\\n }\\n\\n if (oracle.getUnderlyingPrice(CToken(cToken)) == 0) {\\n return uint(Error.PRICE_ERROR);\\n }\\n\\n (Error err, , uint shortfall) = getHypotheticalAccountLiquidityInternal(borrower, CToken(cToken), 0, borrowAmount);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n if (shortfall > 0) {\\n return uint(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n\\n // Keep the flywheel moving\\n Exp memory borrowIndex = Exp({mantissa: CToken(cToken).borrowIndex()});\\n updateCompBorrowIndex(cToken, borrowIndex);\\n distributeBorrowerComp(cToken, borrower, borrowIndex, false);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates borrow and reverts on rejection. May emit logs.\\n * @param cToken Asset whose underlying is being borrowed\\n * @param borrower The address borrowing the underlying\\n * @param borrowAmount The amount of the underlying asset requested to borrow\\n */\\n function borrowVerify(address cToken, address borrower, uint borrowAmount) external {\\n // Shh - currently unused\\n cToken;\\n borrower;\\n borrowAmount;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to repay a borrow in the given market\\n * @param cToken The market to verify the repay against\\n * @param payer The account which would repay the asset\\n * @param borrower The account which would borrowed the asset\\n * @param repayAmount The amount of the underlying asset the account would repay\\n * @return 0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function repayBorrowAllowed(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount) external returns (uint) {\\n // Shh - currently unused\\n payer;\\n borrower;\\n repayAmount;\\n\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n // Keep the flywheel moving\\n Exp memory borrowIndex = Exp({mantissa: CToken(cToken).borrowIndex()});\\n updateCompBorrowIndex(cToken, borrowIndex);\\n distributeBorrowerComp(cToken, borrower, borrowIndex, false);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates repayBorrow and reverts on rejection. May emit logs.\\n * @param cToken Asset being repaid\\n * @param payer The address repaying the borrow\\n * @param borrower The address of the borrower\\n * @param actualRepayAmount The amount of underlying being repaid\\n */\\n function repayBorrowVerify(\\n address cToken,\\n address payer,\\n address borrower,\\n uint actualRepayAmount,\\n uint borrowerIndex) external {\\n // Shh - currently unused\\n cToken;\\n payer;\\n borrower;\\n actualRepayAmount;\\n borrowerIndex;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the liquidation should be allowed to occur\\n * @param cTokenBorrowed Asset which was borrowed by the borrower\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param repayAmount The amount of underlying being repaid\\n */\\n function liquidateBorrowAllowed(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount) external returns (uint) {\\n // Shh - currently unused\\n liquidator;\\n\\n if (!markets[cTokenBorrowed].isListed || !markets[cTokenCollateral].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n /* The borrower must have shortfall in order to be liquidatable */\\n (Error err, , uint shortfall) = getAccountLiquidityInternal(borrower);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n if (shortfall == 0) {\\n return uint(Error.INSUFFICIENT_SHORTFALL);\\n }\\n\\n /* The liquidator may not repay more than what is allowed by the closeFactor */\\n uint borrowBalance = CToken(cTokenBorrowed).borrowBalanceStored(borrower);\\n (MathError mathErr, uint maxClose) = mulScalarTruncate(Exp({mantissa: closeFactorMantissa}), borrowBalance);\\n if (mathErr != MathError.NO_ERROR) {\\n return uint(Error.MATH_ERROR);\\n }\\n if (repayAmount > 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 cTokenBorrowed Asset which was borrowed by the borrower\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param actualRepayAmount The amount of underlying being repaid\\n */\\n function liquidateBorrowVerify(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint actualRepayAmount,\\n uint seizeTokens) external {\\n // Shh - currently unused\\n cTokenBorrowed;\\n cTokenCollateral;\\n liquidator;\\n borrower;\\n actualRepayAmount;\\n seizeTokens;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the seizing of assets should be allowed to occur\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param cTokenBorrowed Asset which was borrowed by the borrower\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param seizeTokens The number of collateral tokens to seize\\n */\\n function seizeAllowed(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external returns (uint) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n require(!seizeGuardianPaused, \\\"seize is paused\\\");\\n\\n // Shh - currently unused\\n seizeTokens;\\n\\n if (!markets[cTokenCollateral].isListed || !markets[cTokenBorrowed].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n if (CToken(cTokenCollateral).comptroller() != CToken(cTokenBorrowed).comptroller()) {\\n return uint(Error.COMPTROLLER_MISMATCH);\\n }\\n\\n // Keep the flywheel moving\\n updateCompSupplyIndex(cTokenCollateral);\\n distributeSupplierComp(cTokenCollateral, borrower, false);\\n distributeSupplierComp(cTokenCollateral, liquidator, false);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates seize and reverts on rejection. May emit logs.\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param cTokenBorrowed Asset which was borrowed by the borrower\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param seizeTokens The number of collateral tokens to seize\\n */\\n function seizeVerify(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external {\\n // Shh - currently unused\\n cTokenCollateral;\\n cTokenBorrowed;\\n liquidator;\\n borrower;\\n seizeTokens;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to transfer tokens in the given market\\n * @param cToken The market to verify the transfer against\\n * @param src The account which sources the tokens\\n * @param dst The account which receives the tokens\\n * @param transferTokens The number of cTokens to transfer\\n * @return 0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function transferAllowed(address cToken, address src, address dst, uint transferTokens) external returns (uint) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n require(!transferGuardianPaused, \\\"transfer is paused\\\");\\n\\n // Currently the only consideration is whether or not\\n // the src is allowed to redeem this many tokens\\n uint allowed = redeemAllowedInternal(cToken, src, transferTokens);\\n if (allowed != uint(Error.NO_ERROR)) {\\n return allowed;\\n }\\n\\n // Keep the flywheel moving\\n updateCompSupplyIndex(cToken);\\n distributeSupplierComp(cToken, src, false);\\n distributeSupplierComp(cToken, dst, false);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates transfer and reverts on rejection. May emit logs.\\n * @param cToken Asset being transferred\\n * @param src The account which sources the tokens\\n * @param dst The account which receives the tokens\\n * @param transferTokens The number of cTokens to transfer\\n */\\n function transferVerify(address cToken, address src, address dst, uint transferTokens) external {\\n // Shh - currently unused\\n cToken;\\n src;\\n dst;\\n transferTokens;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n /**\\n * @dev Local vars for avoiding stack-depth limits in calculating account liquidity.\\n * Note that `cTokenBalance` is the number of cTokens the account owns in the market,\\n * whereas `borrowBalance` is the amount of underlying that the account has borrowed.\\n */\\n struct AccountLiquidityLocalVars {\\n uint sumCollateral;\\n uint sumBorrowPlusEffects;\\n uint cTokenBalance;\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n uint oraclePriceMantissa;\\n Exp collateralFactor;\\n Exp exchangeRate;\\n Exp oraclePrice;\\n Exp tokensToDenom;\\n }\\n\\n /**\\n * @notice Determine the current account liquidity wrt collateral requirements\\n * @return (possible error code (semi-opaque),\\n account liquidity in excess of collateral requirements,\\n * account shortfall below collateral requirements)\\n */\\n function getAccountLiquidity(address account) public view returns (uint, uint, uint) {\\n (Error err, uint liquidity, uint shortfall) = getHypotheticalAccountLiquidityInternal(account, CToken(0), 0, 0);\\n\\n return (uint(err), liquidity, shortfall);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity wrt collateral requirements\\n * @return (possible error code,\\n account liquidity in excess of collateral requirements,\\n * account shortfall below collateral requirements)\\n */\\n function getAccountLiquidityInternal(address account) internal view returns (Error, uint, uint) {\\n return getHypotheticalAccountLiquidityInternal(account, CToken(0), 0, 0);\\n }\\n\\n /**\\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\\n * @param cTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @return (possible error code (semi-opaque),\\n hypothetical account liquidity in excess of collateral requirements,\\n * hypothetical account shortfall below collateral requirements)\\n */\\n function getHypotheticalAccountLiquidity(\\n address account,\\n address cTokenModify,\\n uint redeemTokens,\\n uint borrowAmount) public view returns (uint, uint, uint) {\\n (Error err, uint liquidity, uint shortfall) = getHypotheticalAccountLiquidityInternal(account, CToken(cTokenModify), 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 cTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @dev Note that we calculate the exchangeRateStored for each collateral cToken using stored data,\\n * without calculating accumulated interest.\\n * @return (possible error code,\\n hypothetical account liquidity in excess of collateral requirements,\\n * hypothetical account shortfall below collateral requirements)\\n */\\n function getHypotheticalAccountLiquidityInternal(\\n address account,\\n CToken cTokenModify,\\n uint redeemTokens,\\n uint borrowAmount) internal view returns (Error, uint, uint) {\\n\\n AccountLiquidityLocalVars memory vars; // Holds all our calculation results\\n uint oErr;\\n MathError mErr;\\n\\n // For each asset the account is in\\n CToken[] memory assets = accountAssets[account];\\n for (uint i = 0; i < assets.length; i++) {\\n CToken asset = assets[i];\\n\\n // Read the balances and exchange rate from the cToken\\n (oErr, vars.cTokenBalance, vars.borrowBalance, vars.exchangeRateMantissa) = asset.getAccountSnapshot(account);\\n if (oErr != 0) { // semi-opaque error code, we assume NO_ERROR == 0 is invariant between upgrades\\n return (Error.SNAPSHOT_ERROR, 0, 0);\\n }\\n vars.collateralFactor = Exp({mantissa: markets[address(asset)].collateralFactorMantissa});\\n vars.exchangeRate = Exp({mantissa: vars.exchangeRateMantissa});\\n\\n // Get the normalized price of the asset\\n vars.oraclePriceMantissa = oracle.getUnderlyingPrice(asset);\\n if (vars.oraclePriceMantissa == 0) {\\n return (Error.PRICE_ERROR, 0, 0);\\n }\\n vars.oraclePrice = Exp({mantissa: vars.oraclePriceMantissa});\\n\\n // Pre-compute a conversion factor from tokens -> 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 * cTokenBalance\\n (mErr, vars.sumCollateral) = mulScalarTruncateAddUInt(vars.tokensToDenom, vars.cTokenBalance, 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 cTokenModify\\n if (asset == cTokenModify) {\\n // redeem effect\\n // sumBorrowPlusEffects += tokensToDenom * redeemTokens\\n (mErr, vars.sumBorrowPlusEffects) = mulScalarTruncateAddUInt(vars.tokensToDenom, redeemTokens, vars.sumBorrowPlusEffects);\\n if (mErr != MathError.NO_ERROR) {\\n return (Error.MATH_ERROR, 0, 0);\\n }\\n\\n // borrow effect\\n // sumBorrowPlusEffects += oraclePrice * borrowAmount\\n (mErr, vars.sumBorrowPlusEffects) = mulScalarTruncateAddUInt(vars.oraclePrice, borrowAmount, vars.sumBorrowPlusEffects);\\n if (mErr != MathError.NO_ERROR) {\\n return (Error.MATH_ERROR, 0, 0);\\n }\\n }\\n }\\n\\n // These are safe, as the underflow condition is checked first\\n if (vars.sumCollateral > vars.sumBorrowPlusEffects) {\\n return (Error.NO_ERROR, vars.sumCollateral - vars.sumBorrowPlusEffects, 0);\\n } else {\\n return (Error.NO_ERROR, 0, vars.sumBorrowPlusEffects - vars.sumCollateral);\\n }\\n }\\n\\n /**\\n * @notice Calculate number of tokens of collateral asset to seize given an underlying amount\\n * @dev Used in liquidation (called in cToken.liquidateBorrowFresh)\\n * @param cTokenBorrowed The address of the borrowed cToken\\n * @param cTokenCollateral The address of the collateral cToken\\n * @param actualRepayAmount The amount of cTokenBorrowed underlying to convert into cTokenCollateral tokens\\n * @return (errorCode, number of cTokenCollateral tokens to be seized in a liquidation)\\n */\\n function liquidateCalculateSeizeTokens(address cTokenBorrowed, address cTokenCollateral, uint actualRepayAmount) external view returns (uint, uint) {\\n /* Read oracle prices for borrowed and collateral markets */\\n uint priceBorrowedMantissa = oracle.getUnderlyingPrice(CToken(cTokenBorrowed));\\n uint priceCollateralMantissa = oracle.getUnderlyingPrice(CToken(cTokenCollateral));\\n if (priceBorrowedMantissa == 0 || priceCollateralMantissa == 0) {\\n return (uint(Error.PRICE_ERROR), 0);\\n }\\n\\n /*\\n * Get the exchange rate and calculate the number of collateral tokens to seize:\\n * seizeAmount = actualRepayAmount * liquidationIncentive * priceBorrowed / priceCollateral\\n * seizeTokens = seizeAmount / exchangeRate\\n * = actualRepayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate)\\n */\\n uint exchangeRateMantissa = CToken(cTokenCollateral).exchangeRateStored(); // Note: reverts on error\\n uint seizeTokens;\\n Exp memory numerator;\\n Exp memory denominator;\\n Exp memory ratio;\\n MathError mathErr;\\n\\n (mathErr, numerator) = mulExp(liquidationIncentiveMantissa, priceBorrowedMantissa);\\n if (mathErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0);\\n }\\n\\n (mathErr, denominator) = mulExp(priceCollateralMantissa, exchangeRateMantissa);\\n if (mathErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0);\\n }\\n\\n (mathErr, ratio) = divExp(numerator, denominator);\\n if (mathErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0);\\n }\\n\\n (mathErr, seizeTokens) = mulScalarTruncate(ratio, actualRepayAmount);\\n if (mathErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0);\\n }\\n\\n return (uint(Error.NO_ERROR), seizeTokens);\\n }\\n\\n /*** Admin Functions ***/\\n\\n /**\\n * @notice Sets a new price oracle for the comptroller\\n * @dev Admin function to set a new price oracle\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPriceOracle(PriceOracle newOracle) public returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PRICE_ORACLE_OWNER_CHECK);\\n }\\n\\n // Track the old oracle for the comptroller\\n PriceOracle oldOracle = oracle;\\n\\n // Set comptroller's oracle to newOracle\\n oracle = newOracle;\\n\\n // Emit NewPriceOracle(oldOracle, newOracle)\\n emit NewPriceOracle(oldOracle, newOracle);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets the closeFactor used when liquidating borrows\\n * @dev Admin function to set closeFactor\\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\\n * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function _setCloseFactor(uint newCloseFactorMantissa) external returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_CLOSE_FACTOR_OWNER_CHECK);\\n }\\n\\n Exp memory newCloseFactorExp = Exp({mantissa: newCloseFactorMantissa});\\n Exp memory lowLimit = Exp({mantissa: closeFactorMinMantissa});\\n if (lessThanOrEqualExp(newCloseFactorExp, lowLimit)) {\\n return fail(Error.INVALID_CLOSE_FACTOR, FailureInfo.SET_CLOSE_FACTOR_VALIDATION);\\n }\\n\\n Exp memory highLimit = Exp({mantissa: closeFactorMaxMantissa});\\n if (lessThanExp(highLimit, newCloseFactorExp)) {\\n return fail(Error.INVALID_CLOSE_FACTOR, FailureInfo.SET_CLOSE_FACTOR_VALIDATION);\\n }\\n\\n uint oldCloseFactorMantissa = closeFactorMantissa;\\n closeFactorMantissa = newCloseFactorMantissa;\\n emit NewCloseFactor(oldCloseFactorMantissa, closeFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets the collateralFactor for a market\\n * @dev Admin function to set per-market collateralFactor\\n * @param cToken The market to set the factor on\\n * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18\\n * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function _setCollateralFactor(CToken cToken, 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(cToken)];\\n if (!market.isListed) {\\n return fail(Error.MARKET_NOT_LISTED, FailureInfo.SET_COLLATERAL_FACTOR_NO_EXISTS);\\n }\\n\\n Exp memory newCollateralFactorExp = Exp({mantissa: newCollateralFactorMantissa});\\n\\n // Check collateral factor <= 0.9\\n Exp memory highLimit = Exp({mantissa: collateralFactorMaxMantissa});\\n if (lessThanExp(highLimit, newCollateralFactorExp)) {\\n return fail(Error.INVALID_COLLATERAL_FACTOR, FailureInfo.SET_COLLATERAL_FACTOR_VALIDATION);\\n }\\n\\n // If collateral factor != 0, fail if price == 0\\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(cToken) == 0) {\\n return fail(Error.PRICE_ERROR, FailureInfo.SET_COLLATERAL_FACTOR_WITHOUT_PRICE);\\n }\\n\\n // Set market's collateral factor to new collateral factor, remember old value\\n uint oldCollateralFactorMantissa = market.collateralFactorMantissa;\\n market.collateralFactorMantissa = newCollateralFactorMantissa;\\n\\n // Emit event with asset, old collateral factor, and new collateral factor\\n emit NewCollateralFactor(cToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets maxAssets which controls how many markets can be entered\\n * @dev Admin function to set maxAssets\\n * @param newMaxAssets New max assets\\n * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function _setMaxAssets(uint newMaxAssets) external returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_MAX_ASSETS_OWNER_CHECK);\\n }\\n\\n uint oldMaxAssets = maxAssets;\\n maxAssets = newMaxAssets;\\n emit NewMaxAssets(oldMaxAssets, newMaxAssets);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets liquidationIncentive\\n * @dev Admin function to set liquidationIncentive\\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\\n * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function _setLiquidationIncentive(uint newLiquidationIncentiveMantissa) external returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_LIQUIDATION_INCENTIVE_OWNER_CHECK);\\n }\\n\\n // Check de-scaled min <= newLiquidationIncentive <= max\\n Exp memory newLiquidationIncentive = Exp({mantissa: newLiquidationIncentiveMantissa});\\n Exp memory minLiquidationIncentive = Exp({mantissa: liquidationIncentiveMinMantissa});\\n if (lessThanExp(newLiquidationIncentive, minLiquidationIncentive)) {\\n return fail(Error.INVALID_LIQUIDATION_INCENTIVE, FailureInfo.SET_LIQUIDATION_INCENTIVE_VALIDATION);\\n }\\n\\n Exp memory maxLiquidationIncentive = Exp({mantissa: liquidationIncentiveMaxMantissa});\\n if (lessThanExp(maxLiquidationIncentive, newLiquidationIncentive)) {\\n return fail(Error.INVALID_LIQUIDATION_INCENTIVE, FailureInfo.SET_LIQUIDATION_INCENTIVE_VALIDATION);\\n }\\n\\n // Save current value for use in log\\n uint oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa;\\n\\n // Set liquidation incentive to new incentive\\n liquidationIncentiveMantissa = newLiquidationIncentiveMantissa;\\n\\n // Emit event with old incentive, new incentive\\n emit NewLiquidationIncentive(oldLiquidationIncentiveMantissa, newLiquidationIncentiveMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Add the market to the markets mapping and set it as listed\\n * @dev Admin function to set isListed and add support for the market\\n * @param cToken The address of the market (token) to list\\n * @return uint 0=success, otherwise a failure. (See enum Error for details)\\n */\\n function _supportMarket(CToken cToken) external returns (uint) {\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SUPPORT_MARKET_OWNER_CHECK);\\n }\\n\\n if (markets[address(cToken)].isListed) {\\n return fail(Error.MARKET_ALREADY_LISTED, FailureInfo.SUPPORT_MARKET_EXISTS);\\n }\\n\\n cToken.isCToken(); // Sanity check to make sure its really a CToken\\n\\n markets[address(cToken)] = Market({isListed: true, isComped: false, collateralFactorMantissa: 0});\\n\\n _addMarketInternal(address(cToken));\\n\\n emit MarketListed(cToken);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n function _addMarketInternal(address cToken) internal {\\n for (uint i = 0; i < allMarkets.length; i ++) {\\n require(allMarkets[i] != CToken(cToken), \\\"market already added\\\");\\n }\\n allMarkets.push(CToken(cToken));\\n }\\n\\n /**\\n * @notice Admin function to change the Pause Guardian\\n * @param newPauseGuardian The address of the new Pause Guardian\\n * @return uint 0=success, otherwise a failure. (See enum Error for details)\\n */\\n function _setPauseGuardian(address newPauseGuardian) public returns (uint) {\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PAUSE_GUARDIAN_OWNER_CHECK);\\n }\\n\\n // Save current value for inclusion in log\\n address oldPauseGuardian = pauseGuardian;\\n\\n // Store pauseGuardian with value newPauseGuardian\\n pauseGuardian = newPauseGuardian;\\n\\n // Emit NewPauseGuardian(OldPauseGuardian, NewPauseGuardian)\\n emit NewPauseGuardian(oldPauseGuardian, pauseGuardian);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n function _setMintPaused(CToken cToken, bool state) public returns (bool) {\\n require(markets[address(cToken)].isListed, \\\"cannot pause a market that is not listed\\\");\\n require(msg.sender == pauseGuardian || msg.sender == admin, \\\"only pause guardian and admin can pause\\\");\\n require(msg.sender == admin || state == true, \\\"only admin can unpause\\\");\\n\\n mintGuardianPaused[address(cToken)] = state;\\n emit ActionPaused(cToken, \\\"Mint\\\", state);\\n return state;\\n }\\n\\n function _setBorrowPaused(CToken cToken, bool state) public returns (bool) {\\n require(markets[address(cToken)].isListed, \\\"cannot pause a market that is not listed\\\");\\n require(msg.sender == pauseGuardian || msg.sender == admin, \\\"only pause guardian and admin can pause\\\");\\n require(msg.sender == admin || state == true, \\\"only admin can unpause\\\");\\n\\n borrowGuardianPaused[address(cToken)] = state;\\n emit ActionPaused(cToken, \\\"Borrow\\\", state);\\n return state;\\n }\\n\\n function _setTransferPaused(bool state) public returns (bool) {\\n require(msg.sender == pauseGuardian || msg.sender == admin, \\\"only pause guardian and admin can pause\\\");\\n require(msg.sender == admin || state == true, \\\"only admin can unpause\\\");\\n\\n transferGuardianPaused = state;\\n emit ActionPaused(\\\"Transfer\\\", state);\\n return state;\\n }\\n\\n function _setSeizePaused(bool state) public returns (bool) {\\n require(msg.sender == pauseGuardian || msg.sender == admin, \\\"only pause guardian and admin can pause\\\");\\n require(msg.sender == admin || state == true, \\\"only admin can unpause\\\");\\n\\n seizeGuardianPaused = state;\\n emit ActionPaused(\\\"Seize\\\", state);\\n return state;\\n }\\n\\n function _become(Unitroller unitroller) public {\\n require(msg.sender == unitroller.admin(), \\\"only unitroller admin can change brains\\\");\\n require(unitroller._acceptImplementation() == 0, \\\"change not authorized\\\");\\n }\\n\\n /**\\n * @notice Checks caller is admin, or this contract is becoming the new implementation\\n */\\n function adminOrInitializing() internal view returns (bool) {\\n return msg.sender == admin || msg.sender == comptrollerImplementation;\\n }\\n\\n /*** Comp Distribution ***/\\n\\n /**\\n * @notice Recalculate and update COMP speeds for all COMP markets\\n */\\n function refreshCompSpeeds() public {\\n require(msg.sender == tx.origin, \\\"only externally owned accounts may refresh speeds\\\");\\n refreshCompSpeedsInternal();\\n }\\n\\n function refreshCompSpeedsInternal() internal {\\n CToken[] memory allMarkets_ = allMarkets;\\n\\n for (uint i = 0; i < allMarkets_.length; i++) {\\n CToken cToken = allMarkets_[i];\\n Exp memory borrowIndex = Exp({mantissa: cToken.borrowIndex()});\\n updateCompSupplyIndex(address(cToken));\\n updateCompBorrowIndex(address(cToken), borrowIndex);\\n }\\n\\n Exp memory totalUtility = Exp({mantissa: 0});\\n Exp[] memory utilities = new Exp[](allMarkets_.length);\\n for (uint i = 0; i < allMarkets_.length; i++) {\\n CToken cToken = allMarkets_[i];\\n if (markets[address(cToken)].isComped) {\\n Exp memory assetPrice = Exp({mantissa: oracle.getUnderlyingPrice(cToken)});\\n Exp memory utility = mul_(assetPrice, cToken.totalBorrows());\\n utilities[i] = utility;\\n totalUtility = add_(totalUtility, utility);\\n }\\n }\\n\\n for (uint i = 0; i < allMarkets_.length; i++) {\\n CToken cToken = allMarkets[i];\\n uint newSpeed = totalUtility.mantissa > 0 ? mul_(compRate, div_(utilities[i], totalUtility)) : 0;\\n compSpeeds[address(cToken)] = newSpeed;\\n emit CompSpeedUpdated(cToken, newSpeed);\\n }\\n }\\n\\n /**\\n * @notice Accrue COMP to the market by updating the supply index\\n * @param cToken The market whose supply index to update\\n */\\n function updateCompSupplyIndex(address cToken) internal {\\n CompMarketState storage supplyState = compSupplyState[cToken];\\n uint supplySpeed = compSpeeds[cToken];\\n uint blockNumber = getBlockNumber();\\n uint deltaBlocks = sub_(blockNumber, uint(supplyState.block));\\n if (deltaBlocks > 0 && supplySpeed > 0) {\\n uint supplyTokens = CToken(cToken).totalSupply();\\n uint compAccrued = mul_(deltaBlocks, supplySpeed);\\n Double memory ratio = supplyTokens > 0 ? fraction(compAccrued, supplyTokens) : Double({mantissa: 0});\\n Double memory index = add_(Double({mantissa: supplyState.index}), ratio);\\n compSupplyState[cToken] = CompMarketState({\\n index: safe224(index.mantissa, \\\"new index exceeds 224 bits\\\"),\\n block: safe32(blockNumber, \\\"block number exceeds 32 bits\\\")\\n });\\n } else if (deltaBlocks > 0) {\\n supplyState.block = safe32(blockNumber, \\\"block number exceeds 32 bits\\\");\\n }\\n }\\n\\n /**\\n * @notice Accrue COMP to the market by updating the borrow index\\n * @param cToken The market whose borrow index to update\\n */\\n function updateCompBorrowIndex(address cToken, Exp memory marketBorrowIndex) internal {\\n CompMarketState storage borrowState = compBorrowState[cToken];\\n uint borrowSpeed = compSpeeds[cToken];\\n uint blockNumber = getBlockNumber();\\n uint deltaBlocks = sub_(blockNumber, uint(borrowState.block));\\n if (deltaBlocks > 0 && borrowSpeed > 0) {\\n uint borrowAmount = div_(CToken(cToken).totalBorrows(), marketBorrowIndex);\\n uint compAccrued = mul_(deltaBlocks, borrowSpeed);\\n Double memory ratio = borrowAmount > 0 ? fraction(compAccrued, borrowAmount) : Double({mantissa: 0});\\n Double memory index = add_(Double({mantissa: borrowState.index}), ratio);\\n compBorrowState[cToken] = CompMarketState({\\n index: safe224(index.mantissa, \\\"new index exceeds 224 bits\\\"),\\n block: safe32(blockNumber, \\\"block number exceeds 32 bits\\\")\\n });\\n } else if (deltaBlocks > 0) {\\n borrowState.block = safe32(blockNumber, \\\"block number exceeds 32 bits\\\");\\n }\\n }\\n\\n /**\\n * @notice Calculate COMP accrued by a supplier and possibly transfer it to them\\n * @param cToken The market in which the supplier is interacting\\n * @param supplier The address of the supplier to distribute COMP to\\n */\\n function distributeSupplierComp(address cToken, address supplier, bool distributeAll) internal {\\n CompMarketState storage supplyState = compSupplyState[cToken];\\n Double memory supplyIndex = Double({mantissa: supplyState.index});\\n Double memory supplierIndex = Double({mantissa: compSupplierIndex[cToken][supplier]});\\n compSupplierIndex[cToken][supplier] = supplyIndex.mantissa;\\n\\n if (supplierIndex.mantissa == 0 && supplyIndex.mantissa > 0) {\\n supplierIndex.mantissa = compInitialIndex;\\n }\\n\\n Double memory deltaIndex = sub_(supplyIndex, supplierIndex);\\n uint supplierTokens = CToken(cToken).balanceOf(supplier);\\n uint supplierDelta = mul_(supplierTokens, deltaIndex);\\n uint supplierAccrued = add_(compAccrued[supplier], supplierDelta);\\n compAccrued[supplier] = transferComp(supplier, supplierAccrued, distributeAll ? 0 : compClaimThreshold);\\n emit DistributedSupplierComp(CToken(cToken), supplier, supplierDelta, supplyIndex.mantissa);\\n }\\n\\n /**\\n * @notice Calculate COMP accrued by a borrower and possibly transfer it to them\\n * @dev Borrowers will not begin to accrue until after the first interaction with the protocol.\\n * @param cToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute COMP to\\n */\\n function distributeBorrowerComp(address cToken, address borrower, Exp memory marketBorrowIndex, bool distributeAll) internal {\\n CompMarketState storage borrowState = compBorrowState[cToken];\\n Double memory borrowIndex = Double({mantissa: borrowState.index});\\n Double memory borrowerIndex = Double({mantissa: compBorrowerIndex[cToken][borrower]});\\n compBorrowerIndex[cToken][borrower] = borrowIndex.mantissa;\\n\\n if (borrowerIndex.mantissa > 0) {\\n Double memory deltaIndex = sub_(borrowIndex, borrowerIndex);\\n uint borrowerAmount = div_(CToken(cToken).borrowBalanceStored(borrower), marketBorrowIndex);\\n uint borrowerDelta = mul_(borrowerAmount, deltaIndex);\\n uint borrowerAccrued = add_(compAccrued[borrower], borrowerDelta);\\n compAccrued[borrower] = transferComp(borrower, borrowerAccrued, distributeAll ? 0 : compClaimThreshold);\\n emit DistributedBorrowerComp(CToken(cToken), borrower, borrowerDelta, borrowIndex.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Transfer COMP to the user, if they are above the threshold\\n * @dev Note: If there is not enough COMP, we do not perform the transfer all.\\n * @param user The address of the user to transfer COMP to\\n * @param userAccrued The amount of COMP to (possibly) transfer\\n * @return The amount of COMP which was NOT transferred to the user\\n */\\n function transferComp(address user, uint userAccrued, uint threshold) internal returns (uint) {\\n if (userAccrued >= threshold && userAccrued > 0) {\\n Comp comp = Comp(getCompAddress());\\n uint compRemaining = comp.balanceOf(address(this));\\n if (userAccrued <= compRemaining) {\\n comp.transfer(user, userAccrued);\\n return 0;\\n }\\n }\\n return userAccrued;\\n }\\n\\n /**\\n * @notice Claim all the comp accrued by holder in all markets\\n * @param holder The address to claim COMP for\\n */\\n function claimComp(address holder) public {\\n return claimComp(holder, allMarkets);\\n }\\n\\n /**\\n * @notice Claim all the comp accrued by holder in the specified markets\\n * @param holder The address to claim COMP for\\n * @param cTokens The list of markets to claim COMP in\\n */\\n function claimComp(address holder, CToken[] memory cTokens) public {\\n address[] memory holders = new address[](1);\\n holders[0] = holder;\\n claimComp(holders, cTokens, true, true);\\n }\\n\\n /**\\n * @notice Claim all comp accrued by the holders\\n * @param holders The addresses to claim COMP for\\n * @param cTokens The list of markets to claim COMP in\\n * @param borrowers Whether or not to claim COMP earned by borrowing\\n * @param suppliers Whether or not to claim COMP earned by supplying\\n */\\n function claimComp(address[] memory holders, CToken[] memory cTokens, bool borrowers, bool suppliers) public {\\n for (uint i = 0; i < cTokens.length; i++) {\\n CToken cToken = cTokens[i];\\n require(markets[address(cToken)].isListed, \\\"market must be listed\\\");\\n if (borrowers == true) {\\n Exp memory borrowIndex = Exp({mantissa: cToken.borrowIndex()});\\n updateCompBorrowIndex(address(cToken), borrowIndex);\\n for (uint j = 0; j < holders.length; j++) {\\n distributeBorrowerComp(address(cToken), holders[j], borrowIndex, true);\\n }\\n }\\n if (suppliers == true) {\\n updateCompSupplyIndex(address(cToken));\\n for (uint j = 0; j < holders.length; j++) {\\n distributeSupplierComp(address(cToken), holders[j], true);\\n }\\n }\\n }\\n }\\n\\n /*** Comp Distribution Admin ***/\\n\\n /**\\n * @notice Set the amount of COMP distributed per block\\n * @param compRate_ The amount of COMP wei per block to distribute\\n */\\n function _setCompRate(uint compRate_) public {\\n require(adminOrInitializing(), \\\"only admin can change comp rate\\\");\\n\\n uint oldRate = compRate;\\n compRate = compRate_;\\n emit NewCompRate(oldRate, compRate_);\\n\\n refreshCompSpeedsInternal();\\n }\\n\\n /**\\n * @notice Add markets to compMarkets, allowing them to earn COMP in the flywheel\\n * @param cTokens The addresses of the markets to add\\n */\\n function _addCompMarkets(address[] memory cTokens) public {\\n require(adminOrInitializing(), \\\"only admin can add comp market\\\");\\n\\n for (uint i = 0; i < cTokens.length; i++) {\\n _addCompMarketInternal(cTokens[i]);\\n }\\n\\n refreshCompSpeedsInternal();\\n }\\n\\n function _addCompMarketInternal(address cToken) internal {\\n Market storage market = markets[cToken];\\n require(market.isListed == true, \\\"comp market is not listed\\\");\\n require(market.isComped == false, \\\"comp market already added\\\");\\n\\n market.isComped = true;\\n emit MarketComped(CToken(cToken), true);\\n\\n if (compSupplyState[cToken].index == 0 && compSupplyState[cToken].block == 0) {\\n compSupplyState[cToken] = CompMarketState({\\n index: compInitialIndex,\\n block: safe32(getBlockNumber(), \\\"block number exceeds 32 bits\\\")\\n });\\n }\\n\\n if (compBorrowState[cToken].index == 0 && compBorrowState[cToken].block == 0) {\\n compBorrowState[cToken] = CompMarketState({\\n index: compInitialIndex,\\n block: safe32(getBlockNumber(), \\\"block number exceeds 32 bits\\\")\\n });\\n }\\n }\\n\\n /**\\n * @notice Remove a market from compMarkets, preventing it from earning COMP in the flywheel\\n * @param cToken The address of the market to drop\\n */\\n function _dropCompMarket(address cToken) public {\\n require(msg.sender == admin, \\\"only admin can drop comp market\\\");\\n\\n Market storage market = markets[cToken];\\n require(market.isComped == true, \\\"market is not a comp market\\\");\\n\\n market.isComped = false;\\n emit MarketComped(CToken(cToken), false);\\n\\n refreshCompSpeedsInternal();\\n }\\n\\n /**\\n * @notice Return all of the markets\\n * @dev The automatic getter may be used to access an individual market.\\n * @return The list of market addresses\\n */\\n function getAllMarkets() public view returns (CToken[] memory) {\\n return allMarkets;\\n }\\n\\n function getBlockNumber() public view returns (uint) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Return the address of the COMP token\\n * @return The address of COMP\\n */\\n function getCompAddress() public view returns (address) {\\n return 0xc00e94Cb662C3520282E6f5717214004A7f26888;\\n }\\n}\\n\",\"keccak256\":\"0xb78d0330a0c8697901972280103a7749d673d6b6d8084002ab4f53cc853ade4c\"},\"contracts/ComptrollerInterface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\ncontract ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n bool public constant isComptroller = true;\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata cTokens) external returns (uint[] memory);\\n function exitMarket(address cToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address cToken, address minter, uint mintAmount) external returns (uint);\\n function mintVerify(address cToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address cToken, address redeemer, uint redeemTokens) external returns (uint);\\n function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address cToken, address borrower, uint borrowAmount) external returns (uint);\\n function borrowVerify(address cToken, address borrower, uint borrowAmount) external;\\n\\n function repayBorrowAllowed(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount) external returns (uint);\\n function repayBorrowVerify(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex) external;\\n\\n function liquidateBorrowAllowed(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount) external returns (uint);\\n function liquidateBorrowVerify(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens) external;\\n\\n function seizeAllowed(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external returns (uint);\\n function seizeVerify(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external;\\n\\n function transferAllowed(address cToken, address src, address dst, uint transferTokens) external returns (uint);\\n function transferVerify(address cToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n uint repayAmount) external view returns (uint, uint);\\n}\\n\",\"keccak256\":\"0xede7670d2dd7b25d0187aecd2c28b7b5ca7d7c1bdac144fbedecf5d4bdd92a6b\"},\"contracts/ComptrollerStorage.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.sol\\\";\\nimport \\\"./PriceOracle.sol\\\";\\n\\ncontract UnitrollerAdminStorage {\\n /**\\n * @notice Administrator for this contract\\n */\\n address public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address public pendingAdmin;\\n\\n /**\\n * @notice Active brains of Unitroller\\n */\\n address public comptrollerImplementation;\\n\\n /**\\n * @notice Pending brains of Unitroller\\n */\\n address public pendingComptrollerImplementation;\\n}\\n\\ncontract ComptrollerV1Storage is UnitrollerAdminStorage {\\n\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n PriceOracle public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives\\n */\\n uint public liquidationIncentiveMantissa;\\n\\n /**\\n * @notice Max number of assets a single account can participate in (borrow or use as collateral)\\n */\\n uint public maxAssets;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\\n */\\n mapping(address => CToken[]) public accountAssets;\\n\\n}\\n\\ncontract ComptrollerV2Storage is ComptrollerV1Storage {\\n struct Market {\\n /// @notice Whether or not this market is listed\\n bool isListed;\\n\\n /**\\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\\n * For instance, 0.9 to allow borrowing 90% of collateral value.\\n * Must be between 0 and 1, and stored as a mantissa.\\n */\\n uint collateralFactorMantissa;\\n\\n /// @notice Per-market mapping of \\\"accounts in this asset\\\"\\n mapping(address => bool) accountMembership;\\n\\n /// @notice Whether or not this market receives COMP\\n bool isComped;\\n }\\n\\n /**\\n * @notice Official mapping of cTokens -> Market metadata\\n * @dev Used e.g. to determine if a market is supported\\n */\\n mapping(address => Market) public markets;\\n\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n * Actions which allow users to remove their own assets cannot be paused.\\n * Liquidation / seizing / transfer can only be paused globally, not by market.\\n */\\n address public pauseGuardian;\\n bool public _mintGuardianPaused;\\n bool public _borrowGuardianPaused;\\n bool public transferGuardianPaused;\\n bool public seizeGuardianPaused;\\n mapping(address => bool) public mintGuardianPaused;\\n mapping(address => bool) public borrowGuardianPaused;\\n}\\n\\ncontract ComptrollerV3Storage is ComptrollerV2Storage {\\n struct CompMarketState {\\n /// @notice The market's last updated compBorrowIndex or compSupplyIndex\\n uint224 index;\\n\\n /// @notice The block number the index was last updated at\\n uint32 block;\\n }\\n\\n /// @notice A list of all markets\\n CToken[] public allMarkets;\\n\\n /// @notice The rate at which the flywheel distributes COMP, per block\\n uint public compRate;\\n\\n /// @notice The portion of compRate that each market currently receives\\n mapping(address => uint) public compSpeeds;\\n\\n /// @notice The COMP market supply state for each market\\n mapping(address => CompMarketState) public compSupplyState;\\n\\n /// @notice The COMP market borrow state for each market\\n mapping(address => CompMarketState) public compBorrowState;\\n\\n /// @notice The COMP borrow index for each market for each supplier as of the last time they accrued COMP\\n mapping(address => mapping(address => uint)) public compSupplierIndex;\\n\\n /// @notice The COMP borrow index for each market for each borrower as of the last time they accrued COMP\\n mapping(address => mapping(address => uint)) public compBorrowerIndex;\\n\\n /// @notice The COMP accrued but not yet transferred to each user\\n mapping(address => uint) public compAccrued;\\n}\\n\\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\\n // @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\\n address public borrowCapGuardian;\\n\\n // @notice Borrow caps enforced by borrowAllowed for each cToken address. Defaults to zero which corresponds to unlimited borrowing.\\n mapping(address => uint) public borrowCaps;\\n}\\n\\ncontract ComptrollerV5Storage is ComptrollerV4Storage {\\n /// @notice The portion of COMP that each contributor receives per block\\n mapping(address => uint) public compContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's COMP rewards have been allocated\\n mapping(address => uint) public lastContributorBlock;\\n}\\n\",\"keccak256\":\"0x5db970485549f493618b5e36bfd4d799d4f8701a136bf71ed6e0117e1ed8c254\"},\"contracts/EIP20Interface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title ERC 20 Token Standard Interface\\n * https://eips.ethereum.org/EIPS/eip-20\\n */\\ninterface EIP20Interface {\\n function name() external view returns (string memory);\\n function symbol() external view returns (string memory);\\n function decimals() external view returns (uint8);\\n\\n /**\\n * @notice Get the total number of tokens in circulation\\n * @return The supply of tokens\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @notice Gets the balance of the specified address\\n * @param owner The address from which the balance will be retrieved\\n * @return The balance\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transfer(address dst, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferFrom(address src, address dst, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (-1 means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (-1 means infinite)\\n */\\n function allowance(address owner, address spender) external view returns (uint256 remaining);\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n}\\n\",\"keccak256\":\"0xfd8ed2eac6d0b4d9ee6b32628ba68bae17544b66f190a5f7ce0c6ad024579dc8\"},\"contracts/EIP20NonStandardInterface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title EIP20NonStandardInterface\\n * @dev Version of ERC20 with no return values for `transfer` and `transferFrom`\\n * See https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\\n */\\ninterface EIP20NonStandardInterface {\\n\\n /**\\n * @notice Get the total number of tokens in circulation\\n * @return The supply of tokens\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @notice Gets the balance of the specified address\\n * @param owner The address from which the balance will be retrieved\\n * @return The balance\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n ///\\n /// !!!!!!!!!!!!!!\\n /// !!! NOTICE !!! `transfer` does not return a value, in violation of the ERC-20 specification\\n /// !!!!!!!!!!!!!!\\n ///\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n */\\n function transfer(address dst, uint256 amount) external;\\n\\n ///\\n /// !!!!!!!!!!!!!!\\n /// !!! NOTICE !!! `transferFrom` does not return a value, in violation of the ERC-20 specification\\n /// !!!!!!!!!!!!!!\\n ///\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n */\\n function transferFrom(address src, address dst, uint256 amount) external;\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent\\n */\\n function allowance(address owner, address spender) external view returns (uint256 remaining);\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n}\\n\",\"keccak256\":\"0x9719f12e4b80b51147ac195553a198cf8b0c516e7e4d04fc324a23ed15cbafb2\"},\"contracts/ErrorReporter.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\ncontract ComptrollerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\",\"keccak256\":\"0x5179afb1071c0fd555e5c1f1d2565f72dbe1740cc3dd02f6e52037f150afc5c9\"},\"contracts/Exponential.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CarefulMath.sol\\\";\\nimport \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @dev Legacy contract for compatibility reasons with existing contracts that still use MathError\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: rational}));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({mantissa: result}));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({mantissa: result}));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: scaledMantissa}));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: descaledMantissa}));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) pure internal returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({mantissa: 0}));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({mantissa: product}));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) pure internal returns (MathError, Exp memory) {\\n return mulExp(Exp({mantissa: a}), Exp({mantissa: b}));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) pure internal returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6ff054d65a0289dbb43c9f437d6909f9cf1207c9b8f984b3cb8e97a9de76a434\"},\"contracts/ExponentialNoError.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\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 Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) pure internal returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) pure internal returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) pure internal returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) pure internal returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) pure internal returns (uint224) {\\n require(n < 2**224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) pure internal returns (uint32) {\\n require(n < 2**32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: add_(a.mantissa, b.mantissa)});\\n }\\n\\n function add_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: add_(a.mantissa, b.mantissa)});\\n }\\n\\n function add_(uint a, uint b) pure internal returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: sub_(a.mantissa, b.mantissa)});\\n }\\n\\n function sub_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: sub_(a.mantissa, b.mantissa)});\\n }\\n\\n function sub_(uint a, uint b) pure internal returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: mul_(a.mantissa, b.mantissa) / expScale});\\n }\\n\\n function mul_(Exp memory a, uint b) pure internal returns (Exp memory) {\\n return Exp({mantissa: mul_(a.mantissa, b)});\\n }\\n\\n function mul_(uint a, Exp memory b) pure internal returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: mul_(a.mantissa, b.mantissa) / doubleScale});\\n }\\n\\n function mul_(Double memory a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: mul_(a.mantissa, b)});\\n }\\n\\n function mul_(uint a, Double memory b) pure internal returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) pure internal returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) pure internal 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) pure internal returns (Exp memory) {\\n return Exp({mantissa: div_(mul_(a.mantissa, expScale), b.mantissa)});\\n }\\n\\n function div_(Exp memory a, uint b) pure internal returns (Exp memory) {\\n return Exp({mantissa: div_(a.mantissa, b)});\\n }\\n\\n function div_(uint a, Exp memory b) pure internal returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa)});\\n }\\n\\n function div_(Double memory a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(a.mantissa, b)});\\n }\\n\\n function div_(uint a, Double memory b) pure internal returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) pure internal returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(mul_(a, doubleScale), b)});\\n }\\n}\\n\",\"keccak256\":\"0x7cb184b7cee71a5e707053dfba7eebbd46f11974004028100510ccce19b6694d\"},\"contracts/Governance/Comp.sol\":{\"content\":\"pragma solidity ^0.5.16;\\npragma experimental ABIEncoderV2;\\n\\ncontract Comp {\\n /// @notice EIP-20 token name for this token\\n string public constant name = \\\"Compound\\\";\\n\\n /// @notice EIP-20 token symbol for this token\\n string public constant symbol = \\\"COMP\\\";\\n\\n /// @notice EIP-20 token decimals for this token\\n uint8 public constant decimals = 18;\\n\\n /// @notice Total number of tokens in circulation\\n uint public constant totalSupply = 10000000e18; // 10 million Comp\\n\\n /// @notice Allowance amounts on behalf of others\\n mapping (address => mapping (address => uint96)) internal allowances;\\n\\n /// @notice Official record of token balances for each account\\n mapping (address => uint96) internal balances;\\n\\n /// @notice A record of each accounts delegate\\n mapping (address => address) public delegates;\\n\\n /// @notice A checkpoint for marking number of votes from a given block\\n struct Checkpoint {\\n uint32 fromBlock;\\n uint96 votes;\\n }\\n\\n /// @notice A record of votes checkpoints for each account, by index\\n mapping (address => mapping (uint32 => Checkpoint)) public checkpoints;\\n\\n /// @notice The number of checkpoints for each account\\n mapping (address => uint32) public numCheckpoints;\\n\\n /// @notice The EIP-712 typehash for the contract's domain\\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\\\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\\\");\\n\\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\\\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\\\");\\n\\n /// @notice A record of states for signing / validating signatures\\n mapping (address => uint) public nonces;\\n\\n /// @notice An event thats emitted when an account changes its delegate\\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\\n\\n /// @notice An event thats emitted when a delegate account's vote balance changes\\n event DelegateVotesChanged(address indexed delegate, uint previousBalance, uint newBalance);\\n\\n /// @notice The standard EIP-20 transfer event\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n\\n /// @notice The standard EIP-20 approval event\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n\\n /**\\n * @notice Construct a new Comp token\\n * @param account The initial account to grant all the tokens\\n */\\n constructor(address account) public {\\n balances[account] = uint96(totalSupply);\\n emit Transfer(address(0), account, totalSupply);\\n }\\n\\n /**\\n * @notice Get the number of tokens `spender` is approved to spend on behalf of `account`\\n * @param account The address of the account holding the funds\\n * @param spender The address of the account spending the funds\\n * @return The number of tokens approved\\n */\\n function allowance(address account, address spender) external view returns (uint) {\\n return allowances[account][spender];\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param rawAmount The number of tokens that are approved (2^256-1 means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint rawAmount) external returns (bool) {\\n uint96 amount;\\n if (rawAmount == uint(-1)) {\\n amount = uint96(-1);\\n } else {\\n amount = safe96(rawAmount, \\\"Comp::approve: amount exceeds 96 bits\\\");\\n }\\n\\n allowances[msg.sender][spender] = amount;\\n\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the number of tokens held by the `account`\\n * @param account The address of the account to get the balance of\\n * @return The number of tokens held\\n */\\n function balanceOf(address account) external view returns (uint) {\\n return balances[account];\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param rawAmount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transfer(address dst, uint rawAmount) external returns (bool) {\\n uint96 amount = safe96(rawAmount, \\\"Comp::transfer: amount exceeds 96 bits\\\");\\n _transferTokens(msg.sender, dst, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param rawAmount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferFrom(address src, address dst, uint rawAmount) external returns (bool) {\\n address spender = msg.sender;\\n uint96 spenderAllowance = allowances[src][spender];\\n uint96 amount = safe96(rawAmount, \\\"Comp::approve: amount exceeds 96 bits\\\");\\n\\n if (spender != src && spenderAllowance != uint96(-1)) {\\n uint96 newAllowance = sub96(spenderAllowance, amount, \\\"Comp::transferFrom: transfer amount exceeds spender allowance\\\");\\n allowances[src][spender] = newAllowance;\\n\\n emit Approval(src, spender, newAllowance);\\n }\\n\\n _transferTokens(src, dst, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Delegate votes from `msg.sender` to `delegatee`\\n * @param delegatee The address to delegate votes to\\n */\\n function delegate(address delegatee) public {\\n return _delegate(msg.sender, delegatee);\\n }\\n\\n /**\\n * @notice Delegates votes from signatory to `delegatee`\\n * @param delegatee The address to delegate votes to\\n * @param nonce The contract state required to match the signature\\n * @param expiry The time at which to expire the signature\\n * @param v The recovery byte of the signature\\n * @param r Half of the ECDSA signature pair\\n * @param s Half of the ECDSA signature pair\\n */\\n function delegateBySig(address delegatee, uint nonce, uint expiry, uint8 v, bytes32 r, bytes32 s) public {\\n bytes32 domainSeparator = keccak256(abi.encode(DOMAIN_TYPEHASH, keccak256(bytes(name)), getChainId(), address(this)));\\n bytes32 structHash = keccak256(abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry));\\n bytes32 digest = keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash));\\n address signatory = ecrecover(digest, v, r, s);\\n require(signatory != address(0), \\\"Comp::delegateBySig: invalid signature\\\");\\n require(nonce == nonces[signatory]++, \\\"Comp::delegateBySig: invalid nonce\\\");\\n require(now <= expiry, \\\"Comp::delegateBySig: signature expired\\\");\\n return _delegate(signatory, delegatee);\\n }\\n\\n /**\\n * @notice Gets the current votes balance for `account`\\n * @param account The address to get votes balance\\n * @return The number of current votes for `account`\\n */\\n function getCurrentVotes(address account) external view returns (uint96) {\\n uint32 nCheckpoints = numCheckpoints[account];\\n return nCheckpoints > 0 ? checkpoints[account][nCheckpoints - 1].votes : 0;\\n }\\n\\n /**\\n * @notice Determine the prior number of votes for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param account The address of the account to check\\n * @param blockNumber The block number to get the vote balance at\\n * @return The number of votes the account had as of the given block\\n */\\n function getPriorVotes(address account, uint blockNumber) public view returns (uint96) {\\n require(blockNumber < block.number, \\\"Comp::getPriorVotes: not yet determined\\\");\\n\\n uint32 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (checkpoints[account][nCheckpoints - 1].fromBlock <= blockNumber) {\\n return checkpoints[account][nCheckpoints - 1].votes;\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[account][0].fromBlock > blockNumber) {\\n return 0;\\n }\\n\\n uint32 lower = 0;\\n uint32 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[account][center];\\n if (cp.fromBlock == blockNumber) {\\n return cp.votes;\\n } else if (cp.fromBlock < blockNumber) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return checkpoints[account][lower].votes;\\n }\\n\\n function _delegate(address delegator, address delegatee) internal {\\n address currentDelegate = delegates[delegator];\\n uint96 delegatorBalance = balances[delegator];\\n delegates[delegator] = delegatee;\\n\\n emit DelegateChanged(delegator, currentDelegate, delegatee);\\n\\n _moveDelegates(currentDelegate, delegatee, delegatorBalance);\\n }\\n\\n function _transferTokens(address src, address dst, uint96 amount) internal {\\n require(src != address(0), \\\"Comp::_transferTokens: cannot transfer from the zero address\\\");\\n require(dst != address(0), \\\"Comp::_transferTokens: cannot transfer to the zero address\\\");\\n\\n balances[src] = sub96(balances[src], amount, \\\"Comp::_transferTokens: transfer amount exceeds balance\\\");\\n balances[dst] = add96(balances[dst], amount, \\\"Comp::_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 && amount > 0) {\\n if (srcRep != address(0)) {\\n uint32 srcRepNum = numCheckpoints[srcRep];\\n uint96 srcRepOld = srcRepNum > 0 ? checkpoints[srcRep][srcRepNum - 1].votes : 0;\\n uint96 srcRepNew = sub96(srcRepOld, amount, \\\"Comp::_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 > 0 ? checkpoints[dstRep][dstRepNum - 1].votes : 0;\\n uint96 dstRepNew = add96(dstRepOld, amount, \\\"Comp::_moveVotes: vote amount overflows\\\");\\n _writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew);\\n }\\n }\\n }\\n\\n function _writeCheckpoint(address delegatee, uint32 nCheckpoints, uint96 oldVotes, uint96 newVotes) internal {\\n uint32 blockNumber = safe32(block.number, \\\"Comp::_writeCheckpoint: block number exceeds 32 bits\\\");\\n\\n if (nCheckpoints > 0 && checkpoints[delegatee][nCheckpoints - 1].fromBlock == blockNumber) {\\n checkpoints[delegatee][nCheckpoints - 1].votes = newVotes;\\n } else {\\n checkpoints[delegatee][nCheckpoints] = Checkpoint(blockNumber, newVotes);\\n numCheckpoints[delegatee] = nCheckpoints + 1;\\n }\\n\\n emit DelegateVotesChanged(delegatee, oldVotes, newVotes);\\n }\\n\\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\\n require(n < 2**32, errorMessage);\\n return uint32(n);\\n }\\n\\n function safe96(uint n, string memory errorMessage) internal pure returns (uint96) {\\n require(n < 2**96, errorMessage);\\n return uint96(n);\\n }\\n\\n function add96(uint96 a, uint96 b, string memory errorMessage) internal pure returns (uint96) {\\n uint96 c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub96(uint96 a, uint96 b, string memory errorMessage) internal pure returns (uint96) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function getChainId() internal pure returns (uint) {\\n uint256 chainId;\\n assembly { chainId := chainid() }\\n return chainId;\\n }\\n}\\n\",\"keccak256\":\"0x539f7158013dd91efd3ad42dc6a56e0f7aebdca06063d40ce7b6e9a981b726a3\"},\"contracts/InterestRateModel.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Compound's InterestRateModel Interface\\n * @author Compound\\n */\\ncontract InterestRateModel {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint cash, uint borrows, uint reserves) external view returns (uint);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) external view returns (uint);\\n\\n}\\n\",\"keccak256\":\"0x929282d73c79e6d700ebe79f9fafc1e414b3848acff5a56d6740afd1dc908678\"},\"contracts/PriceOracle.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.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 cToken asset\\n * @param cToken The cToken to get the underlying price of\\n * @return The underlying asset price mantissa (scaled by 1e18).\\n * Zero means the price is unavailable.\\n */\\n function getUnderlyingPrice(CToken cToken) external view returns (uint);\\n}\\n\",\"keccak256\":\"0xe79ebc23bba508eb2479e7b3340abf566da1ab62131f106aee1aac3dc53816ef\"},\"contracts/Unitroller.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ErrorReporter.sol\\\";\\nimport \\\"./ComptrollerStorage.sol\\\";\\n/**\\n * @title ComptrollerCore\\n * @dev Storage for the comptroller is at this address, while execution is delegated to the `comptrollerImplementation`.\\n * CTokens should reference this contract as their comptroller.\\n */\\ncontract Unitroller is UnitrollerAdminStorage, ComptrollerErrorReporter {\\n\\n /**\\n * @notice Emitted when pendingComptrollerImplementation is changed\\n */\\n event NewPendingImplementation(address oldPendingImplementation, address newPendingImplementation);\\n\\n /**\\n * @notice Emitted when pendingComptrollerImplementation is accepted, which means comptroller implementation is updated\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Emitted when pendingAdmin is accepted, which means admin is updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n constructor() public {\\n // Set admin to caller\\n admin = msg.sender;\\n }\\n\\n /*** Admin Functions ***/\\n function _setPendingImplementation(address newPendingImplementation) public returns (uint) {\\n\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_IMPLEMENTATION_OWNER_CHECK);\\n }\\n\\n address oldPendingImplementation = pendingComptrollerImplementation;\\n\\n pendingComptrollerImplementation = newPendingImplementation;\\n\\n emit NewPendingImplementation(oldPendingImplementation, pendingComptrollerImplementation);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts new implementation of comptroller. msg.sender must be pendingImplementation\\n * @dev Admin function for new implementation to accept it's role as implementation\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptImplementation() public returns (uint) {\\n // Check caller is pendingImplementation and pendingImplementation \\u2260 address(0)\\n if (msg.sender != pendingComptrollerImplementation || pendingComptrollerImplementation == address(0)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldImplementation = comptrollerImplementation;\\n address oldPendingImplementation = pendingComptrollerImplementation;\\n\\n comptrollerImplementation = pendingComptrollerImplementation;\\n\\n pendingComptrollerImplementation = address(0);\\n\\n emit NewImplementation(oldImplementation, comptrollerImplementation);\\n emit NewPendingImplementation(oldPendingImplementation, pendingComptrollerImplementation);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPendingAdmin(address newPendingAdmin) public returns (uint) {\\n // Check caller = admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\\n }\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptAdmin() public returns (uint) {\\n // Check caller is pendingAdmin and pendingAdmin \\u2260 address(0)\\n if (msg.sender != pendingAdmin || msg.sender == address(0)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = address(0);\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return 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 () payable external {\\n // delegate all other functions to current implementation\\n (bool success, ) = comptrollerImplementation.delegatecall(msg.data);\\n\\n assembly {\\n let free_mem_ptr := mload(0x40)\\n returndatacopy(free_mem_ptr, 0, returndatasize)\\n\\n switch success\\n case 0 { revert(free_mem_ptr, returndatasize) }\\n default { return(free_mem_ptr, returndatasize) }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x51f81451eab9d5c4849507e724f2b2c53e41f54e5359fdbeae89432a727c16df\"},\"tests/Contracts/ComptrollerScenarioG4.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"../../contracts/ComptrollerG4.sol\\\";\\n\\ncontract ComptrollerScenarioG4 is ComptrollerG4 {\\n uint public blockNumber;\\n address public compAddress;\\n\\n constructor() ComptrollerG4() public {}\\n\\n function fastForward(uint blocks) public returns (uint) {\\n blockNumber += blocks;\\n return blockNumber;\\n }\\n\\n function setBlockNumber(uint number) public {\\n blockNumber = number;\\n }\\n\\n function membershipLength(CToken cToken) public view returns (uint) {\\n return accountAssets[address(cToken)].length;\\n }\\n\\n function unlist(CToken cToken) public {\\n markets[address(cToken)].isListed = false;\\n }\\n}\\n\",\"keccak256\":\"0xf777407af8485e3e917388797ce4fae2a025c1f5c61293fdbeb2708de2cb0cf5\"}},\"version\":1}" + }, + "tests/Contracts/ComptrollerScenarioG5.sol:ComptrollerScenarioG5": { + "abi": "[{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"action\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"pauseState\",\"type\":\"bool\"}],\"name\":\"ActionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"action\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"pauseState\",\"type\":\"bool\"}],\"name\":\"ActionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSpeed\",\"type\":\"uint256\"}],\"name\":\"CompSpeedUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compBorrowIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedBorrowerComp\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"supplier\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compSupplyIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedSupplierComp\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isComped\",\"type\":\"bool\"}],\"name\":\"MarketComped\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketEntered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketExited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"MarketListed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newBorrowCap\",\"type\":\"uint256\"}],\"name\":\"NewBorrowCap\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldBorrowCapGuardian\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newBorrowCapGuardian\",\"type\":\"address\"}],\"name\":\"NewBorrowCapGuardian\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCloseFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCloseFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCollateralFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCollateralFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCompRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCompRate\",\"type\":\"uint256\"}],\"name\":\"NewCompRate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldLiquidationIncentiveMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"NewLiquidationIncentive\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMaxAssets\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMaxAssets\",\"type\":\"uint256\"}],\"name\":\"NewMaxAssets\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldPauseGuardian\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"NewPauseGuardian\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"oldPriceOracle\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"newPriceOracle\",\"type\":\"address\"}],\"name\":\"NewPriceOracle\",\"type\":\"event\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"_addCompMarkets\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract Unitroller\",\"name\":\"unitroller\",\"type\":\"address\"}],\"name\":\"_become\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"_dropCompMarket\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"newBorrowCapGuardian\",\"type\":\"address\"}],\"name\":\"_setBorrowCapGuardian\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setBorrowPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCloseFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCollateralFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"compRate_\",\"type\":\"uint256\"}],\"name\":\"_setCompRate\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"_setLiquidationIncentive\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"cTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"newBorrowCaps\",\"type\":\"uint256[]\"}],\"name\":\"_setMarketBorrowCaps\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newMaxAssets\",\"type\":\"uint256\"}],\"name\":\"_setMaxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setMintPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"_setPauseGuardian\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"newOracle\",\"type\":\"address\"}],\"name\":\"_setPriceOracle\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setSeizePaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setTransferPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"_supportMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allMarkets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"blockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"borrowCapGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"checkMembership\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"},{\"internalType\":\"contract CToken[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"holders\",\"type\":\"address[]\"},{\"internalType\":\"contract CToken[]\",\"name\":\"cTokens\",\"type\":\"address[]\"},{\"internalType\":\"bool\",\"name\":\"borrowers\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"suppliers\",\"type\":\"bool\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compAccrued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compBorrowState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compBorrowerIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compClaimThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compInitialIndex\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSupplierIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSupplyState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"enterMarkets\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenAddress\",\"type\":\"address\"}],\"name\":\"exitMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blocks\",\"type\":\"uint256\"}],\"name\":\"fastForward\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getAllMarkets\",\"outputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAssetsIn\",\"outputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getCompAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getCompMarkets\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenModify\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"getHypotheticalAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"isComptroller\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateCalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"liquidationIncentiveMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"markets\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isComped\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"membershipLength\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"mintAmount\",\"type\":\"uint256\"}],\"name\":\"mintAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualMintAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"mintTokens\",\"type\":\"uint256\"}],\"name\":\"mintVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"refreshCompSpeeds\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"repayBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowerIndex\",\"type\":\"uint256\"}],\"name\":\"repayBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"seizeGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"}],\"name\":\"setBlockNumber\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"compAddress_\",\"type\":\"address\"}],\"name\":\"setCompAddress\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"transferGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"unlist\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + "bin": "608060405234801561001057600080fd5b50600080546001600160a01b0319163317905561627880620000336000396000f3fe608060405234801561001057600080fd5b50600436106104a05760003560e01c8063731f0c2b1161026d578063bb82aa5e11610151578063da3d454c116100ce578063e875544611610092578063e875544614611307578063e9af02921461130f578063eabe7d9114611335578063ede4edd01461136b578063f851a44014611391578063fccbe7f614611399576104a0565b8063da3d454c14611269578063dce154491461129f578063dcfbc0c7146112cb578063e4028eee146112d3578063e6653f3d146112ff576104a0565b8063ca0af04311610115578063ca0af04314611111578063cc7ebdc41461113f578063ce485c5e14611165578063d02f735114611206578063d9226ced1461124c576104a0565b8063bb82aa5e14610fb7578063bdcdc25814610fbf578063bde3672d14610ffb578063c299823814611021578063c488847b146110c2576104a0565b806394b2294b116101ea578063aa900754116101ae578063aa90075414610ef3578063abfceffc14610efb578063ac0b0bb714610f71578063aee260b414610f79578063b0772d0b14610f81578063b21be7fd14610f89576104a0565b806394b2294b14610e7c5780639d1b5a0a14610e84578063a76b3fda14610e8c578063a7f0e23114610eb2578063a8c3c85014610ed6576104a0565b806387f763031161023157806387f7630314610db95780638c57804e14610dc15780638e8f294b14610de75780638ebf636414610e2f578063929fe9a114610e4e576104a0565b8063731f0c2b14610d55578063747026c914610d7b5780637d3ab61a14610d835780637dc0d1d014610d8b578063858aa5e514610d93576104a0565b80634ada90af116103945780635c778605116103115780636810dfa6116102d55780636810dfa614610b165780636a49111214610c425780636a56947e14610c5f5780636b79c38d14610c9b5780636d154ea514610ce95780636d35bf9114610d0f576104a0565b80635c778605146109905780635ec88c79146109c65780635f5af1aa146109ec5780635fc7e71e14610a12578063607ef6c114610a58576104a0565b80634fd42e17116103585780634fd42e17146108ec57806351dff9891461090957806352d84d1e1461094557806355ee1fe11461096257806357e871e714610988576104a0565b80634ada90af146108265780634bca0d8c1461082e5780634d8e5037146108545780634e79238f1461085c5780634ef4c3e1146108b6576104a0565b80632d70db78116104225780633c94786f116103e65780633c94786f1461076857806341c728b91461077057806342cbb15c146107ac57806347ef3b3b146107b45780634a58443214610800576104a0565b80632d70db78146106b2578063317b0b77146106d1578063391957d7146106ee5780633aa729b4146107145780633bcf7ec11461073a576104a0565b80631ededc91116104695780631ededc911461060057806321af45691461064257806324008a621461066657806324a3d622146106a257806326782247146106aa576104a0565b80627e3dd2146104a557806318c882a5146104c15780631c3db2e0146104ef5780631d504dc6146105a25780631d7b33d7146105c8575b600080fd5b6104ad6113b6565b604080519115158252519081900360200190f35b6104ad600480360360408110156104d757600080fd5b506001600160a01b03813516906020013515156113bb565b6105a06004803603604081101561050557600080fd5b6001600160a01b038235169190810190604081016020820135600160201b81111561052f57600080fd5b82018360208201111561054157600080fd5b803590602001918460208302840111600160201b8311171561056257600080fd5b91908080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525092955061155b945050505050565b005b6105a0600480360360208110156105b857600080fd5b50356001600160a01b03166115bd565b6105ee600480360360208110156105de57600080fd5b50356001600160a01b031661171c565b60408051918252519081900360200190f35b6105a0600480360360a081101561061657600080fd5b506001600160a01b0381358116916020810135821691604082013516906060810135906080013561172e565b61064a611735565b604080516001600160a01b039092168252519081900360200190f35b6105ee6004803603608081101561067c57600080fd5b506001600160a01b03813581169160208101358216916040820135169060600135611744565b61064a61180d565b61064a61181c565b6104ad600480360360208110156106c857600080fd5b5035151561182b565b6105ee600480360360208110156106e757600080fd5b5035611965565b6105a06004803603602081101561070457600080fd5b50356001600160a01b0316611a76565b6105a06004803603602081101561072a57600080fd5b50356001600160a01b0316611b22565b6104ad6004803603604081101561075057600080fd5b506001600160a01b0381351690602001351515611c53565b6104ad611dee565b6105a06004803603608081101561078657600080fd5b506001600160a01b03813581169160208101359091169060408101359060600135611dfe565b6105ee611e04565b6105a0600480360360c08110156107ca57600080fd5b506001600160a01b0381358116916020810135821691604082013581169160608101359091169060808101359060a00135611e0b565b6105ee6004803603602081101561081657600080fd5b50356001600160a01b0316611e13565b6105ee611e25565b6105ee6004803603602081101561084457600080fd5b50356001600160a01b0316611e2b565b6105a0611e46565b6108986004803603608081101561087257600080fd5b506001600160a01b03813581169160208101359091169060408101359060600135611e8e565b60408051938452602084019290925282820152519081900360600190f35b6105ee600480360360608110156108cc57600080fd5b506001600160a01b03813581169160208101359091169060400135611ec8565b6105ee6004803603602081101561090257600080fd5b5035611f73565b6105a06004803603608081101561091f57600080fd5b506001600160a01b03813581169160208101359091169060408101359060600135612067565b61064a6004803603602081101561095b57600080fd5b50356120bb565b6105ee6004803603602081101561097857600080fd5b50356001600160a01b03166120e2565b6105ee612169565b6105a0600480360360608110156109a657600080fd5b506001600160a01b0381358116916020810135909116906040013561216f565b610898600480360360208110156109dc57600080fd5b50356001600160a01b0316612174565b6105ee60048036036020811015610a0257600080fd5b50356001600160a01b03166121a9565b6105ee600480360360a0811015610a2857600080fd5b506001600160a01b038135811691602081013582169160408201358116916060810135909116906080013561222d565b6105a060048036036040811015610a6e57600080fd5b810190602081018135600160201b811115610a8857600080fd5b820183602082011115610a9a57600080fd5b803590602001918460208302840111600160201b83111715610abb57600080fd5b919390929091602081019035600160201b811115610ad857600080fd5b820183602082011115610aea57600080fd5b803590602001918460208302840111600160201b83111715610b0b57600080fd5b5090925090506123b4565b6105a060048036036080811015610b2c57600080fd5b810190602081018135600160201b811115610b4657600080fd5b820183602082011115610b5857600080fd5b803590602001918460208302840111600160201b83111715610b7957600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b811115610bc857600080fd5b820183602082011115610bda57600080fd5b803590602001918460208302840111600160201b83111715610bfb57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550505050803515159150602001351515612544565b6105a060048036036020811015610c5857600080fd5b50356126ed565b6105a060048036036080811015610c7557600080fd5b506001600160a01b03813581169160208101358216916040820135169060600135611dfe565b610cc160048036036020811015610cb157600080fd5b50356001600160a01b0316612791565b604080516001600160e01b03909316835263ffffffff90911660208301528051918290030190f35b6104ad60048036036020811015610cff57600080fd5b50356001600160a01b03166127bb565b6105a0600480360360a0811015610d2557600080fd5b506001600160a01b038135811691602081013582169160408201358116916060810135909116906080013561172e565b6104ad60048036036020811015610d6b57600080fd5b50356001600160a01b03166127d0565b6105ee6127e5565b61064a6127f0565b61064a6127ff565b6105a060048036036020811015610da957600080fd5b50356001600160a01b031661280e565b6104ad612830565b610cc160048036036020811015610dd757600080fd5b50356001600160a01b0316612840565b610e0d60048036036020811015610dfd57600080fd5b50356001600160a01b031661286a565b6040805193151584526020840192909252151582820152519081900360600190f35b6104ad60048036036020811015610e4557600080fd5b50351515612890565b6104ad60048036036040811015610e6457600080fd5b506001600160a01b03813581169160200135166129c9565b6105ee6129fc565b61064a612a02565b6105ee60048036036020811015610ea257600080fd5b50356001600160a01b0316612a11565b610eba612b6e565b604080516001600160e01b039092168252519081900360200190f35b6105a060048036036020811015610eec57600080fd5b5035612b81565b6105ee612b86565b610f2160048036036020811015610f1157600080fd5b50356001600160a01b0316612b8c565b60408051602080825283518183015283519192839290830191858101910280838360005b83811015610f5d578181015183820152602001610f45565b505050509050019250505060405180910390f35b6104ad612c15565b610f21612c25565b610f21612d6d565b6105ee60048036036040811015610f9f57600080fd5b506001600160a01b0381358116916020013516612dcf565b61064a612dec565b6105ee60048036036080811015610fd557600080fd5b506001600160a01b03813581169160208101358216916040820135169060600135612dfb565b6105a06004803603602081101561101157600080fd5b50356001600160a01b0316612e8f565b610f216004803603602081101561103757600080fd5b810190602081018135600160201b81111561105157600080fd5b82018360208201111561106357600080fd5b803590602001918460208302840111600160201b8311171561108457600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550612eb0945050505050565b6110f8600480360360608110156110d857600080fd5b506001600160a01b03813581169160208101359091169060400135612f47565b6040805192835260208301919091528051918290030190f35b6105ee6004803603604081101561112757600080fd5b506001600160a01b03813581169160200135166131bc565b6105ee6004803603602081101561115557600080fd5b50356001600160a01b03166131d9565b6105a06004803603602081101561117b57600080fd5b810190602081018135600160201b81111561119557600080fd5b8201836020820111156111a757600080fd5b803590602001918460208302840111600160201b831117156111c857600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295506131eb945050505050565b6105ee600480360360a081101561121c57600080fd5b506001600160a01b038135811691602081013582169160408201358116916060810135909116906080013561327d565b6105ee6004803603602081101561126257600080fd5b5035613435565b6105ee6004803603606081101561127f57600080fd5b506001600160a01b0381358116916020810135909116906040013561349e565b61064a600480360360408110156112b557600080fd5b506001600160a01b0381351690602001356138d8565b61064a61390d565b6105ee600480360360408110156112e957600080fd5b506001600160a01b03813516906020013561391c565b6104ad613acc565b6105ee613adc565b6105a06004803603602081101561132557600080fd5b50356001600160a01b0316613ae2565b6105ee6004803603606081101561134b57600080fd5b506001600160a01b03813581169160208101359091169060400135613b46565b6105ee6004803603602081101561138157600080fd5b50356001600160a01b0316613b83565b61064a613e96565b6105ee600480360360208110156113af57600080fd5b5035613ea5565b600181565b6001600160a01b03821660009081526009602052604081205460ff166114125760405162461bcd60e51b81526004018080602001828103825260288152602001806160fd6028913960400191505060405180910390fd5b600a546001600160a01b031633148061143557506000546001600160a01b031633145b6114705760405162461bcd60e51b81526004018080602001828103825260278152602001806161566027913960400191505060405180910390fd5b6000546001600160a01b031633148061148b57506001821515145b6114d5576040805162461bcd60e51b81526020600482015260166024820152756f6e6c792061646d696e2063616e20756e706175736560501b604482015290519081900360640190fd5b6001600160a01b0383166000818152600c6020908152604091829020805486151560ff199091168117909155825193845283830152606090830181905260069083015265426f72726f7760d01b6080830152517f71aec636243f9709bb0007ae15e9afb8150ab01716d75fd7573be5cc096e03b09181900360a00190a150805b92915050565b60408051600180825281830190925260609160208083019080388339019050509050828160008151811061158b57fe5b60200260200101906001600160a01b031690816001600160a01b0316815250506115b88183600180612544565b505050565b806001600160a01b031663f851a4406040518163ffffffff1660e01b815260040160206040518083038186803b1580156115f657600080fd5b505afa15801561160a573d6000803e3d6000fd5b505050506040513d602081101561162057600080fd5b50516001600160a01b031633146116685760405162461bcd60e51b815260040180806020018281038252602781526020018061621d6027913960400191505060405180910390fd5b806001600160a01b031663c1e803346040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156116a357600080fd5b505af11580156116b7573d6000803e3d6000fd5b505050506040513d60208110156116cd57600080fd5b505115611719576040805162461bcd60e51b815260206004820152601560248201527418da185b99d9481b9bdd08185d5d1a1bdc9a5e9959605a1b604482015290519081900360640190fd5b50565b600f6020526000908152604090205481565b5050505050565b6015546001600160a01b031681565b6001600160a01b03841660009081526009602052604081205460ff1661176c57506009611805565b61177461603d565b6040518060200160405280876001600160a01b031663aa5af0fd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156117b857600080fd5b505afa1580156117cc573d6000803e3d6000fd5b505050506040513d60208110156117e257600080fd5b5051905290506117f28682613eb4565b6117ff868583600061413c565b60009150505b949350505050565b600a546001600160a01b031681565b6001546001600160a01b031681565b600a546000906001600160a01b031633148061185157506000546001600160a01b031633145b61188c5760405162461bcd60e51b81526004018080602001828103825260278152602001806161566027913960400191505060405180910390fd5b6000546001600160a01b03163314806118a757506001821515145b6118f1576040805162461bcd60e51b81526020600482015260166024820152756f6e6c792061646d696e2063616e20756e706175736560501b604482015290519081900360640190fd5b600a8054831515600160b81b810260ff60b81b1990921691909117909155604080516020810192909252808252600582820152645365697a6560d81b6060830152517fef159d9a32b2472e32b098f954f3ce62d232939f1c207070b584df1814de2de09181900360800190a150805b919050565b600080546001600160a01b0316331461198b5761198460016004614326565b9050611960565b61199361603d565b5060408051602081019091528281526119aa61603d565b50604080516020810190915266b1a2bc2ec5000081526119ca828261438c565b156119e3576119da600580614326565b92505050611960565b6119eb61603d565b506040805160208101909152670c7d713b49da00008152611a0c8184614394565b15611a2657611a1c600580614326565b9350505050611960565b6005805490869055604080518281526020810188905281517f3b9670cf975d26958e754b57098eaa2ac914d8d2a31b83257997b9f346110fd9929181900390910190a160005b9695505050505050565b6000546001600160a01b03163314611abf5760405162461bcd60e51b815260040180806020018281038252602681526020018061617d6026913960400191505060405180910390fd5b601580546001600160a01b038381166001600160a01b0319831681179093556040805191909216808252602082019390935281517feda98690e518e9a05f8ec6837663e188211b2da8f4906648b323f2c1d4434e29929181900390910190a15050565b6000546001600160a01b03163314611b81576040805162461bcd60e51b815260206004820152601f60248201527f6f6e6c792061646d696e2063616e2064726f7020636f6d70206d61726b657400604482015290519081900360640190fd5b6001600160a01b0381166000908152600960205260409020600381015460ff161515600114611bf7576040805162461bcd60e51b815260206004820152601b60248201527f6d61726b6574206973206e6f74206120636f6d70206d61726b65740000000000604482015290519081900360640190fd5b60038101805460ff19169055604080516001600160a01b03841681526000602082015281517f93c1f3e36ed71139f466a4ce8c9751790e2e33f5afb2df0dcfb3aeabe55d5aa2929181900390910190a1611c4f61439b565b5050565b6001600160a01b03821660009081526009602052604081205460ff16611caa5760405162461bcd60e51b81526004018080602001828103825260288152602001806160fd6028913960400191505060405180910390fd5b600a546001600160a01b0316331480611ccd57506000546001600160a01b031633145b611d085760405162461bcd60e51b81526004018080602001828103825260278152602001806161566027913960400191505060405180910390fd5b6000546001600160a01b0316331480611d2357506001821515145b611d6d576040805162461bcd60e51b81526020600482015260166024820152756f6e6c792061646d696e2063616e20756e706175736560501b604482015290519081900360640190fd5b6001600160a01b0383166000818152600b6020908152604091829020805486151560ff199091168117909155825193845283830152606090830181905260049083015263135a5b9d60e21b6080830152517f71aec636243f9709bb0007ae15e9afb8150ab01716d75fd7573be5cc096e03b09181900360a00190a150919050565b600a54600160a01b900460ff1681565b50505050565b6017545b90565b505050505050565b60166020526000908152604090205481565b60065481565b6001600160a01b031660009081526008602052604090205490565b333214611e845760405162461bcd60e51b81526004018080602001828103825260318152602001806161256031913960400191505060405180910390fd5b611e8c61439b565b565b600080600080600080611ea38a8a8a8a614760565b925092509250826011811115611eb557fe5b95509093509150505b9450945094915050565b6001600160a01b0383166000908152600b602052604081205460ff1615611f27576040805162461bcd60e51b815260206004820152600e60248201526d1b5a5b9d081a5cc81c185d5cd95960921b604482015290519081900360640190fd5b6001600160a01b03841660009081526009602052604090205460ff16611f515760095b9050611f6c565b611f5a84614b7b565b611f6684846000614df9565b60005b90505b9392505050565b600080546001600160a01b03163314611f92576119846001600b614326565b611f9a61603d565b506040805160208101909152828152611fb161603d565b506040805160208101909152670de0b6b3a76400008152611fd28282614394565b15611fe3576119da6007600c614326565b611feb61603d565b5060408051602081019091526714d1120d7b160000815261200c8184614394565b1561201d57611a1c6007600c614326565b6006805490869055604080518281526020810188905281517faeba5a6c40a8ac138134bff1aaa65debf25971188a58804bad717f82f0ec1316929181900390910190a16000611a6c565b801580156120755750600082115b15611dfe576040805162461bcd60e51b815260206004820152601160248201527072656465656d546f6b656e73207a65726f60781b604482015290519081900360640190fd5b600d81815481106120c857fe5b6000918252602090912001546001600160a01b0316905081565b600080546001600160a01b031633146121015761198460016010614326565b600480546001600160a01b038481166001600160a01b0319831681179093556040805191909216808252602082019390935281517fd52b2b9b7e9ee655fcb95d2e5b9e0c9f69e7ef2b8e9d2d0ea78402d576d22e22929181900390910190a160009392505050565b60175481565b6115b8565b60008060008060008061218b876000806000614760565b92509250925082601181111561219d57fe5b97919650945092505050565b600080546001600160a01b031633146121c85761198460016013614326565b600a80546001600160a01b038481166001600160a01b0319831617928390556040805192821680845293909116602083015280517f0613b6ee6a04f0d09f390e4d9318894b9f6ac7fd83897cd8d18896ba579c401e9281900390910190a16000611f6c565b6001600160a01b03851660009081526009602052604081205460ff16158061226e57506001600160a01b03851660009081526009602052604090205460ff16155b1561227d5760095b90506123ab565b60008061228985614ff1565b9193509091506000905082601181111561229f57fe5b146122b9578160118111156122b057fe5b925050506123ab565b806122c55760036122b0565b6000886001600160a01b03166395dd9193876040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561231d57600080fd5b505afa158015612331573d6000803e3d6000fd5b505050506040513d602081101561234757600080fd5b505160408051602081019091526005548152909150600090819061236b9084615011565b9092509050600082600381111561237e57fe5b1461239257600b5b955050505050506123ab565b808711156123a1576011612386565b6000955050505050505b95945050505050565b6000546001600160a01b03163314806123d757506015546001600160a01b031633145b6124125760405162461bcd60e51b81526004018080602001828103825260358152602001806161a36035913960400191505060405180910390fd5b8281811580159061242257508082145b612463576040805162461bcd60e51b815260206004820152600d60248201526c1a5b9d985b1a59081a5b9c1d5d609a1b604482015290519081900360640190fd5b60005b8281101561253b5784848281811061247a57fe5b905060200201356016600089898581811061249157fe5b905060200201356001600160a01b03166001600160a01b03166001600160a01b03168152602001908152602001600020819055508686828181106124d157fe5b905060200201356001600160a01b03166001600160a01b03167f6f1951b2aad10f3fc81b86d91105b413a5b3f847a34bbc5ce1904201b14438f686868481811061251757fe5b905060200201356040518082815260200191505060405180910390a2600101612466565b50505050505050565b60005b835181101561172e57600084828151811061255e57fe5b6020908102919091018101516001600160a01b0381166000908152600990925260409091205490915060ff166125d3576040805162461bcd60e51b81526020600482015260156024820152741b585c9ad95d081b5d5cdd081899481b1a5cdd1959605a1b604482015290519081900360640190fd5b6001841515141561269b576125e661603d565b6040518060200160405280836001600160a01b031663aa5af0fd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561262a57600080fd5b505afa15801561263e573d6000803e3d6000fd5b505050506040513d602081101561265457600080fd5b5051905290506126648282613eb4565b60005b8751811015612698576126908389838151811061268057fe5b602002602001015184600161413c565b600101612667565b50505b600183151514156126e4576126af81614b7b565b60005b86518110156126e2576126da828883815181106126cb57fe5b60200260200101516001614df9565b6001016126b2565b505b50600101612547565b6126f5615065565b612746576040805162461bcd60e51b815260206004820152601f60248201527f6f6e6c792061646d696e2063616e206368616e676520636f6d70207261746500604482015290519081900360640190fd5b600e805490829055604080518281526020810184905281517fc227c9272633c3a307d9845bf2bc2509cefb20d655b5f3c1002d8e1e3f22c8b0929181900390910190a1611c4f61439b565b6010602052600090815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b600c6020526000908152604090205460ff1681565b600b6020526000908152604090205460ff1681565b66038d7ea4c6800081565b6018546001600160a01b031681565b6004546001600160a01b031681565b601880546001600160a01b0319166001600160a01b0392909216919091179055565b600a54600160b01b900460ff1681565b6011602052600090815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b60096020526000908152604090208054600182015460039092015460ff91821692911683565b600a546000906001600160a01b03163314806128b657506000546001600160a01b031633145b6128f15760405162461bcd60e51b81526004018080602001828103825260278152602001806161566027913960400191505060405180910390fd5b6000546001600160a01b031633148061290c57506001821515145b612956576040805162461bcd60e51b81526020600482015260166024820152756f6e6c792061646d696e2063616e20756e706175736560501b604482015290519081900360640190fd5b600a8054831515600160b01b810260ff60b01b1990921691909117909155604080516020810192909252808252600882820152672a3930b739b332b960c11b6060830152517fef159d9a32b2472e32b098f954f3ce62d232939f1c207070b584df1814de2de09181900360800190a15090565b6001600160a01b038082166000908152600960209081526040808320938616835260029093019052205460ff1692915050565b60075481565b6018546001600160a01b031690565b600080546001600160a01b03163314612a305761198460016012614326565b6001600160a01b03821660009081526009602052604090205460ff1615612a5d57611984600a6011614326565b816001600160a01b031663fe9c44ae6040518163ffffffff1660e01b815260040160206040518083038186803b158015612a9657600080fd5b505afa158015612aaa573d6000803e3d6000fd5b505050506040513d6020811015612ac057600080fd5b5050604080516060810182526001808252600060208381018281528486018381526001600160a01b03891684526009909252949091209251835490151560ff19918216178455935191830191909155516003909101805491151591909216179055612b2a8261508e565b604080516001600160a01b038416815290517fcf583bb0c569eb967f806b11601c4cb93c10310485c67add5f8362c2f212321f9181900360200190a1600092915050565b6ec097ce7bc90715b34b9f100000000081565b601755565b600e5481565b60608060086000846001600160a01b03166001600160a01b03168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015612c0857602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612bea575b5093979650505050505050565b600a54600160b81b900460ff1681565b600d546060906000805b82811015612c875760096000600d8381548110612c4857fe5b60009182526020808320909101546001600160a01b0316835282019290925260400190206003015460ff1615612c7f576001909101905b600101612c2f565b50606081604051908082528060200260200182016040528015612cb4578160200160208202803883390190505b5090506000805b84811015612d635760096000600d8381548110612cd457fe5b60009182526020808320909101546001600160a01b0316835282019290925260400190206003015460ff1615612d5b57600d8181548110612d1157fe5b600091825260209091200154835160018401936001600160a01b039092169185918110612d3a57fe5b60200260200101906001600160a01b031690816001600160a01b0316815250505b600101612cbb565b5090935050505090565b6060600d805480602002602001604051908101604052809291908181526020018280548015612dc557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612da7575b5050505050905090565b601260209081526000928352604080842090915290825290205481565b6002546001600160a01b031681565b600a54600090600160b01b900460ff1615612e52576040805162461bcd60e51b81526020600482015260126024820152711d1c985b9cd9995c881a5cc81c185d5cd95960721b604482015290519081900360640190fd5b6000612e5f86868561516c565b90508015612e6e579050611805565b612e7786614b7b565b612e8386866000614df9565b6117ff86856000614df9565b6001600160a01b03166000908152600960205260409020805460ff19169055565b6060600082519050606081604051908082528060200260200182016040528015612ee4578160200160208202803883390190505b50905060005b82811015612f3f576000858281518110612f0057fe5b60200260200101519050612f148133615218565b6011811115612f1f57fe5b838381518110612f2b57fe5b602090810291909101015250600101612eea565b509392505050565b600480546040805163fc57d4df60e01b81526001600160a01b038781169482019490945290516000938493849391169163fc57d4df91602480820192602092909190829003018186803b158015612f9d57600080fd5b505afa158015612fb1573d6000803e3d6000fd5b505050506040513d6020811015612fc757600080fd5b5051600480546040805163fc57d4df60e01b81526001600160a01b038a8116948201949094529051939450600093929091169163fc57d4df91602480820192602092909190829003018186803b15801561302057600080fd5b505afa158015613034573d6000803e3d6000fd5b505050506040513d602081101561304a57600080fd5b50519050811580613059575080155b1561306e57600d9350600092506131b4915050565b6000866001600160a01b031663182df0f56040518163ffffffff1660e01b815260040160206040518083038186803b1580156130a957600080fd5b505afa1580156130bd573d6000803e3d6000fd5b505050506040513d60208110156130d357600080fd5b5051905060006130e161603d565b6130e961603d565b6130f161603d565b60006130ff60065489615339565b94509050600081600381111561311157fe5b1461312d57600b5b9950600098506131b4975050505050505050565b6131378787615339565b93509050600081600381111561314957fe5b1461315557600b613119565b61315f8484615374565b92509050600081600381111561317157fe5b1461317d57600b613119565b613187828c615011565b95509050600081600381111561319957fe5b146131a557600b613119565b60009950939750505050505050505b935093915050565b601360209081526000928352604080842090915290825290205481565b60146020526000908152604090205481565b6131f3615065565b613244576040805162461bcd60e51b815260206004820152601e60248201527f6f6e6c792061646d696e2063616e2061646420636f6d70206d61726b65740000604482015290519081900360640190fd5b60005b81518110156132745761326c82828151811061325f57fe5b602002602001015161538c565b600101613247565b5061171961439b565b600a54600090600160b81b900460ff16156132d1576040805162461bcd60e51b815260206004820152600f60248201526e1cd95a5e99481a5cc81c185d5cd959608a1b604482015290519081900360640190fd5b6001600160a01b03861660009081526009602052604090205460ff16158061331257506001600160a01b03851660009081526009602052604090205460ff16155b1561331e576009612276565b846001600160a01b0316635fe3b5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561335757600080fd5b505afa15801561336b573d6000803e3d6000fd5b505050506040513d602081101561338157600080fd5b505160408051635fe3b56760e01b815290516001600160a01b0392831692891691635fe3b567916004808301926020929190829003018186803b1580156133c757600080fd5b505afa1580156133db573d6000803e3d6000fd5b505050506040513d60208110156133f157600080fd5b50516001600160a01b031614613408576002612276565b61341186614b7b565b61341d86846000614df9565b61342986856000614df9565b60009695505050505050565b600080546001600160a01b03163314613454576119846001600d614326565b6007805490839055604080518281526020810185905281517f7093cf1eb653f749c3ff531d6df7f92764536a7fa0d13530cd26e070780c32ea929181900390910190a16000611f6c565b6001600160a01b0383166000908152600c602052604081205460ff16156134ff576040805162461bcd60e51b815260206004820152601060248201526f189bdc9c9bddc81a5cc81c185d5cd95960821b604482015290519081900360640190fd5b6001600160a01b03841660009081526009602052604090205460ff16613526576009611f4a565b6001600160a01b038085166000908152600960209081526040808320938716835260029093019052205460ff1661361657336001600160a01b038516146135ac576040805162461bcd60e51b815260206004820152601560248201527439b2b73232b91036bab9ba1031329031aa37b5b2b760591b604482015290519081900360640190fd5b60006135b83385615218565b905060008160118111156135c857fe5b146135e1578060118111156135d957fe5b915050611f6c565b6001600160a01b038086166000908152600960209081526040808320938816835260029093019052205460ff1661361457fe5b505b600480546040805163fc57d4df60e01b81526001600160a01b03888116948201949094529051929091169163fc57d4df91602480820192602092909190829003018186803b15801561366757600080fd5b505afa15801561367b573d6000803e3d6000fd5b505050506040513d602081101561369157600080fd5b505161369e57600d611f4a565b6001600160a01b03841660009081526016602052604090205480156137e9576000856001600160a01b03166347bd37186040518163ffffffff1660e01b815260040160206040518083038186803b1580156136f857600080fd5b505afa15801561370c573d6000803e3d6000fd5b505050506040513d602081101561372257600080fd5b5051905060008061373383876156a7565b9092509050600082600381111561374657fe5b14613791576040805162461bcd60e51b8152602060048201526016602482015275746f74616c20626f72726f7773206f766572666c6f7760501b604482015290519081900360640190fd5b8381106137e5576040805162461bcd60e51b815260206004820152601960248201527f6d61726b657420626f72726f7720636170207265616368656400000000000000604482015290519081900360640190fd5b5050505b6000806137f98688600088614760565b9193509091506000905082601181111561380f57fe5b1461382a5781601181111561382057fe5b9350505050611f6c565b8015613837576004613820565b61383f61603d565b6040518060200160405280896001600160a01b031663aa5af0fd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561388357600080fd5b505afa158015613897573d6000803e3d6000fd5b505050506040513d60208110156138ad57600080fd5b5051905290506138bd8882613eb4565b6138ca888883600061413c565b600098975050505050505050565b600860205281600052604060002081815481106138f157fe5b6000918252602090912001546001600160a01b03169150829050565b6003546001600160a01b031681565b600080546001600160a01b031633146139425761393b60016006614326565b9050611555565b6001600160a01b0383166000908152600960205260409020805460ff166139775761396f60096007614326565b915050611555565b61397f61603d565b50604080516020810190915283815261399661603d565b506040805160208101909152670c7d713b49da000081526139b78183614394565b156139d2576139c860066008614326565b9350505050611555565b8415801590613a5b5750600480546040805163fc57d4df60e01b81526001600160a01b038a8116948201949094529051929091169163fc57d4df91602480820192602092909190829003018186803b158015613a2d57600080fd5b505afa158015613a41573d6000803e3d6000fd5b505050506040513d6020811015613a5757600080fd5b5051155b15613a6c576139c8600d6009614326565b60018301805490869055604080516001600160a01b03891681526020810183905280820188905290517f70483e6592cd5182d45ac970e05bc62cdcc90e9d8ef2c2dbe686cf383bcd7fc59181900360600190a16000979650505050505050565b600a54600160a81b900460ff1681565b60055481565b61171981600d805480602002602001604051908101604052809291908181526020018280548015613b3c57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311613b1e575b505050505061155b565b600080613b5485858561516c565b90508015613b63579050611f6c565b613b6c85614b7b565b613b7885856000614df9565b600095945050505050565b6000808290506000806000836001600160a01b031663c37f68e2336040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060806040518083038186803b158015613be457600080fd5b505afa158015613bf8573d6000803e3d6000fd5b505050506040513d6080811015613c0e57600080fd5b508051602082015160409092015190945090925090508215613c615760405162461bcd60e51b81526004018080602001828103825260258152602001806161d86025913960400191505060405180910390fd5b8015613c7e57613c73600c6002614326565b945050505050611960565b6000613c8b87338561516c565b90508015613cac57613ca0600e6003836156cd565b95505050505050611960565b6001600160a01b0385166000908152600960209081526040808320338452600281019092529091205460ff16613ceb5760009650505050505050611960565b3360009081526002820160209081526040808320805460ff191690556008825291829020805483518184028101840190945280845260609392830182828015613d5d57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311613d3f575b5050835193945083925060009150505b82811015613db257896001600160a01b0316848281518110613d8b57fe5b60200260200101516001600160a01b03161415613daa57809150613db2565b600101613d6d565b50818110613dbc57fe5b336000908152600860205260409020805481906000198101908110613ddd57fe5b9060005260206000200160009054906101000a90046001600160a01b0316818381548110613e0757fe5b600091825260209091200180546001600160a01b0319166001600160a01b03929092169190911790558054613e40826000198301616050565b50604080516001600160a01b038c16815233602082015281517fe699a64c18b07ac5b7301aa273f36a2287239eb9501d81950672794afba29a0d929181900390910190a160009c9b505050505050505050505050565b6000546001600160a01b031681565b60178054820190819055919050565b6001600160a01b0382166000908152601160209081526040808320600f9092528220549091613ee1611e04565b8354909150600090613f01908390600160e01b900463ffffffff16615733565b9050600081118015613f135750600083115b156140e2576000613f88876001600160a01b03166347bd37186040518163ffffffff1660e01b815260040160206040518083038186803b158015613f5657600080fd5b505afa158015613f6a573d6000803e3d6000fd5b505050506040513d6020811015613f8057600080fd5b50518761576d565b90506000613f96838661578b565b9050613fa061603d565b60008311613fbd5760405180602001604052806000815250613fc7565b613fc782846157cd565b9050613fd161603d565b604080516020810190915288546001600160e01b03168152613ff3908361580b565b9050604051806040016040528061404383600001516040518060400160405280601a81526020017f6e657720696e6465782065786365656473203232342062697473000000000000815250615830565b6001600160e01b0316815260200161407e886040518060400160405280601c81526020016000805160206161fd8339815191528152506158ca565b63ffffffff9081169091526001600160a01b038c166000908152601160209081526040909120835181549490920151909216600160e01b026001600160e01b039182166001600160e01b0319909416939093171691909117905550611e0b92505050565b8015611e0b57614115826040518060400160405280601c81526020016000805160206161fd8339815191528152506158ca565b845463ffffffff91909116600160e01b026001600160e01b03909116178455505050505050565b6001600160a01b038416600090815260116020526040902061415c61603d565b50604080516020810190915281546001600160e01b0316815261417d61603d565b5060408051602080820183526001600160a01b03808a16600090815260138352848120918a168082528284529481208054855286519590915291529190915580511561253b576141cb61603d565b6141d5838361591f565b90506000614264896001600160a01b03166395dd91938a6040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561423257600080fd5b505afa158015614246573d6000803e3d6000fd5b505050506040513d602081101561425c57600080fd5b50518861576d565b905060006142728284615944565b6001600160a01b038a16600090815260146020526040812054919250906142999083615973565b90506142ba8a828a6142b25766038d7ea4c680006142b5565b60005b6159a9565b6001600160a01b03808c1660008181526014602090815260409182902094909455895181518781529485015280519193928f16927f1fc3ecc087d8d2d15e23d0032af5a47059c3892d003d8e139fdcb6bb327c99a6929081900390910190a35050505050505050505050565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa083601181111561435557fe5b83601381111561436157fe5b604080519283526020830191909152600082820152519081900360600190a1826011811115611f6c57fe5b519051111590565b5190511090565b6060600d8054806020026020016040519081016040528092919081815260200182805480156143f357602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116143d5575b50939450600093505050505b81518110156144b957600082828151811061441657fe5b6020026020010151905061442861603d565b6040518060200160405280836001600160a01b031663aa5af0fd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561446c57600080fd5b505afa158015614480573d6000803e3d6000fd5b505050506040513d602081101561449657600080fd5b5051905290506144a582614b7b565b6144af8282613eb4565b50506001016143ff565b506144c261603d565b6040518060200160405280600081525090506060825160405190808252806020026020018201604052801561451157816020015b6144fe61603d565b8152602001906001900390816144f65790505b50905060005b835181101561469757600084828151811061452e57fe5b6020908102919091018101516001600160a01b0381166000908152600990925260409091206003015490915060ff161561468e5761456a61603d565b60408051602080820180845260045463fc57d4df60e01b9091526001600160a01b03868116602485015293519293849391169163fc57d4df916044808601929190818703018186803b1580156145bf57600080fd5b505afa1580156145d3573d6000803e3d6000fd5b505050506040513d60208110156145e957600080fd5b5051905290506145f761603d565b61466582846001600160a01b03166347bd37186040518163ffffffff1660e01b815260040160206040518083038186803b15801561463457600080fd5b505afa158015614648573d6000803e3d6000fd5b505050506040513d602081101561465e57600080fd5b5051615aee565b90508085858151811061467457fe5b6020026020010181905250614689868261580b565b955050505b50600101614517565b5060005b8351811015611dfe576000600d82815481106146b357fe5b600091825260208220015485516001600160a01b0390911692506146d8576000614700565b614700600e546146fb8686815181106146ed57fe5b602002602001015188615b0f565b615b42565b6001600160a01b0383166000818152600f60209081526040918290208490558151848152915193945091927f2ab93f65628379309f36cb125e90d7c902454a545c4f8b8cb0794af75c24b807929181900390910190a2505060010161469b565b600080600061476d616074565b6001600160a01b0388166000908152600860209081526040808320805482518185028101850190935280835284936060939291908301828280156147da57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116147bc575b50939450600093505050505b8151811015614b365760008282815181106147fd57fe5b60200260200101519050806001600160a01b031663c37f68e28e6040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060806040518083038186803b15801561485d57600080fd5b505afa158015614871573d6000803e3d6000fd5b505050506040513d608081101561488757600080fd5b508051602082015160408084015160609485015160808c0152938a019390935291880191909152945084156148cd5750600f975060009650869550611ebe945050505050565b60408051602080820183526001600160a01b0380851660008181526009845285902060010154845260c08b01939093528351808301855260808b0151815260e08b015260048054855163fc57d4df60e01b815291820194909452935192169263fc57d4df9260248083019392829003018186803b15801561494d57600080fd5b505afa158015614961573d6000803e3d6000fd5b505050506040513d602081101561497757600080fd5b505160a0870181905261499b5750600d975060009650869550611ebe945050505050565b604080516020810190915260a08701518152610100870181905260c087015160e08801516149c892615b5b565b610120880152935060008460038111156149de57fe5b146149fa5750600b975060009650869550611ebe945050505050565b614a1286610120015187604001518860000151615bb3565b875293506000846003811115614a2457fe5b14614a405750600b975060009650869550611ebe945050505050565b614a5886610100015187606001518860200151615bb3565b602088015293506000846003811115614a6d57fe5b14614a895750600b975060009650869550611ebe945050505050565b8b6001600160a01b0316816001600160a01b03161415614b2d57614ab78661012001518c8860200151615bb3565b602088015293506000846003811115614acc57fe5b14614ae85750600b975060009650869550611ebe945050505050565b614afc8661010001518b8860200151615bb3565b602088015293506000846003811115614b1157fe5b14614b2d5750600b975060009650869550611ebe945050505050565b506001016147e6565b50602084015184511115614b5d575050506020810151905160009450039150829050611ebe565b5050815160209092015160009550859450919091039150611ebe9050565b6001600160a01b0381166000908152601060209081526040808320600f9092528220549091614ba8611e04565b8354909150600090614bc8908390600160e01b900463ffffffff16615733565b9050600081118015614bda5750600083115b15614da0576000856001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015614c1a57600080fd5b505afa158015614c2e573d6000803e3d6000fd5b505050506040513d6020811015614c4457600080fd5b505190506000614c54838661578b565b9050614c5e61603d565b60008311614c7b5760405180602001604052806000815250614c85565b614c8582846157cd565b9050614c8f61603d565b604080516020810190915288546001600160e01b03168152614cb1908361580b565b90506040518060400160405280614d0183600001516040518060400160405280601a81526020017f6e657720696e6465782065786365656473203232342062697473000000000000815250615830565b6001600160e01b03168152602001614d3c886040518060400160405280601c81526020016000805160206161fd8339815191528152506158ca565b63ffffffff9081169091526001600160a01b038b166000908152601060209081526040909120835181549490920151909216600160e01b026001600160e01b039182166001600160e01b031990941693909317169190911790555061172e92505050565b801561172e57614dd3826040518060400160405280601c81526020016000805160206161fd8339815191528152506158ca565b845463ffffffff91909116600160e01b026001600160e01b039091161784555050505050565b6001600160a01b0383166000908152601060205260409020614e1961603d565b50604080516020810190915281546001600160e01b03168152614e3a61603d565b5060408051602080820183526001600160a01b03808916600090815260128352848120918916808252828452948120805485528651959091529152919091558051158015614e885750815115155b15614ea0576ec097ce7bc90715b34b9f100000000081525b614ea861603d565b614eb2838361591f565b90506000876001600160a01b03166370a08231886040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015614f0c57600080fd5b505afa158015614f20573d6000803e3d6000fd5b505050506040513d6020811015614f3657600080fd5b505190506000614f468284615944565b6001600160a01b03891660009081526014602052604081205491925090614f6d9083615973565b9050614f8689828a6142b25766038d7ea4c680006142b5565b6001600160a01b03808b1660008181526014602090815260409182902094909455895181518781529485015280519193928e16927f2caecd17d02f56fa897705dcc740da2d237c373f70686f4e0d9bd3bf0400ea7a929081900390910190a350505050505050505050565b6000806000615004846000806000614760565b9250925092509193909250565b600080600061501e61603d565b6150288686615c00565b9092509050600082600381111561503b57fe5b1461504c575091506000905061505e565b600061505782615c68565b9350935050505b9250929050565b600080546001600160a01b031633148061508957506002546001600160a01b031633145b905090565b60005b600d5481101561511957816001600160a01b0316600d82815481106150b257fe5b6000918252602090912001546001600160a01b03161415615111576040805162461bcd60e51b81526020600482015260146024820152731b585c9ad95d08185b1c9958591e48185919195960621b604482015290519081900360640190fd5b600101615091565b50600d80546001810182556000919091527fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb50180546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b03831660009081526009602052604081205460ff16615193576009611f4a565b6001600160a01b038085166000908152600960209081526040808320938716835260029093019052205460ff166151cb576000611f4a565b6000806151db8587866000614760565b919350909150600090508260118111156151f157fe5b1461520b5781601181111561520257fe5b92505050611f6c565b8015613429576004615202565b6001600160a01b0382166000908152600960205260408120805460ff16615243576009915050611555565b6001600160a01b038316600090815260028201602052604090205460ff16151560011415615275576000915050611555565b6007546001600160a01b038416600090815260086020526040902054106152a0576010915050611555565b6001600160a01b0380841660008181526002840160209081526040808320805460ff19166001908117909155600883528184208054918201815584529282902090920180549489166001600160a01b031990951685179055815193845283019190915280517f3ab23ab0d51cccc0c3085aec51f99228625aa1a922b3a8ca89a26b0f2027a1a59281900390910190a15060009392505050565b600061534361603d565b615369604051806020016040528086815250604051806020016040528086815250615c77565b915091509250929050565b600061537e61603d565b835183516153699190615d60565b6001600160a01b0381166000908152600960205260409020805460ff1615156001146153ff576040805162461bcd60e51b815260206004820152601960248201527f636f6d70206d61726b6574206973206e6f74206c697374656400000000000000604482015290519081900360640190fd5b600381015460ff1615615459576040805162461bcd60e51b815260206004820152601960248201527f636f6d70206d61726b657420616c726561647920616464656400000000000000604482015290519081900360640190fd5b60038101805460ff19166001908117909155604080516001600160a01b0385168152602081019290925280517f93c1f3e36ed71139f466a4ce8c9751790e2e33f5afb2df0dcfb3aeabe55d5aa29281900390910190a16001600160a01b0382166000908152601060205260409020546001600160e01b031615801561550157506001600160a01b038216600090815260106020526040902054600160e01b900463ffffffff16155b156155be5760405180604001604052806ec097ce7bc90715b34b9f10000000006001600160e01b0316815260200161556361553a611e04565b6040518060400160405280601c81526020016000805160206161fd8339815191528152506158ca565b63ffffffff9081169091526001600160a01b0384166000908152601060209081526040909120835181549490920151909216600160e01b026001600160e01b039182166001600160e01b031990941693909317169190911790555b6001600160a01b0382166000908152601160205260409020546001600160e01b031615801561561057506001600160a01b038216600090815260116020526040902054600160e01b900463ffffffff16155b15611c4f5760405180604001604052806ec097ce7bc90715b34b9f10000000006001600160e01b0316815260200161564961553a611e04565b63ffffffff9081169091526001600160a01b0384166000908152601160209081526040909120835181549490920151909216600160e01b026001600160e01b039182166001600160e01b031990941693909317169190911790555050565b6000808383018481106156bf5760009250905061505e565b50600291506000905061505e565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa08460118111156156fc57fe5b84601381111561570857fe5b604080519283526020830191909152818101859052519081900360600190a1836011811115611f6957fe5b6000611f6c8383604051806040016040528060158152602001747375627472616374696f6e20756e646572666c6f7760581b815250615e10565b6000611f6c61578484670de0b6b3a764000061578b565b8351615e6a565b6000611f6c83836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f77000000000000000000815250615e9d565b6157d561603d565b60405180602001604052806158026157fc866ec097ce7bc90715b34b9f100000000061578b565b85615e6a565b90529392505050565b61581361603d565b604051806020016040528061580285600001518560000151615973565b600081600160e01b84106158c25760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561588757818101518382015260200161586f565b50505050905090810190601f1680156158b45780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b509192915050565b600081600160201b84106158c25760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561588757818101518382015260200161586f565b61592761603d565b604051806020016040528061580285600001518560000151615733565b60006ec097ce7bc90715b34b9f100000000061596484846000015161578b565b8161596b57fe5b049392505050565b6000611f6c8383604051806040016040528060118152602001706164646974696f6e206f766572666c6f7760781b815250615f1c565b60008183101580156159bb5750600083115b15615ae65760006159ca612a02565b604080516370a0823160e01b815230600482015290519192506000916001600160a01b038416916370a08231916024808301926020929190829003018186803b158015615a1657600080fd5b505afa158015615a2a573d6000803e3d6000fd5b505050506040513d6020811015615a4057600080fd5b50519050808511615ae357816001600160a01b031663a9059cbb87876040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b158015615aab57600080fd5b505af1158015615abf573d6000803e3d6000fd5b505050506040513d6020811015615ad557600080fd5b5060009350611f6c92505050565b50505b509092915050565b615af661603d565b604051806020016040528061580285600001518561578b565b615b1761603d565b6040518060200160405280615802615b3b8660000151670de0b6b3a764000061578b565b8551615e6a565b6000670de0b6b3a764000061596484846000015161578b565b6000615b6561603d565b6000615b6f61603d565b615b798787615c77565b90925090506000826003811115615b8c57fe5b14615b9b5790925090506131b4565b615ba58186615c77565b935093505050935093915050565b6000806000615bc061603d565b615bca8787615c00565b90925090506000826003811115615bdd57fe5b14615bee57509150600090506131b4565b615ba5615bfa82615c68565b866156a7565b6000615c0a61603d565b600080615c1b866000015186615f71565b90925090506000826003811115615c2e57fe5b14615c4d5750604080516020810190915260008152909250905061505e565b60408051602081019091529081526000969095509350505050565b51670de0b6b3a7640000900490565b6000615c8161603d565b600080615c9686600001518660000151615f71565b90925090506000826003811115615ca957fe5b14615cc85750604080516020810190915260008152909250905061505e565b600080615cdd6706f05b59d3b20000846156a7565b90925090506000826003811115615cf057fe5b14615d125750604080516020810190915260008152909450925061505e915050565b600080615d2783670de0b6b3a7640000615fb0565b90925090506000826003811115615d3a57fe5b14615d4157fe5b604080516020810190915290815260009a909950975050505050505050565b6000615d6a61603d565b600080615d7f86670de0b6b3a7640000615f71565b90925090506000826003811115615d9257fe5b14615db15750604080516020810190915260008152909250905061505e565b600080615dbe8388615fb0565b90925090506000826003811115615dd157fe5b14615df35750604080516020810190915260008152909450925061505e915050565b604080516020810190915290815260009890975095505050505050565b60008184841115615e625760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561588757818101518382015260200161586f565b505050900390565b6000611f6c83836040518060400160405280600e81526020016d646976696465206279207a65726f60901b815250615fdb565b6000831580615eaa575082155b15615eb757506000611f6c565b83830283858281615ec457fe5b04148390615f135760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561588757818101518382015260200161586f565b50949350505050565b60008383018285821015615f135760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561588757818101518382015260200161586f565b60008083615f845750600090508061505e565b83830283858281615f9157fe5b0414615fa55750600291506000905061505e565b60009250905061505e565b60008082615fc4575060019050600061505e565b6000838581615fcf57fe5b04915091509250929050565b6000818361602a5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561588757818101518382015260200161586f565b5082848161603457fe5b04949350505050565b6040518060200160405280600081525090565b8154818355818111156115b8576000838152602090206115b89181019083016160de565b6040518061014001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016160b261603d565b81526020016160bf61603d565b81526020016160cc61603d565b81526020016160d961603d565b905290565b611e0891905b808211156160f857600081556001016160e4565b509056fe63616e6e6f742070617573652061206d61726b65742074686174206973206e6f74206c69737465646f6e6c792065787465726e616c6c79206f776e6564206163636f756e7473206d61792072656672657368207370656564736f6e6c7920706175736520677561726469616e20616e642061646d696e2063616e2070617573656f6e6c792061646d696e2063616e2073657420626f72726f772063617020677561726469616e6f6e6c792061646d696e206f7220626f72726f772063617020677561726469616e2063616e2073657420626f72726f772063617073657869744d61726b65743a206765744163636f756e74536e617073686f74206661696c6564626c6f636b206e756d62657220657863656564732033322062697473000000006f6e6c7920756e6974726f6c6c65722061646d696e2063616e206368616e676520627261696e73a265627a7a72315820576ee9fb98f89b212593c11bb59729e9416cb4a4b8583a2027ef7249d02c4e6b64736f6c63430005100032", + "metadata": "{\"compiler\":{\"version\":\"0.5.16+commit.9c3226ce\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"action\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"pauseState\",\"type\":\"bool\"}],\"name\":\"ActionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"action\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"pauseState\",\"type\":\"bool\"}],\"name\":\"ActionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSpeed\",\"type\":\"uint256\"}],\"name\":\"CompSpeedUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compBorrowIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedBorrowerComp\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"supplier\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compSupplyIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedSupplierComp\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isComped\",\"type\":\"bool\"}],\"name\":\"MarketComped\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketEntered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketExited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"MarketListed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newBorrowCap\",\"type\":\"uint256\"}],\"name\":\"NewBorrowCap\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldBorrowCapGuardian\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newBorrowCapGuardian\",\"type\":\"address\"}],\"name\":\"NewBorrowCapGuardian\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCloseFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCloseFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCollateralFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCollateralFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCompRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCompRate\",\"type\":\"uint256\"}],\"name\":\"NewCompRate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldLiquidationIncentiveMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"NewLiquidationIncentive\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMaxAssets\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMaxAssets\",\"type\":\"uint256\"}],\"name\":\"NewMaxAssets\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldPauseGuardian\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"NewPauseGuardian\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"oldPriceOracle\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"newPriceOracle\",\"type\":\"address\"}],\"name\":\"NewPriceOracle\",\"type\":\"event\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"_addCompMarkets\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract Unitroller\",\"name\":\"unitroller\",\"type\":\"address\"}],\"name\":\"_become\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"_dropCompMarket\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"newBorrowCapGuardian\",\"type\":\"address\"}],\"name\":\"_setBorrowCapGuardian\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setBorrowPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCloseFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCollateralFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"compRate_\",\"type\":\"uint256\"}],\"name\":\"_setCompRate\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"_setLiquidationIncentive\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"cTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"newBorrowCaps\",\"type\":\"uint256[]\"}],\"name\":\"_setMarketBorrowCaps\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newMaxAssets\",\"type\":\"uint256\"}],\"name\":\"_setMaxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setMintPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"_setPauseGuardian\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"newOracle\",\"type\":\"address\"}],\"name\":\"_setPriceOracle\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setSeizePaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setTransferPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"_supportMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allMarkets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"blockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"borrowCapGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"checkMembership\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"},{\"internalType\":\"contract CToken[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"holders\",\"type\":\"address[]\"},{\"internalType\":\"contract CToken[]\",\"name\":\"cTokens\",\"type\":\"address[]\"},{\"internalType\":\"bool\",\"name\":\"borrowers\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"suppliers\",\"type\":\"bool\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compAccrued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compBorrowState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compBorrowerIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compClaimThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compInitialIndex\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSupplierIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSupplyState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"enterMarkets\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenAddress\",\"type\":\"address\"}],\"name\":\"exitMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blocks\",\"type\":\"uint256\"}],\"name\":\"fastForward\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getAllMarkets\",\"outputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAssetsIn\",\"outputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getCompAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getCompMarkets\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenModify\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"getHypotheticalAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"isComptroller\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateCalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"liquidationIncentiveMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"markets\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isComped\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"membershipLength\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"mintAmount\",\"type\":\"uint256\"}],\"name\":\"mintAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualMintAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"mintTokens\",\"type\":\"uint256\"}],\"name\":\"mintVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"refreshCompSpeeds\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"repayBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowerIndex\",\"type\":\"uint256\"}],\"name\":\"repayBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"seizeGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"}],\"name\":\"setBlockNumber\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"compAddress_\",\"type\":\"address\"}],\"name\":\"setCompAddress\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"transferGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"unlist\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"methods\":{\"_addCompMarkets(address[])\":{\"params\":{\"cTokens\":\"The addresses of the markets to add\"}},\"_dropCompMarket(address)\":{\"params\":{\"cToken\":\"The address of the market to drop\"}},\"_setBorrowCapGuardian(address)\":{\"params\":{\"newBorrowCapGuardian\":\"The address of the new Borrow Cap Guardian\"}},\"_setCloseFactor(uint256)\":{\"details\":\"Admin function to set closeFactor\",\"params\":{\"newCloseFactorMantissa\":\"New close factor, scaled by 1e18\"},\"return\":\"uint 0=success, otherwise a failure. (See ErrorReporter for details)\"},\"_setCollateralFactor(address,uint256)\":{\"details\":\"Admin function to set per-market collateralFactor\",\"params\":{\"cToken\":\"The market to set the factor on\",\"newCollateralFactorMantissa\":\"The new collateral factor, scaled by 1e18\"},\"return\":\"uint 0=success, otherwise a failure. (See ErrorReporter for details)\"},\"_setCompRate(uint256)\":{\"params\":{\"compRate_\":\"The amount of COMP wei per block to distribute\"}},\"_setLiquidationIncentive(uint256)\":{\"details\":\"Admin function to set liquidationIncentive\",\"params\":{\"newLiquidationIncentiveMantissa\":\"New liquidationIncentive scaled by 1e18\"},\"return\":\"uint 0=success, otherwise a failure. (See ErrorReporter for details)\"},\"_setMarketBorrowCaps(address[],uint256[])\":{\"details\":\"Admin or borrowCapGuardian function to set the borrow caps. A borrow cap of 0 corresponds to unlimited borrowing.\",\"params\":{\"cTokens\":\"The addresses of the markets (tokens) to change the borrow caps for\",\"newBorrowCaps\":\"The new borrow cap values in underlying to be set. A value of 0 corresponds to unlimited borrowing.\"}},\"_setMaxAssets(uint256)\":{\"details\":\"Admin function to set maxAssets\",\"params\":{\"newMaxAssets\":\"New max assets\"},\"return\":\"uint 0=success, otherwise a failure. (See ErrorReporter for details)\"},\"_setPauseGuardian(address)\":{\"params\":{\"newPauseGuardian\":\"The address of the new Pause Guardian\"},\"return\":\"uint 0=success, otherwise a failure. (See enum Error for details)\"},\"_setPriceOracle(address)\":{\"details\":\"Admin function to set a new price oracle\",\"return\":\"uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\"},\"_supportMarket(address)\":{\"details\":\"Admin function to set isListed and add support for the market\",\"params\":{\"cToken\":\"The address of the market (token) to list\"},\"return\":\"uint 0=success, otherwise a failure. (See enum Error for details)\"},\"borrowAllowed(address,address,uint256)\":{\"params\":{\"borrowAmount\":\"The amount of underlying the account would borrow\",\"borrower\":\"The account which would borrow the asset\",\"cToken\":\"The market to verify the borrow against\"},\"return\":\"0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"borrowVerify(address,address,uint256)\":{\"params\":{\"borrowAmount\":\"The amount of the underlying asset requested to borrow\",\"borrower\":\"The address borrowing the underlying\",\"cToken\":\"Asset whose underlying is being borrowed\"}},\"checkMembership(address,address)\":{\"params\":{\"account\":\"The address of the account to check\",\"cToken\":\"The cToken to check\"},\"return\":\"True if the account is in the asset, otherwise false.\"},\"claimComp(address)\":{\"params\":{\"holder\":\"The address to claim COMP for\"}},\"claimComp(address,address[])\":{\"params\":{\"cTokens\":\"The list of markets to claim COMP in\",\"holder\":\"The address to claim COMP for\"}},\"claimComp(address[],address[],bool,bool)\":{\"params\":{\"borrowers\":\"Whether or not to claim COMP earned by borrowing\",\"cTokens\":\"The list of markets to claim COMP in\",\"holders\":\"The addresses to claim COMP for\",\"suppliers\":\"Whether or not to claim COMP earned by supplying\"}},\"enterMarkets(address[])\":{\"params\":{\"cTokens\":\"The list of addresses of the cToken markets to be enabled\"},\"return\":\"Success indicator for whether each corresponding market was entered\"},\"exitMarket(address)\":{\"details\":\"Sender must not have an outstanding borrow balance in the asset, or be providing necessary collateral for an outstanding borrow.\",\"params\":{\"cTokenAddress\":\"The address of the asset to be removed\"},\"return\":\"Whether or not the account successfully exited the market\"},\"getAccountLiquidity(address)\":{\"return\":\"(possible error code (semi-opaque), account liquidity in excess of collateral requirements, account shortfall below collateral requirements)\"},\"getAllMarkets()\":{\"details\":\"The automatic getter may be used to access an individual market.\",\"return\":\"The list of market addresses\"},\"getAssetsIn(address)\":{\"params\":{\"account\":\"The address of the account to pull assets for\"},\"return\":\"A dynamic list with the assets the account has entered\"},\"getHypotheticalAccountLiquidity(address,address,uint256,uint256)\":{\"params\":{\"account\":\"The account to determine liquidity for\",\"borrowAmount\":\"The amount of underlying to hypothetically borrow\",\"cTokenModify\":\"The market to hypothetically redeem/borrow in\",\"redeemTokens\":\"The number of tokens to hypothetically redeem\"},\"return\":\"(possible error code (semi-opaque), hypothetical account liquidity in excess of collateral requirements, hypothetical account shortfall below collateral requirements)\"},\"liquidateBorrowAllowed(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"repayAmount\":\"The amount of underlying being repaid\"}},\"liquidateBorrowVerify(address,address,address,address,uint256,uint256)\":{\"params\":{\"actualRepayAmount\":\"The amount of underlying being repaid\",\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\"}},\"liquidateCalculateSeizeTokens(address,address,uint256)\":{\"details\":\"Used in liquidation (called in cToken.liquidateBorrowFresh)\",\"params\":{\"actualRepayAmount\":\"The amount of cTokenBorrowed underlying to convert into cTokenCollateral tokens\",\"cTokenBorrowed\":\"The address of the borrowed cToken\",\"cTokenCollateral\":\"The address of the collateral cToken\"},\"return\":\"(errorCode, number of cTokenCollateral tokens to be seized in a liquidation)\"},\"mintAllowed(address,address,uint256)\":{\"params\":{\"cToken\":\"The market to verify the mint against\",\"mintAmount\":\"The amount of underlying being supplied to the market in exchange for tokens\",\"minter\":\"The account which would get the minted tokens\"},\"return\":\"0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"mintVerify(address,address,uint256,uint256)\":{\"params\":{\"actualMintAmount\":\"The amount of the underlying asset being minted\",\"cToken\":\"Asset being minted\",\"mintTokens\":\"The number of tokens being minted\",\"minter\":\"The address minting the tokens\"}},\"redeemAllowed(address,address,uint256)\":{\"params\":{\"cToken\":\"The market to verify the redeem against\",\"redeemTokens\":\"The number of cTokens to exchange for the underlying asset in the market\",\"redeemer\":\"The account which would redeem the tokens\"},\"return\":\"0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"redeemVerify(address,address,uint256,uint256)\":{\"params\":{\"cToken\":\"Asset being redeemed\",\"redeemAmount\":\"The amount of the underlying asset being redeemed\",\"redeemTokens\":\"The number of tokens being redeemed\",\"redeemer\":\"The address redeeming the tokens\"}},\"repayBorrowAllowed(address,address,address,uint256)\":{\"params\":{\"borrower\":\"The account which would borrowed the asset\",\"cToken\":\"The market to verify the repay against\",\"payer\":\"The account which would repay the asset\",\"repayAmount\":\"The amount of the underlying asset the account would repay\"},\"return\":\"0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"repayBorrowVerify(address,address,address,uint256,uint256)\":{\"params\":{\"actualRepayAmount\":\"The amount of underlying being repaid\",\"borrower\":\"The address of the borrower\",\"cToken\":\"Asset being repaid\",\"payer\":\"The address repaying the borrow\"}},\"seizeAllowed(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"seizeTokens\":\"The number of collateral tokens to seize\"}},\"seizeVerify(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"seizeTokens\":\"The number of collateral tokens to seize\"}},\"transferAllowed(address,address,address,uint256)\":{\"params\":{\"cToken\":\"The market to verify the transfer against\",\"dst\":\"The account which receives the tokens\",\"src\":\"The account which sources the tokens\",\"transferTokens\":\"The number of cTokens to transfer\"},\"return\":\"0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"transferVerify(address,address,address,uint256)\":{\"params\":{\"cToken\":\"Asset being transferred\",\"dst\":\"The account which receives the tokens\",\"src\":\"The account which sources the tokens\",\"transferTokens\":\"The number of cTokens to transfer\"}}}},\"userdoc\":{\"methods\":{\"_addCompMarkets(address[])\":{\"notice\":\"Add markets to compMarkets, allowing them to earn COMP in the flywheel\"},\"_dropCompMarket(address)\":{\"notice\":\"Remove a market from compMarkets, preventing it from earning COMP in the flywheel\"},\"_setBorrowCapGuardian(address)\":{\"notice\":\"Admin function to change the Borrow Cap Guardian\"},\"_setCloseFactor(uint256)\":{\"notice\":\"Sets the closeFactor used when liquidating borrows\"},\"_setCollateralFactor(address,uint256)\":{\"notice\":\"Sets the collateralFactor for a market\"},\"_setCompRate(uint256)\":{\"notice\":\"Set the amount of COMP distributed per block\"},\"_setLiquidationIncentive(uint256)\":{\"notice\":\"Sets liquidationIncentive\"},\"_setMarketBorrowCaps(address[],uint256[])\":{\"notice\":\"Set the given borrow caps for the given cToken markets. Borrowing that brings total borrows to or above borrow cap will revert.\"},\"_setMaxAssets(uint256)\":{\"notice\":\"Sets maxAssets which controls how many markets can be entered\"},\"_setPauseGuardian(address)\":{\"notice\":\"Admin function to change the Pause Guardian\"},\"_setPriceOracle(address)\":{\"notice\":\"Sets a new price oracle for the comptroller\"},\"_supportMarket(address)\":{\"notice\":\"Add the market to the markets mapping and set it as listed\"},\"borrowAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to borrow the underlying asset of the given market\"},\"borrowVerify(address,address,uint256)\":{\"notice\":\"Validates borrow and reverts on rejection. May emit logs.\"},\"checkMembership(address,address)\":{\"notice\":\"Returns whether the given account is entered in the given asset\"},\"claimComp(address)\":{\"notice\":\"Claim all the comp accrued by holder in all markets\"},\"claimComp(address,address[])\":{\"notice\":\"Claim all the comp accrued by holder in the specified markets\"},\"claimComp(address[],address[],bool,bool)\":{\"notice\":\"Claim all comp accrued by the holders\"},\"enterMarkets(address[])\":{\"notice\":\"Add assets to be included in account liquidity calculation\"},\"exitMarket(address)\":{\"notice\":\"Removes asset from sender's account liquidity calculation\"},\"getAccountLiquidity(address)\":{\"notice\":\"Determine the current account liquidity wrt collateral requirements\"},\"getAllMarkets()\":{\"notice\":\"Return all of the markets\"},\"getAssetsIn(address)\":{\"notice\":\"Returns the assets an account has entered\"},\"getHypotheticalAccountLiquidity(address,address,uint256,uint256)\":{\"notice\":\"Determine what the account liquidity would be if the given amounts were redeemed/borrowed\"},\"liquidateBorrowAllowed(address,address,address,address,uint256)\":{\"notice\":\"Checks if the liquidation should be allowed to occur\"},\"liquidateBorrowVerify(address,address,address,address,uint256,uint256)\":{\"notice\":\"Validates liquidateBorrow and reverts on rejection. May emit logs.\"},\"liquidateCalculateSeizeTokens(address,address,uint256)\":{\"notice\":\"Calculate number of tokens of collateral asset to seize given an underlying amount\"},\"mintAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to mint tokens in the given market\"},\"mintVerify(address,address,uint256,uint256)\":{\"notice\":\"Validates mint and reverts on rejection. May emit logs.\"},\"redeemAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to redeem tokens in the given market\"},\"redeemVerify(address,address,uint256,uint256)\":{\"notice\":\"Validates redeem and reverts on rejection. May emit logs.\"},\"refreshCompSpeeds()\":{\"notice\":\"Recalculate and update COMP speeds for all COMP markets\"},\"repayBorrowAllowed(address,address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to repay a borrow in the given market\"},\"repayBorrowVerify(address,address,address,uint256,uint256)\":{\"notice\":\"Validates repayBorrow and reverts on rejection. May emit logs.\"},\"seizeAllowed(address,address,address,address,uint256)\":{\"notice\":\"Checks if the seizing of assets should be allowed to occur\"},\"seizeVerify(address,address,address,address,uint256)\":{\"notice\":\"Validates seize and reverts on rejection. May emit logs.\"},\"transferAllowed(address,address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to transfer tokens in the given market\"},\"transferVerify(address,address,address,uint256)\":{\"notice\":\"Validates transfer and reverts on rejection. May emit logs.\"}}}},\"settings\":{\"compilationTarget\":{\"tests/Contracts/ComptrollerScenarioG5.sol\":\"ComptrollerScenarioG5\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/CToken.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./CTokenInterfaces.sol\\\";\\nimport \\\"./ErrorReporter.sol\\\";\\nimport \\\"./Exponential.sol\\\";\\nimport \\\"./EIP20Interface.sol\\\";\\nimport \\\"./InterestRateModel.sol\\\";\\n\\n/**\\n * @title Compound's CToken Contract\\n * @notice Abstract base for CTokens\\n * @author Compound\\n */\\ncontract CToken is CTokenInterface, Exponential, TokenErrorReporter {\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_) public {\\n require(msg.sender == admin, \\\"only admin may initialize the market\\\");\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = getBlockNumber();\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Transfer `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = uint(-1);\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srcTokensNew;\\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, srcTokensNew) = 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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srcTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != uint(-1)) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n // unused function\\n // comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transfer(address dst, uint256 amount) external nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferFrom(address src, address dst, uint256 amount) external nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (-1 means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool) {\\n address src = msg.sender;\\n transferAllowances[src][spender] = amount;\\n emit Approval(src, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (-1 means infinite)\\n */\\n function allowance(address owner, address spender) external view returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external returns (uint) {\\n Exp memory exchangeRate = Exp({mantissa: exchangeRateCurrent()});\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n require(mErr == MathError.NO_ERROR, \\\"balance could not be calculated\\\");\\n return balance;\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view returns (uint, uint, uint, uint) {\\n uint cTokenBalance = accountTokens[account];\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), cTokenBalance, borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @dev Function to simply retrieve block number\\n * This exists mainly for inheriting test contracts to stub this result.\\n */\\n function getBlockNumber() internal view returns (uint) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this cToken\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view returns (uint) {\\n return interestRateModel.getBorrowRate(getCashPrior(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this cToken\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view returns (uint) {\\n return interestRateModel.getSupplyRate(getCashPrior(), totalBorrows, totalReserves, reserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n require(err == MathError.NO_ERROR, \\\"borrowBalanceStored: borrowBalanceStoredInternal failed\\\");\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return (error code, the calculated balance or 0 if error code is non-zero)\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the CToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n require(err == MathError.NO_ERROR, \\\"exchangeRateStored: exchangeRateStoredInternal failed\\\");\\n return result;\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the CToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return (error code, calculated exchange rate scaled by 1e18)\\n */\\n function exchangeRateStoredInternal() internal view returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows - totalReserves) / totalSupply\\n */\\n uint totalCash = getCashPrior();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Get cash balance of this cToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage.\\n */\\n function accrueInterest() public returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = getBlockNumber();\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = getCashPrior();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n require(mathErr == MathError.NO_ERROR, \\\"could not calculate block delta\\\");\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({mantissa: borrowRateMantissa}), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(Exp({mantissa: reserveFactorMantissa}), interestAccumulated, reservesPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives cTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n struct MintLocalVars {\\n Error err;\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives cTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, 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's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the cToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of cTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.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 cTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED\\\");\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\\");\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender redeems cTokens in exchange for the underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemTokens The number of cTokens to redeem into underlying\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemInternal(uint redeemTokens) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(msg.sender, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems cTokens in exchange for a specified amount of underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemAmount The amount of underlying to receive from redeeming cTokens\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemUnderlyingInternal(uint redeemAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(msg.sender, 0, redeemAmount);\\n }\\n\\n struct RedeemLocalVars {\\n Error err;\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n /**\\n * @notice User redeems cTokens in exchange for the underlying asset\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param redeemTokensIn The number of cTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming cTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemFresh(address payable redeemer, uint redeemTokensIn, uint redeemAmountIn) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr));\\n }\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(Exp({mantissa: vars.exchangeRateMantissa}), redeemTokensIn);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(redeemAmountIn, Exp({mantissa: vars.exchangeRateMantissa}));\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REDEEM_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDEEM_FRESHNESS_CHECK);\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDEEM_TRANSFER_OUT_NOT_POSSIBLE);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We invoke doTransferOut for the redeemer and the redeemAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(redeemer, vars.redeemAmount);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n /* We call the defense hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender borrows assets from the protocol to their own address\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function borrowInternal(uint borrowAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(msg.sender, borrowAmount);\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n /**\\n * @notice Users borrow assets from the protocol to their own address\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function borrowFresh(address payable borrower, uint borrowAmount) internal returns (uint) {\\n /* Fail if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.BORROW_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.BORROW_FRESHNESS_CHECK);\\n }\\n\\n /* Fail gracefully if protocol has insufficient underlying cash */\\n if (getCashPrior() < borrowAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.BORROW_CASH_NOT_AVAILABLE);\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We invoke doTransferOut for the borrower and the borrowAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(borrower, borrowAmount);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to borrower\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer the account paying off the borrow\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount the amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED\\\");\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED\\\");\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this cToken to be liquidated\\n * @param cTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) 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 = cTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, cTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this cToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param cTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowFresh(address liquidator, address borrower, uint repayAmount, CTokenInterface cTokenCollateral) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(address(this), address(cTokenCollateral), liquidator, borrower, repayAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify cTokenCollateral market's block number equals current block number */\\n if (cTokenCollateral.accrualBlockNumber() != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = -1 */\\n if (repayAmount == uint(-1)) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & 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(cTokenCollateral), actualRepayAmount);\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(cTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(cTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = cTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(cTokenCollateral), seizeTokens);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.liquidateBorrowVerify(address(this), address(cTokenCollateral), liquidator, borrower, actualRepayAmount, seizeTokens);\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another cToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed cToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of cTokens to seize\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function seize(address liquidator, address borrower, uint seizeTokens) external nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n struct SeizeInternalLocalVars {\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n uint liquidatorSeizeTokens;\\n uint protocolSeizeTokens;\\n uint protocolSeizeAmount;\\n uint exchangeRateMantissa;\\n uint totalReservesNew;\\n uint totalSupplyNew;\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another CToken.\\n * Its absolutely critical to use msg.sender as the seizer cToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed cToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of cTokens to seize\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function seizeInternal(address seizerToken, address liquidator, address borrower, uint seizeTokens) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n SeizeInternalLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (vars.mathErr, vars.borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(vars.mathErr));\\n }\\n\\n vars.protocolSeizeTokens = mul_(seizeTokens, Exp({mantissa: protocolSeizeShareMantissa}));\\n vars.liquidatorSeizeTokens = sub_(seizeTokens, vars.protocolSeizeTokens);\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n require(vars.mathErr == MathError.NO_ERROR, \\\"exchange rate math error\\\");\\n\\n vars.protocolSeizeAmount = mul_ScalarTruncate(Exp({mantissa: vars.exchangeRateMantissa}), vars.protocolSeizeTokens);\\n\\n vars.totalReservesNew = add_(totalReserves, vars.protocolSeizeAmount);\\n vars.totalSupplyNew = sub_(totalSupply, vars.protocolSeizeTokens);\\n\\n (vars.mathErr, vars.liquidatorTokensNew) = addUInt(accountTokens[liquidator], vars.liquidatorSeizeTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(vars.mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n totalReserves = vars.totalReservesNew;\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[borrower] = vars.borrowerTokensNew;\\n accountTokens[liquidator] = vars.liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, vars.liquidatorSeizeTokens);\\n emit Transfer(borrower, address(this), vars.protocolSeizeTokens);\\n emit ReservesAdded(address(this), vars.protocolSeizeAmount, vars.totalReservesNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n\\n /*** Admin Functions ***/\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPendingAdmin(address payable newPendingAdmin) external returns (uint) {\\n // Check caller = admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\\n }\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptAdmin() external returns (uint) {\\n // Check caller is pendingAdmin and pendingAdmin \\u2260 address(0)\\n if (msg.sender != pendingAdmin || msg.sender == address(0)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = address(0);\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setComptroller(ComptrollerInterface newComptroller) public returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_COMPTROLLER_OWNER_CHECK);\\n }\\n\\n ComptrollerInterface oldComptroller = comptroller;\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(oldComptroller, newComptroller);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh\\n * @dev Admin function to accrue interest and set a new reserve factor\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setReserveFactor(uint newReserveFactorMantissa) external nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\\n * @dev Admin function to set a new reserve factor\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_RESERVE_FACTOR_ADMIN_CHECK);\\n }\\n\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring from msg.sender\\n * @param addAmount Amount of addition to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to admin\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _reduceReserves(uint reduceAmount) external nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to admin\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _reduceReservesFresh(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's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n totalReservesNew = totalReserves - reduceAmount;\\n // We checked reduceAmount <= totalReserves above, so this should never revert.\\n require(totalReservesNew <= 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't be sure if side effects occurred.\\n doTransferOut(admin, reduceAmount);\\n\\n emit ReservesReduced(admin, reduceAmount, totalReservesNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Admin function to accrue interest and update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel);\\n }\\n\\n /**\\n * @notice updates the interest rate model (*requires fresh interest accrual)\\n * @dev Admin function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal returns (uint) {\\n\\n // Used to store old model for use in the event that is emitted on success\\n InterestRateModel oldInterestRateModel;\\n\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_INTEREST_RATE_MODEL_OWNER_CHECK);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Track the market's current interest rate model\\n oldInterestRateModel = interestRateModel;\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view returns (uint);\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure tather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal;\\n\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n}\\n\",\"keccak256\":\"0x436ec2e309682995f8a82dfdd9e8f75928599c10a9a680dddbee6c275014008d\"},\"contracts/CTokenInterfaces.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./InterestRateModel.sol\\\";\\nimport \\\"./EIP20NonStandardInterface.sol\\\";\\n\\ncontract CTokenStorage {\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-cToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModel public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first CTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping (address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping (address => mapping (address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Share of seized collateral that is added to reserves\\n */\\n uint public constant protocolSeizeShareMantissa = 2.8e16; //2.8%\\n\\n}\\n\\ncontract CTokenInterface is CTokenStorage {\\n /**\\n * @notice Indicator that this is a CToken contract (for inspection)\\n */\\n bool public constant isCToken = true;\\n\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(address liquidator, address borrower, uint repayAmount, address cTokenCollateral, uint seizeTokens);\\n\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin is updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(InterestRateModel oldInterestRateModel, InterestRateModel newInterestRateModel);\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address admin, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Failure event\\n */\\n event Failure(uint error, uint info, uint detail);\\n\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external returns (bool);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function approve(address spender, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function balanceOfUnderlying(address owner) external returns (uint);\\n function getAccountSnapshot(address account) external view returns (uint, uint, uint, uint);\\n function borrowRatePerBlock() external view returns (uint);\\n function supplyRatePerBlock() external view returns (uint);\\n function totalBorrowsCurrent() external returns (uint);\\n function borrowBalanceCurrent(address account) external returns (uint);\\n function borrowBalanceStored(address account) public view returns (uint);\\n function exchangeRateCurrent() public returns (uint);\\n function exchangeRateStored() public view returns (uint);\\n function getCash() external view returns (uint);\\n function accrueInterest() public returns (uint);\\n function seize(address liquidator, address borrower, uint seizeTokens) external returns (uint);\\n\\n\\n /*** Admin Functions ***/\\n\\n function _setPendingAdmin(address payable newPendingAdmin) external returns (uint);\\n function _acceptAdmin() external returns (uint);\\n function _setComptroller(ComptrollerInterface newComptroller) public returns (uint);\\n function _setReserveFactor(uint newReserveFactorMantissa) external returns (uint);\\n function _reduceReserves(uint reduceAmount) external returns (uint);\\n function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint);\\n}\\n\\ncontract CErc20Storage {\\n /**\\n * @notice Underlying asset for this CToken\\n */\\n address public underlying;\\n}\\n\\ncontract CErc20Interface is CErc20Storage {\\n\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n function redeem(uint redeemTokens) external returns (uint);\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n function borrow(uint borrowAmount) external returns (uint);\\n function repayBorrow(uint repayAmount) external returns (uint);\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n function liquidateBorrow(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) external returns (uint);\\n function sweepToken(EIP20NonStandardInterface token) external;\\n\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ncontract CDelegationStorage {\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n}\\n\\ncontract CDelegatorInterface is CDelegationStorage {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(address implementation_, bool allowResign, bytes memory becomeImplementationData) public;\\n}\\n\\ncontract CDelegateInterface is CDelegationStorage {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) public;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() public;\\n}\\n\",\"keccak256\":\"0x963bbf60b4c0b76900b3fcb2db8c8be634934b37b4113f1055e57a308197d21a\"},\"contracts/CarefulMath.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Careful Math\\n * @author Compound\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c = a * b;\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n return (MathError.NO_ERROR, a - b);\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c = a + b;\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\",\"keccak256\":\"0x0647348f27e41d22555d99eebd217dee02a4d737df6accd7cce5347a7487c7de\"},\"contracts/ComptrollerG5.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.sol\\\";\\nimport \\\"./ErrorReporter.sol\\\";\\nimport \\\"./Exponential.sol\\\";\\nimport \\\"./PriceOracle.sol\\\";\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./ComptrollerStorage.sol\\\";\\nimport \\\"./Unitroller.sol\\\";\\nimport \\\"./Governance/Comp.sol\\\";\\n\\n/**\\n * @title Compound's Comptroller Contract\\n * @author Compound (modified by Arr00)\\n */\\ncontract ComptrollerG5 is ComptrollerV4Storage, ComptrollerInterface, ComptrollerErrorReporter, Exponential {\\n /// @notice Emitted when an admin supports a market\\n event MarketListed(CToken cToken);\\n\\n /// @notice Emitted when an account enters a market\\n event MarketEntered(CToken cToken, address account);\\n\\n /// @notice Emitted when an account exits a market\\n event MarketExited(CToken cToken, 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(CToken cToken, 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 maxAssets is changed by admin\\n event NewMaxAssets(uint oldMaxAssets, uint newMaxAssets);\\n\\n /// @notice Emitted when price oracle is changed\\n event NewPriceOracle(PriceOracle oldPriceOracle, PriceOracle newPriceOracle);\\n\\n /// @notice Emitted when pause guardian is changed\\n event NewPauseGuardian(address oldPauseGuardian, address newPauseGuardian);\\n\\n /// @notice Emitted when an action is paused globally\\n event ActionPaused(string action, bool pauseState);\\n\\n /// @notice Emitted when an action is paused on a market\\n event ActionPaused(CToken cToken, string action, bool pauseState);\\n\\n /// @notice Emitted when market comped status is changed\\n event MarketComped(CToken cToken, bool isComped);\\n\\n /// @notice Emitted when COMP rate is changed\\n event NewCompRate(uint oldCompRate, uint newCompRate);\\n\\n /// @notice Emitted when a new COMP speed is calculated for a market\\n event CompSpeedUpdated(CToken indexed cToken, uint newSpeed);\\n\\n /// @notice Emitted when COMP is distributed to a supplier\\n event DistributedSupplierComp(CToken indexed cToken, address indexed supplier, uint compDelta, uint compSupplyIndex);\\n\\n /// @notice Emitted when COMP is distributed to a borrower\\n event DistributedBorrowerComp(CToken indexed cToken, address indexed borrower, uint compDelta, uint compBorrowIndex);\\n\\n /// @notice Emitted when borrow cap for a cToken is changed\\n event NewBorrowCap(CToken indexed cToken, uint newBorrowCap);\\n\\n /// @notice Emitted when borrow cap guardian is changed\\n event NewBorrowCapGuardian(address oldBorrowCapGuardian, address newBorrowCapGuardian);\\n\\n /// @notice The threshold above which the flywheel transfers COMP, in wei\\n uint public constant compClaimThreshold = 0.001e18;\\n\\n /// @notice The initial COMP index for a market\\n uint224 public constant compInitialIndex = 1e36;\\n\\n // closeFactorMantissa must be strictly greater than this value\\n uint internal constant closeFactorMinMantissa = 0.05e18; // 0.05\\n\\n // closeFactorMantissa must not exceed this value\\n uint internal constant closeFactorMaxMantissa = 0.9e18; // 0.9\\n\\n // No collateralFactorMantissa may exceed this value\\n uint internal constant collateralFactorMaxMantissa = 0.9e18; // 0.9\\n\\n // liquidationIncentiveMantissa must be no less than this value\\n uint internal constant liquidationIncentiveMinMantissa = 1.0e18; // 1.0\\n\\n // liquidationIncentiveMantissa must be no greater than this value\\n uint internal constant liquidationIncentiveMaxMantissa = 1.5e18; // 1.5\\n\\n constructor() public {\\n admin = msg.sender;\\n }\\n\\n /*** Assets You Are In ***/\\n\\n /**\\n * @notice Returns the assets an account has entered\\n * @param account The address of the account to pull assets for\\n * @return A dynamic list with the assets the account has entered\\n */\\n function getAssetsIn(address account) external view returns (CToken[] memory) {\\n CToken[] memory assetsIn = accountAssets[account];\\n\\n return assetsIn;\\n }\\n\\n /**\\n * @notice Returns whether the given account is entered in the given asset\\n * @param account The address of the account to check\\n * @param cToken The cToken to check\\n * @return True if the account is in the asset, otherwise false.\\n */\\n function checkMembership(address account, CToken cToken) external view returns (bool) {\\n return markets[address(cToken)].accountMembership[account];\\n }\\n\\n /**\\n * @notice Add assets to be included in account liquidity calculation\\n * @param cTokens The list of addresses of the cToken markets to be enabled\\n * @return Success indicator for whether each corresponding market was entered\\n */\\n function enterMarkets(address[] memory cTokens) public returns (uint[] memory) {\\n uint len = cTokens.length;\\n\\n uint[] memory results = new uint[](len);\\n for (uint i = 0; i < len; i++) {\\n CToken cToken = CToken(cTokens[i]);\\n\\n results[i] = uint(addToMarketInternal(cToken, msg.sender));\\n }\\n\\n return results;\\n }\\n\\n /**\\n * @notice Add the market to the borrower's \\\"assets in\\\" for liquidity calculations\\n * @param cToken The market to enter\\n * @param borrower The address of the account to modify\\n * @return Success indicator for whether the market was entered\\n */\\n function addToMarketInternal(CToken cToken, address borrower) internal returns (Error) {\\n Market storage marketToJoin = markets[address(cToken)];\\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 if (accountAssets[borrower].length >= maxAssets) {\\n // no space, cannot join\\n return Error.TOO_MANY_ASSETS;\\n }\\n\\n // survived the gauntlet, add to list\\n // NOTE: we store these somewhat redundantly as a significant optimization\\n // this avoids having to iterate through the list for the most common use cases\\n // that is, only when we need to perform liquidity checks\\n // and not whenever we want to check if an account is in a particular market\\n marketToJoin.accountMembership[borrower] = true;\\n accountAssets[borrower].push(cToken);\\n\\n emit MarketEntered(cToken, borrower);\\n\\n return Error.NO_ERROR;\\n }\\n\\n /**\\n * @notice Removes asset from sender's 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 cTokenAddress The address of the asset to be removed\\n * @return Whether or not the account successfully exited the market\\n */\\n function exitMarket(address cTokenAddress) external returns (uint) {\\n CToken cToken = CToken(cTokenAddress);\\n /* Get sender tokensHeld and amountOwed underlying from the cToken */\\n (uint oErr, uint tokensHeld, uint amountOwed, ) = cToken.getAccountSnapshot(msg.sender);\\n require(oErr == 0, \\\"exitMarket: getAccountSnapshot failed\\\"); // semi-opaque error code\\n\\n /* Fail if the sender has a borrow balance */\\n if (amountOwed != 0) {\\n return fail(Error.NONZERO_BORROW_BALANCE, FailureInfo.EXIT_MARKET_BALANCE_OWED);\\n }\\n\\n /* Fail if the sender is not permitted to redeem all of their tokens */\\n uint allowed = redeemAllowedInternal(cTokenAddress, msg.sender, tokensHeld);\\n if (allowed != 0) {\\n return failOpaque(Error.REJECTION, FailureInfo.EXIT_MARKET_REJECTION, allowed);\\n }\\n\\n Market storage marketToExit = markets[address(cToken)];\\n\\n /* Return true if the sender is not already \\u2018in\\u2019 the market */\\n if (!marketToExit.accountMembership[msg.sender]) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Set cToken account membership to false */\\n delete marketToExit.accountMembership[msg.sender];\\n\\n /* Delete cToken from the account\\u2019s list of assets */\\n // load into memory for faster iteration\\n CToken[] memory userAssetList = accountAssets[msg.sender];\\n uint len = userAssetList.length;\\n uint assetIndex = len;\\n for (uint i = 0; i < len; i++) {\\n if (userAssetList[i] == cToken) {\\n assetIndex = i;\\n break;\\n }\\n }\\n\\n // We *must* have found the asset in the list or our redundant data structure is broken\\n assert(assetIndex < len);\\n\\n // copy last item in list to location of item to be removed, reduce length by 1\\n CToken[] storage storedList = accountAssets[msg.sender];\\n storedList[assetIndex] = storedList[storedList.length - 1];\\n storedList.length--;\\n\\n emit MarketExited(cToken, 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 cToken The market to verify the mint against\\n * @param minter The account which would get the minted tokens\\n * @param mintAmount The amount of underlying being supplied to the market in exchange for tokens\\n * @return 0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function mintAllowed(address cToken, address minter, uint mintAmount) external returns (uint) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n require(!mintGuardianPaused[cToken], \\\"mint is paused\\\");\\n\\n // Shh - currently unused\\n minter;\\n mintAmount;\\n\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n // Keep the flywheel moving\\n updateCompSupplyIndex(cToken);\\n distributeSupplierComp(cToken, minter, false);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates mint and reverts on rejection. May emit logs.\\n * @param cToken Asset being minted\\n * @param minter The address minting the tokens\\n * @param actualMintAmount The amount of the underlying asset being minted\\n * @param mintTokens The number of tokens being minted\\n */\\n function mintVerify(address cToken, address minter, uint actualMintAmount, uint mintTokens) external {\\n // Shh - currently unused\\n cToken;\\n minter;\\n actualMintAmount;\\n mintTokens;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to redeem tokens in the given market\\n * @param cToken The market to verify the redeem against\\n * @param redeemer The account which would redeem the tokens\\n * @param redeemTokens The number of cTokens to exchange for the underlying asset in the market\\n * @return 0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function redeemAllowed(address cToken, address redeemer, uint redeemTokens) external returns (uint) {\\n uint allowed = redeemAllowedInternal(cToken, redeemer, redeemTokens);\\n if (allowed != uint(Error.NO_ERROR)) {\\n return allowed;\\n }\\n\\n // Keep the flywheel moving\\n updateCompSupplyIndex(cToken);\\n distributeSupplierComp(cToken, redeemer, false);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n function redeemAllowedInternal(address cToken, address redeemer, uint redeemTokens) internal view returns (uint) {\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!markets[cToken].accountMembership[redeemer]) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n (Error err, , uint shortfall) = getHypotheticalAccountLiquidityInternal(redeemer, CToken(cToken), redeemTokens, 0);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n if (shortfall > 0) {\\n return uint(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates redeem and reverts on rejection. May emit logs.\\n * @param cToken Asset being redeemed\\n * @param redeemer The address redeeming the tokens\\n * @param redeemAmount The amount of the underlying asset being redeemed\\n * @param redeemTokens The number of tokens being redeemed\\n */\\n function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) external {\\n // Shh - currently unused\\n cToken;\\n redeemer;\\n\\n // Require tokens is zero or amount is also zero\\n if (redeemTokens == 0 && redeemAmount > 0) {\\n revert(\\\"redeemTokens zero\\\");\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to borrow the underlying asset of the given market\\n * @param cToken The market to verify the borrow against\\n * @param borrower The account which would borrow the asset\\n * @param borrowAmount The amount of underlying the account would borrow\\n * @return 0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function borrowAllowed(address cToken, address borrower, uint borrowAmount) external returns (uint) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n require(!borrowGuardianPaused[cToken], \\\"borrow is paused\\\");\\n\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n if (!markets[cToken].accountMembership[borrower]) {\\n // only cTokens may call borrowAllowed if borrower not in market\\n require(msg.sender == cToken, \\\"sender must be cToken\\\");\\n\\n // attempt to add borrower to the market\\n Error err = addToMarketInternal(CToken(msg.sender), borrower);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n\\n // it should be impossible to break the important invariant\\n assert(markets[cToken].accountMembership[borrower]);\\n }\\n\\n if (oracle.getUnderlyingPrice(CToken(cToken)) == 0) {\\n return uint(Error.PRICE_ERROR);\\n }\\n\\n\\n uint borrowCap = borrowCaps[cToken];\\n // Borrow cap of 0 corresponds to unlimited borrowing\\n if (borrowCap != 0) {\\n uint totalBorrows = CToken(cToken).totalBorrows();\\n (MathError mathErr, uint nextTotalBorrows) = addUInt(totalBorrows, borrowAmount);\\n require(mathErr == MathError.NO_ERROR, \\\"total borrows overflow\\\");\\n require(nextTotalBorrows < borrowCap, \\\"market borrow cap reached\\\");\\n }\\n\\n (Error err, , uint shortfall) = getHypotheticalAccountLiquidityInternal(borrower, CToken(cToken), 0, borrowAmount);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n if (shortfall > 0) {\\n return uint(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n\\n // Keep the flywheel moving\\n Exp memory borrowIndex = Exp({mantissa: CToken(cToken).borrowIndex()});\\n updateCompBorrowIndex(cToken, borrowIndex);\\n distributeBorrowerComp(cToken, borrower, borrowIndex, false);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates borrow and reverts on rejection. May emit logs.\\n * @param cToken Asset whose underlying is being borrowed\\n * @param borrower The address borrowing the underlying\\n * @param borrowAmount The amount of the underlying asset requested to borrow\\n */\\n function borrowVerify(address cToken, address borrower, uint borrowAmount) external {\\n // Shh - currently unused\\n cToken;\\n borrower;\\n borrowAmount;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to repay a borrow in the given market\\n * @param cToken The market to verify the repay against\\n * @param payer The account which would repay the asset\\n * @param borrower The account which would borrowed the asset\\n * @param repayAmount The amount of the underlying asset the account would repay\\n * @return 0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function repayBorrowAllowed(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount) external returns (uint) {\\n // Shh - currently unused\\n payer;\\n borrower;\\n repayAmount;\\n\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n // Keep the flywheel moving\\n Exp memory borrowIndex = Exp({mantissa: CToken(cToken).borrowIndex()});\\n updateCompBorrowIndex(cToken, borrowIndex);\\n distributeBorrowerComp(cToken, borrower, borrowIndex, false);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates repayBorrow and reverts on rejection. May emit logs.\\n * @param cToken Asset being repaid\\n * @param payer The address repaying the borrow\\n * @param borrower The address of the borrower\\n * @param actualRepayAmount The amount of underlying being repaid\\n */\\n function repayBorrowVerify(\\n address cToken,\\n address payer,\\n address borrower,\\n uint actualRepayAmount,\\n uint borrowerIndex) external {\\n // Shh - currently unused\\n cToken;\\n payer;\\n borrower;\\n actualRepayAmount;\\n borrowerIndex;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the liquidation should be allowed to occur\\n * @param cTokenBorrowed Asset which was borrowed by the borrower\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param repayAmount The amount of underlying being repaid\\n */\\n function liquidateBorrowAllowed(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount) external returns (uint) {\\n // Shh - currently unused\\n liquidator;\\n\\n if (!markets[cTokenBorrowed].isListed || !markets[cTokenCollateral].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n /* The borrower must have shortfall in order to be liquidatable */\\n (Error err, , uint shortfall) = getAccountLiquidityInternal(borrower);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n if (shortfall == 0) {\\n return uint(Error.INSUFFICIENT_SHORTFALL);\\n }\\n\\n /* The liquidator may not repay more than what is allowed by the closeFactor */\\n uint borrowBalance = CToken(cTokenBorrowed).borrowBalanceStored(borrower);\\n (MathError mathErr, uint maxClose) = mulScalarTruncate(Exp({mantissa: closeFactorMantissa}), borrowBalance);\\n if (mathErr != MathError.NO_ERROR) {\\n return uint(Error.MATH_ERROR);\\n }\\n if (repayAmount > 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 cTokenBorrowed Asset which was borrowed by the borrower\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param actualRepayAmount The amount of underlying being repaid\\n */\\n function liquidateBorrowVerify(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint actualRepayAmount,\\n uint seizeTokens) external {\\n // Shh - currently unused\\n cTokenBorrowed;\\n cTokenCollateral;\\n liquidator;\\n borrower;\\n actualRepayAmount;\\n seizeTokens;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the seizing of assets should be allowed to occur\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param cTokenBorrowed Asset which was borrowed by the borrower\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param seizeTokens The number of collateral tokens to seize\\n */\\n function seizeAllowed(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external returns (uint) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n require(!seizeGuardianPaused, \\\"seize is paused\\\");\\n\\n // Shh - currently unused\\n seizeTokens;\\n\\n if (!markets[cTokenCollateral].isListed || !markets[cTokenBorrowed].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n if (CToken(cTokenCollateral).comptroller() != CToken(cTokenBorrowed).comptroller()) {\\n return uint(Error.COMPTROLLER_MISMATCH);\\n }\\n\\n // Keep the flywheel moving\\n updateCompSupplyIndex(cTokenCollateral);\\n distributeSupplierComp(cTokenCollateral, borrower, false);\\n distributeSupplierComp(cTokenCollateral, liquidator, false);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates seize and reverts on rejection. May emit logs.\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param cTokenBorrowed Asset which was borrowed by the borrower\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param seizeTokens The number of collateral tokens to seize\\n */\\n function seizeVerify(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external {\\n // Shh - currently unused\\n cTokenCollateral;\\n cTokenBorrowed;\\n liquidator;\\n borrower;\\n seizeTokens;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to transfer tokens in the given market\\n * @param cToken The market to verify the transfer against\\n * @param src The account which sources the tokens\\n * @param dst The account which receives the tokens\\n * @param transferTokens The number of cTokens to transfer\\n * @return 0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function transferAllowed(address cToken, address src, address dst, uint transferTokens) external returns (uint) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n require(!transferGuardianPaused, \\\"transfer is paused\\\");\\n\\n // Currently the only consideration is whether or not\\n // the src is allowed to redeem this many tokens\\n uint allowed = redeemAllowedInternal(cToken, src, transferTokens);\\n if (allowed != uint(Error.NO_ERROR)) {\\n return allowed;\\n }\\n\\n // Keep the flywheel moving\\n updateCompSupplyIndex(cToken);\\n distributeSupplierComp(cToken, src, false);\\n distributeSupplierComp(cToken, dst, false);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates transfer and reverts on rejection. May emit logs.\\n * @param cToken Asset being transferred\\n * @param src The account which sources the tokens\\n * @param dst The account which receives the tokens\\n * @param transferTokens The number of cTokens to transfer\\n */\\n function transferVerify(address cToken, address src, address dst, uint transferTokens) external {\\n // Shh - currently unused\\n cToken;\\n src;\\n dst;\\n transferTokens;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n /**\\n * @dev Local vars for avoiding stack-depth limits in calculating account liquidity.\\n * Note that `cTokenBalance` is the number of cTokens the account owns in the market,\\n * whereas `borrowBalance` is the amount of underlying that the account has borrowed.\\n */\\n struct AccountLiquidityLocalVars {\\n uint sumCollateral;\\n uint sumBorrowPlusEffects;\\n uint cTokenBalance;\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n uint oraclePriceMantissa;\\n Exp collateralFactor;\\n Exp exchangeRate;\\n Exp oraclePrice;\\n Exp tokensToDenom;\\n }\\n\\n /**\\n * @notice Determine the current account liquidity wrt collateral requirements\\n * @return (possible error code (semi-opaque),\\n account liquidity in excess of collateral requirements,\\n * account shortfall below collateral requirements)\\n */\\n function getAccountLiquidity(address account) public view returns (uint, uint, uint) {\\n (Error err, uint liquidity, uint shortfall) = getHypotheticalAccountLiquidityInternal(account, CToken(0), 0, 0);\\n\\n return (uint(err), liquidity, shortfall);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity wrt collateral requirements\\n * @return (possible error code,\\n account liquidity in excess of collateral requirements,\\n * account shortfall below collateral requirements)\\n */\\n function getAccountLiquidityInternal(address account) internal view returns (Error, uint, uint) {\\n return getHypotheticalAccountLiquidityInternal(account, CToken(0), 0, 0);\\n }\\n\\n /**\\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\\n * @param cTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @return (possible error code (semi-opaque),\\n hypothetical account liquidity in excess of collateral requirements,\\n * hypothetical account shortfall below collateral requirements)\\n */\\n function getHypotheticalAccountLiquidity(\\n address account,\\n address cTokenModify,\\n uint redeemTokens,\\n uint borrowAmount) public view returns (uint, uint, uint) {\\n (Error err, uint liquidity, uint shortfall) = getHypotheticalAccountLiquidityInternal(account, CToken(cTokenModify), 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 cTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @dev Note that we calculate the exchangeRateStored for each collateral cToken using stored data,\\n * without calculating accumulated interest.\\n * @return (possible error code,\\n hypothetical account liquidity in excess of collateral requirements,\\n * hypothetical account shortfall below collateral requirements)\\n */\\n function getHypotheticalAccountLiquidityInternal(\\n address account,\\n CToken cTokenModify,\\n uint redeemTokens,\\n uint borrowAmount) internal view returns (Error, uint, uint) {\\n\\n AccountLiquidityLocalVars memory vars; // Holds all our calculation results\\n uint oErr;\\n MathError mErr;\\n\\n // For each asset the account is in\\n CToken[] memory assets = accountAssets[account];\\n for (uint i = 0; i < assets.length; i++) {\\n CToken asset = assets[i];\\n\\n // Read the balances and exchange rate from the cToken\\n (oErr, vars.cTokenBalance, vars.borrowBalance, vars.exchangeRateMantissa) = asset.getAccountSnapshot(account);\\n if (oErr != 0) { // semi-opaque error code, we assume NO_ERROR == 0 is invariant between upgrades\\n return (Error.SNAPSHOT_ERROR, 0, 0);\\n }\\n vars.collateralFactor = Exp({mantissa: markets[address(asset)].collateralFactorMantissa});\\n vars.exchangeRate = Exp({mantissa: vars.exchangeRateMantissa});\\n\\n // Get the normalized price of the asset\\n vars.oraclePriceMantissa = oracle.getUnderlyingPrice(asset);\\n if (vars.oraclePriceMantissa == 0) {\\n return (Error.PRICE_ERROR, 0, 0);\\n }\\n vars.oraclePrice = Exp({mantissa: vars.oraclePriceMantissa});\\n\\n // Pre-compute a conversion factor from tokens -> 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 * cTokenBalance\\n (mErr, vars.sumCollateral) = mulScalarTruncateAddUInt(vars.tokensToDenom, vars.cTokenBalance, 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 cTokenModify\\n if (asset == cTokenModify) {\\n // redeem effect\\n // sumBorrowPlusEffects += tokensToDenom * redeemTokens\\n (mErr, vars.sumBorrowPlusEffects) = mulScalarTruncateAddUInt(vars.tokensToDenom, redeemTokens, vars.sumBorrowPlusEffects);\\n if (mErr != MathError.NO_ERROR) {\\n return (Error.MATH_ERROR, 0, 0);\\n }\\n\\n // borrow effect\\n // sumBorrowPlusEffects += oraclePrice * borrowAmount\\n (mErr, vars.sumBorrowPlusEffects) = mulScalarTruncateAddUInt(vars.oraclePrice, borrowAmount, vars.sumBorrowPlusEffects);\\n if (mErr != MathError.NO_ERROR) {\\n return (Error.MATH_ERROR, 0, 0);\\n }\\n }\\n }\\n\\n // These are safe, as the underflow condition is checked first\\n if (vars.sumCollateral > vars.sumBorrowPlusEffects) {\\n return (Error.NO_ERROR, vars.sumCollateral - vars.sumBorrowPlusEffects, 0);\\n } else {\\n return (Error.NO_ERROR, 0, vars.sumBorrowPlusEffects - vars.sumCollateral);\\n }\\n }\\n\\n /**\\n * @notice Calculate number of tokens of collateral asset to seize given an underlying amount\\n * @dev Used in liquidation (called in cToken.liquidateBorrowFresh)\\n * @param cTokenBorrowed The address of the borrowed cToken\\n * @param cTokenCollateral The address of the collateral cToken\\n * @param actualRepayAmount The amount of cTokenBorrowed underlying to convert into cTokenCollateral tokens\\n * @return (errorCode, number of cTokenCollateral tokens to be seized in a liquidation)\\n */\\n function liquidateCalculateSeizeTokens(address cTokenBorrowed, address cTokenCollateral, uint actualRepayAmount) external view returns (uint, uint) {\\n /* Read oracle prices for borrowed and collateral markets */\\n uint priceBorrowedMantissa = oracle.getUnderlyingPrice(CToken(cTokenBorrowed));\\n uint priceCollateralMantissa = oracle.getUnderlyingPrice(CToken(cTokenCollateral));\\n if (priceBorrowedMantissa == 0 || priceCollateralMantissa == 0) {\\n return (uint(Error.PRICE_ERROR), 0);\\n }\\n\\n /*\\n * Get the exchange rate and calculate the number of collateral tokens to seize:\\n * seizeAmount = actualRepayAmount * liquidationIncentive * priceBorrowed / priceCollateral\\n * seizeTokens = seizeAmount / exchangeRate\\n * = actualRepayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate)\\n */\\n uint exchangeRateMantissa = CToken(cTokenCollateral).exchangeRateStored(); // Note: reverts on error\\n uint seizeTokens;\\n Exp memory numerator;\\n Exp memory denominator;\\n Exp memory ratio;\\n MathError mathErr;\\n\\n (mathErr, numerator) = mulExp(liquidationIncentiveMantissa, priceBorrowedMantissa);\\n if (mathErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0);\\n }\\n\\n (mathErr, denominator) = mulExp(priceCollateralMantissa, exchangeRateMantissa);\\n if (mathErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0);\\n }\\n\\n (mathErr, ratio) = divExp(numerator, denominator);\\n if (mathErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0);\\n }\\n\\n (mathErr, seizeTokens) = mulScalarTruncate(ratio, actualRepayAmount);\\n if (mathErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0);\\n }\\n\\n return (uint(Error.NO_ERROR), seizeTokens);\\n }\\n\\n /*** Admin Functions ***/\\n\\n /**\\n * @notice Sets a new price oracle for the comptroller\\n * @dev Admin function to set a new price oracle\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPriceOracle(PriceOracle newOracle) public returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PRICE_ORACLE_OWNER_CHECK);\\n }\\n\\n // Track the old oracle for the comptroller\\n PriceOracle oldOracle = oracle;\\n\\n // Set comptroller's oracle to newOracle\\n oracle = newOracle;\\n\\n // Emit NewPriceOracle(oldOracle, newOracle)\\n emit NewPriceOracle(oldOracle, newOracle);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets the closeFactor used when liquidating borrows\\n * @dev Admin function to set closeFactor\\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\\n * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function _setCloseFactor(uint newCloseFactorMantissa) external returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_CLOSE_FACTOR_OWNER_CHECK);\\n }\\n\\n Exp memory newCloseFactorExp = Exp({mantissa: newCloseFactorMantissa});\\n Exp memory lowLimit = Exp({mantissa: closeFactorMinMantissa});\\n if (lessThanOrEqualExp(newCloseFactorExp, lowLimit)) {\\n return fail(Error.INVALID_CLOSE_FACTOR, FailureInfo.SET_CLOSE_FACTOR_VALIDATION);\\n }\\n\\n Exp memory highLimit = Exp({mantissa: closeFactorMaxMantissa});\\n if (lessThanExp(highLimit, newCloseFactorExp)) {\\n return fail(Error.INVALID_CLOSE_FACTOR, FailureInfo.SET_CLOSE_FACTOR_VALIDATION);\\n }\\n\\n uint oldCloseFactorMantissa = closeFactorMantissa;\\n closeFactorMantissa = newCloseFactorMantissa;\\n emit NewCloseFactor(oldCloseFactorMantissa, closeFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets the collateralFactor for a market\\n * @dev Admin function to set per-market collateralFactor\\n * @param cToken The market to set the factor on\\n * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18\\n * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function _setCollateralFactor(CToken cToken, 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(cToken)];\\n if (!market.isListed) {\\n return fail(Error.MARKET_NOT_LISTED, FailureInfo.SET_COLLATERAL_FACTOR_NO_EXISTS);\\n }\\n\\n Exp memory newCollateralFactorExp = Exp({mantissa: newCollateralFactorMantissa});\\n\\n // Check collateral factor <= 0.9\\n Exp memory highLimit = Exp({mantissa: collateralFactorMaxMantissa});\\n if (lessThanExp(highLimit, newCollateralFactorExp)) {\\n return fail(Error.INVALID_COLLATERAL_FACTOR, FailureInfo.SET_COLLATERAL_FACTOR_VALIDATION);\\n }\\n\\n // If collateral factor != 0, fail if price == 0\\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(cToken) == 0) {\\n return fail(Error.PRICE_ERROR, FailureInfo.SET_COLLATERAL_FACTOR_WITHOUT_PRICE);\\n }\\n\\n // Set market's collateral factor to new collateral factor, remember old value\\n uint oldCollateralFactorMantissa = market.collateralFactorMantissa;\\n market.collateralFactorMantissa = newCollateralFactorMantissa;\\n\\n // Emit event with asset, old collateral factor, and new collateral factor\\n emit NewCollateralFactor(cToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets maxAssets which controls how many markets can be entered\\n * @dev Admin function to set maxAssets\\n * @param newMaxAssets New max assets\\n * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function _setMaxAssets(uint newMaxAssets) external returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_MAX_ASSETS_OWNER_CHECK);\\n }\\n\\n uint oldMaxAssets = maxAssets;\\n maxAssets = newMaxAssets;\\n emit NewMaxAssets(oldMaxAssets, newMaxAssets);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets liquidationIncentive\\n * @dev Admin function to set liquidationIncentive\\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\\n * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function _setLiquidationIncentive(uint newLiquidationIncentiveMantissa) external returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_LIQUIDATION_INCENTIVE_OWNER_CHECK);\\n }\\n\\n // Check de-scaled min <= newLiquidationIncentive <= max\\n Exp memory newLiquidationIncentive = Exp({mantissa: newLiquidationIncentiveMantissa});\\n Exp memory minLiquidationIncentive = Exp({mantissa: liquidationIncentiveMinMantissa});\\n if (lessThanExp(newLiquidationIncentive, minLiquidationIncentive)) {\\n return fail(Error.INVALID_LIQUIDATION_INCENTIVE, FailureInfo.SET_LIQUIDATION_INCENTIVE_VALIDATION);\\n }\\n\\n Exp memory maxLiquidationIncentive = Exp({mantissa: liquidationIncentiveMaxMantissa});\\n if (lessThanExp(maxLiquidationIncentive, newLiquidationIncentive)) {\\n return fail(Error.INVALID_LIQUIDATION_INCENTIVE, FailureInfo.SET_LIQUIDATION_INCENTIVE_VALIDATION);\\n }\\n\\n // Save current value for use in log\\n uint oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa;\\n\\n // Set liquidation incentive to new incentive\\n liquidationIncentiveMantissa = newLiquidationIncentiveMantissa;\\n\\n // Emit event with old incentive, new incentive\\n emit NewLiquidationIncentive(oldLiquidationIncentiveMantissa, newLiquidationIncentiveMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Add the market to the markets mapping and set it as listed\\n * @dev Admin function to set isListed and add support for the market\\n * @param cToken The address of the market (token) to list\\n * @return uint 0=success, otherwise a failure. (See enum Error for details)\\n */\\n function _supportMarket(CToken cToken) external returns (uint) {\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SUPPORT_MARKET_OWNER_CHECK);\\n }\\n\\n if (markets[address(cToken)].isListed) {\\n return fail(Error.MARKET_ALREADY_LISTED, FailureInfo.SUPPORT_MARKET_EXISTS);\\n }\\n\\n cToken.isCToken(); // Sanity check to make sure its really a CToken\\n\\n markets[address(cToken)] = Market({isListed: true, isComped: false, collateralFactorMantissa: 0});\\n\\n _addMarketInternal(address(cToken));\\n\\n emit MarketListed(cToken);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n function _addMarketInternal(address cToken) internal {\\n for (uint i = 0; i < allMarkets.length; i ++) {\\n require(allMarkets[i] != CToken(cToken), \\\"market already added\\\");\\n }\\n allMarkets.push(CToken(cToken));\\n }\\n\\n\\n /**\\n * @notice Set the given borrow caps for the given cToken markets. Borrowing that brings total borrows to or above borrow cap will revert.\\n * @dev Admin or borrowCapGuardian function to set the borrow caps. A borrow cap of 0 corresponds to unlimited borrowing.\\n * @param cTokens The addresses of the markets (tokens) to change the borrow caps for\\n * @param newBorrowCaps The new borrow cap values in underlying to be set. A value of 0 corresponds to unlimited borrowing.\\n */\\n function _setMarketBorrowCaps(CToken[] calldata cTokens, uint[] calldata newBorrowCaps) external {\\n \\trequire(msg.sender == admin || msg.sender == borrowCapGuardian, \\\"only admin or borrow cap guardian can set borrow caps\\\"); \\n\\n uint numMarkets = cTokens.length;\\n uint numBorrowCaps = newBorrowCaps.length;\\n\\n require(numMarkets != 0 && numMarkets == numBorrowCaps, \\\"invalid input\\\");\\n\\n for(uint i = 0; i < numMarkets; i++) {\\n borrowCaps[address(cTokens[i])] = newBorrowCaps[i];\\n emit NewBorrowCap(cTokens[i], newBorrowCaps[i]);\\n }\\n }\\n\\n /**\\n * @notice Admin function to change the Borrow Cap Guardian\\n * @param newBorrowCapGuardian The address of the new Borrow Cap Guardian\\n */\\n function _setBorrowCapGuardian(address newBorrowCapGuardian) external {\\n require(msg.sender == admin, \\\"only admin can set borrow cap guardian\\\");\\n\\n // Save current value for inclusion in log\\n address oldBorrowCapGuardian = borrowCapGuardian;\\n\\n // Store borrowCapGuardian with value newBorrowCapGuardian\\n borrowCapGuardian = newBorrowCapGuardian;\\n\\n // Emit NewBorrowCapGuardian(OldBorrowCapGuardian, NewBorrowCapGuardian)\\n emit NewBorrowCapGuardian(oldBorrowCapGuardian, newBorrowCapGuardian);\\n }\\n\\n /**\\n * @notice Admin function to change the Pause Guardian\\n * @param newPauseGuardian The address of the new Pause Guardian\\n * @return uint 0=success, otherwise a failure. (See enum Error for details)\\n */\\n function _setPauseGuardian(address newPauseGuardian) public returns (uint) {\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PAUSE_GUARDIAN_OWNER_CHECK);\\n }\\n\\n // Save current value for inclusion in log\\n address oldPauseGuardian = pauseGuardian;\\n\\n // Store pauseGuardian with value newPauseGuardian\\n pauseGuardian = newPauseGuardian;\\n\\n // Emit NewPauseGuardian(OldPauseGuardian, NewPauseGuardian)\\n emit NewPauseGuardian(oldPauseGuardian, pauseGuardian);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n function _setMintPaused(CToken cToken, bool state) public returns (bool) {\\n require(markets[address(cToken)].isListed, \\\"cannot pause a market that is not listed\\\");\\n require(msg.sender == pauseGuardian || msg.sender == admin, \\\"only pause guardian and admin can pause\\\");\\n require(msg.sender == admin || state == true, \\\"only admin can unpause\\\");\\n\\n mintGuardianPaused[address(cToken)] = state;\\n emit ActionPaused(cToken, \\\"Mint\\\", state);\\n return state;\\n }\\n\\n function _setBorrowPaused(CToken cToken, bool state) public returns (bool) {\\n require(markets[address(cToken)].isListed, \\\"cannot pause a market that is not listed\\\");\\n require(msg.sender == pauseGuardian || msg.sender == admin, \\\"only pause guardian and admin can pause\\\");\\n require(msg.sender == admin || state == true, \\\"only admin can unpause\\\");\\n\\n borrowGuardianPaused[address(cToken)] = state;\\n emit ActionPaused(cToken, \\\"Borrow\\\", state);\\n return state;\\n }\\n\\n function _setTransferPaused(bool state) public returns (bool) {\\n require(msg.sender == pauseGuardian || msg.sender == admin, \\\"only pause guardian and admin can pause\\\");\\n require(msg.sender == admin || state == true, \\\"only admin can unpause\\\");\\n\\n transferGuardianPaused = state;\\n emit ActionPaused(\\\"Transfer\\\", state);\\n return state;\\n }\\n\\n function _setSeizePaused(bool state) public returns (bool) {\\n require(msg.sender == pauseGuardian || msg.sender == admin, \\\"only pause guardian and admin can pause\\\");\\n require(msg.sender == admin || state == true, \\\"only admin can unpause\\\");\\n\\n seizeGuardianPaused = state;\\n emit ActionPaused(\\\"Seize\\\", state);\\n return state;\\n }\\n\\n function _become(Unitroller unitroller) public {\\n require(msg.sender == unitroller.admin(), \\\"only unitroller admin can change brains\\\");\\n require(unitroller._acceptImplementation() == 0, \\\"change not authorized\\\");\\n }\\n\\n /**\\n * @notice Checks caller is admin, or this contract is becoming the new implementation\\n */\\n function adminOrInitializing() internal view returns (bool) {\\n return msg.sender == admin || msg.sender == comptrollerImplementation;\\n }\\n\\n /*** Comp Distribution ***/\\n\\n /**\\n * @notice Recalculate and update COMP speeds for all COMP markets\\n */\\n function refreshCompSpeeds() public {\\n require(msg.sender == tx.origin, \\\"only externally owned accounts may refresh speeds\\\");\\n refreshCompSpeedsInternal();\\n }\\n\\n function refreshCompSpeedsInternal() internal {\\n CToken[] memory allMarkets_ = allMarkets;\\n\\n for (uint i = 0; i < allMarkets_.length; i++) {\\n CToken cToken = allMarkets_[i];\\n Exp memory borrowIndex = Exp({mantissa: cToken.borrowIndex()});\\n updateCompSupplyIndex(address(cToken));\\n updateCompBorrowIndex(address(cToken), borrowIndex);\\n }\\n\\n Exp memory totalUtility = Exp({mantissa: 0});\\n Exp[] memory utilities = new Exp[](allMarkets_.length);\\n for (uint i = 0; i < allMarkets_.length; i++) {\\n CToken cToken = allMarkets_[i];\\n if (markets[address(cToken)].isComped) {\\n Exp memory assetPrice = Exp({mantissa: oracle.getUnderlyingPrice(cToken)});\\n Exp memory utility = mul_(assetPrice, cToken.totalBorrows());\\n utilities[i] = utility;\\n totalUtility = add_(totalUtility, utility);\\n }\\n }\\n\\n for (uint i = 0; i < allMarkets_.length; i++) {\\n CToken cToken = allMarkets[i];\\n uint newSpeed = totalUtility.mantissa > 0 ? mul_(compRate, div_(utilities[i], totalUtility)) : 0;\\n compSpeeds[address(cToken)] = newSpeed;\\n emit CompSpeedUpdated(cToken, newSpeed);\\n }\\n }\\n\\n /**\\n * @notice Accrue COMP to the market by updating the supply index\\n * @param cToken The market whose supply index to update\\n */\\n function updateCompSupplyIndex(address cToken) internal {\\n CompMarketState storage supplyState = compSupplyState[cToken];\\n uint supplySpeed = compSpeeds[cToken];\\n uint blockNumber = getBlockNumber();\\n uint deltaBlocks = sub_(blockNumber, uint(supplyState.block));\\n if (deltaBlocks > 0 && supplySpeed > 0) {\\n uint supplyTokens = CToken(cToken).totalSupply();\\n uint compAccrued = mul_(deltaBlocks, supplySpeed);\\n Double memory ratio = supplyTokens > 0 ? fraction(compAccrued, supplyTokens) : Double({mantissa: 0});\\n Double memory index = add_(Double({mantissa: supplyState.index}), ratio);\\n compSupplyState[cToken] = CompMarketState({\\n index: safe224(index.mantissa, \\\"new index exceeds 224 bits\\\"),\\n block: safe32(blockNumber, \\\"block number exceeds 32 bits\\\")\\n });\\n } else if (deltaBlocks > 0) {\\n supplyState.block = safe32(blockNumber, \\\"block number exceeds 32 bits\\\");\\n }\\n }\\n\\n /**\\n * @notice Accrue COMP to the market by updating the borrow index\\n * @param cToken The market whose borrow index to update\\n */\\n function updateCompBorrowIndex(address cToken, Exp memory marketBorrowIndex) internal {\\n CompMarketState storage borrowState = compBorrowState[cToken];\\n uint borrowSpeed = compSpeeds[cToken];\\n uint blockNumber = getBlockNumber();\\n uint deltaBlocks = sub_(blockNumber, uint(borrowState.block));\\n if (deltaBlocks > 0 && borrowSpeed > 0) {\\n uint borrowAmount = div_(CToken(cToken).totalBorrows(), marketBorrowIndex);\\n uint compAccrued = mul_(deltaBlocks, borrowSpeed);\\n Double memory ratio = borrowAmount > 0 ? fraction(compAccrued, borrowAmount) : Double({mantissa: 0});\\n Double memory index = add_(Double({mantissa: borrowState.index}), ratio);\\n compBorrowState[cToken] = CompMarketState({\\n index: safe224(index.mantissa, \\\"new index exceeds 224 bits\\\"),\\n block: safe32(blockNumber, \\\"block number exceeds 32 bits\\\")\\n });\\n } else if (deltaBlocks > 0) {\\n borrowState.block = safe32(blockNumber, \\\"block number exceeds 32 bits\\\");\\n }\\n }\\n\\n /**\\n * @notice Calculate COMP accrued by a supplier and possibly transfer it to them\\n * @param cToken The market in which the supplier is interacting\\n * @param supplier The address of the supplier to distribute COMP to\\n */\\n function distributeSupplierComp(address cToken, address supplier, bool distributeAll) internal {\\n CompMarketState storage supplyState = compSupplyState[cToken];\\n Double memory supplyIndex = Double({mantissa: supplyState.index});\\n Double memory supplierIndex = Double({mantissa: compSupplierIndex[cToken][supplier]});\\n compSupplierIndex[cToken][supplier] = supplyIndex.mantissa;\\n\\n if (supplierIndex.mantissa == 0 && supplyIndex.mantissa > 0) {\\n supplierIndex.mantissa = compInitialIndex;\\n }\\n\\n Double memory deltaIndex = sub_(supplyIndex, supplierIndex);\\n uint supplierTokens = CToken(cToken).balanceOf(supplier);\\n uint supplierDelta = mul_(supplierTokens, deltaIndex);\\n uint supplierAccrued = add_(compAccrued[supplier], supplierDelta);\\n compAccrued[supplier] = transferComp(supplier, supplierAccrued, distributeAll ? 0 : compClaimThreshold);\\n emit DistributedSupplierComp(CToken(cToken), supplier, supplierDelta, supplyIndex.mantissa);\\n }\\n\\n /**\\n * @notice Calculate COMP accrued by a borrower and possibly transfer it to them\\n * @dev Borrowers will not begin to accrue until after the first interaction with the protocol.\\n * @param cToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute COMP to\\n */\\n function distributeBorrowerComp(address cToken, address borrower, Exp memory marketBorrowIndex, bool distributeAll) internal {\\n CompMarketState storage borrowState = compBorrowState[cToken];\\n Double memory borrowIndex = Double({mantissa: borrowState.index});\\n Double memory borrowerIndex = Double({mantissa: compBorrowerIndex[cToken][borrower]});\\n compBorrowerIndex[cToken][borrower] = borrowIndex.mantissa;\\n\\n if (borrowerIndex.mantissa > 0) {\\n Double memory deltaIndex = sub_(borrowIndex, borrowerIndex);\\n uint borrowerAmount = div_(CToken(cToken).borrowBalanceStored(borrower), marketBorrowIndex);\\n uint borrowerDelta = mul_(borrowerAmount, deltaIndex);\\n uint borrowerAccrued = add_(compAccrued[borrower], borrowerDelta);\\n compAccrued[borrower] = transferComp(borrower, borrowerAccrued, distributeAll ? 0 : compClaimThreshold);\\n emit DistributedBorrowerComp(CToken(cToken), borrower, borrowerDelta, borrowIndex.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Transfer COMP to the user, if they are above the threshold\\n * @dev Note: If there is not enough COMP, we do not perform the transfer all.\\n * @param user The address of the user to transfer COMP to\\n * @param userAccrued The amount of COMP to (possibly) transfer\\n * @return The amount of COMP which was NOT transferred to the user\\n */\\n function transferComp(address user, uint userAccrued, uint threshold) internal returns (uint) {\\n if (userAccrued >= threshold && userAccrued > 0) {\\n Comp comp = Comp(getCompAddress());\\n uint compRemaining = comp.balanceOf(address(this));\\n if (userAccrued <= compRemaining) {\\n comp.transfer(user, userAccrued);\\n return 0;\\n }\\n }\\n return userAccrued;\\n }\\n\\n /**\\n * @notice Claim all the comp accrued by holder in all markets\\n * @param holder The address to claim COMP for\\n */\\n function claimComp(address holder) public {\\n return claimComp(holder, allMarkets);\\n }\\n\\n /**\\n * @notice Claim all the comp accrued by holder in the specified markets\\n * @param holder The address to claim COMP for\\n * @param cTokens The list of markets to claim COMP in\\n */\\n function claimComp(address holder, CToken[] memory cTokens) public {\\n address[] memory holders = new address[](1);\\n holders[0] = holder;\\n claimComp(holders, cTokens, true, true);\\n }\\n\\n /**\\n * @notice Claim all comp accrued by the holders\\n * @param holders The addresses to claim COMP for\\n * @param cTokens The list of markets to claim COMP in\\n * @param borrowers Whether or not to claim COMP earned by borrowing\\n * @param suppliers Whether or not to claim COMP earned by supplying\\n */\\n function claimComp(address[] memory holders, CToken[] memory cTokens, bool borrowers, bool suppliers) public {\\n for (uint i = 0; i < cTokens.length; i++) {\\n CToken cToken = cTokens[i];\\n require(markets[address(cToken)].isListed, \\\"market must be listed\\\");\\n if (borrowers == true) {\\n Exp memory borrowIndex = Exp({mantissa: cToken.borrowIndex()});\\n updateCompBorrowIndex(address(cToken), borrowIndex);\\n for (uint j = 0; j < holders.length; j++) {\\n distributeBorrowerComp(address(cToken), holders[j], borrowIndex, true);\\n }\\n }\\n if (suppliers == true) {\\n updateCompSupplyIndex(address(cToken));\\n for (uint j = 0; j < holders.length; j++) {\\n distributeSupplierComp(address(cToken), holders[j], true);\\n }\\n }\\n }\\n }\\n\\n /*** Comp Distribution Admin ***/\\n\\n /**\\n * @notice Set the amount of COMP distributed per block\\n * @param compRate_ The amount of COMP wei per block to distribute\\n */\\n function _setCompRate(uint compRate_) public {\\n require(adminOrInitializing(), \\\"only admin can change comp rate\\\");\\n\\n uint oldRate = compRate;\\n compRate = compRate_;\\n emit NewCompRate(oldRate, compRate_);\\n\\n refreshCompSpeedsInternal();\\n }\\n\\n /**\\n * @notice Add markets to compMarkets, allowing them to earn COMP in the flywheel\\n * @param cTokens The addresses of the markets to add\\n */\\n function _addCompMarkets(address[] memory cTokens) public {\\n require(adminOrInitializing(), \\\"only admin can add comp market\\\");\\n\\n for (uint i = 0; i < cTokens.length; i++) {\\n _addCompMarketInternal(cTokens[i]);\\n }\\n\\n refreshCompSpeedsInternal();\\n }\\n\\n function _addCompMarketInternal(address cToken) internal {\\n Market storage market = markets[cToken];\\n require(market.isListed == true, \\\"comp market is not listed\\\");\\n require(market.isComped == false, \\\"comp market already added\\\");\\n\\n market.isComped = true;\\n emit MarketComped(CToken(cToken), true);\\n\\n if (compSupplyState[cToken].index == 0 && compSupplyState[cToken].block == 0) {\\n compSupplyState[cToken] = CompMarketState({\\n index: compInitialIndex,\\n block: safe32(getBlockNumber(), \\\"block number exceeds 32 bits\\\")\\n });\\n }\\n\\n if (compBorrowState[cToken].index == 0 && compBorrowState[cToken].block == 0) {\\n compBorrowState[cToken] = CompMarketState({\\n index: compInitialIndex,\\n block: safe32(getBlockNumber(), \\\"block number exceeds 32 bits\\\")\\n });\\n }\\n }\\n\\n /**\\n * @notice Remove a market from compMarkets, preventing it from earning COMP in the flywheel\\n * @param cToken The address of the market to drop\\n */\\n function _dropCompMarket(address cToken) public {\\n require(msg.sender == admin, \\\"only admin can drop comp market\\\");\\n\\n Market storage market = markets[cToken];\\n require(market.isComped == true, \\\"market is not a comp market\\\");\\n\\n market.isComped = false;\\n emit MarketComped(CToken(cToken), false);\\n\\n refreshCompSpeedsInternal();\\n }\\n\\n /**\\n * @notice Return all of the markets\\n * @dev The automatic getter may be used to access an individual market.\\n * @return The list of market addresses\\n */\\n function getAllMarkets() public view returns (CToken[] memory) {\\n return allMarkets;\\n }\\n\\n function getBlockNumber() public view returns (uint) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Return the address of the COMP token\\n * @return The address of COMP\\n */\\n function getCompAddress() public view returns (address) {\\n return 0xc00e94Cb662C3520282E6f5717214004A7f26888;\\n }\\n}\\n\",\"keccak256\":\"0x9d5ce154d0a488926be966885160d2ff0442cd067056d08ecae47d65b1979528\"},\"contracts/ComptrollerInterface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\ncontract ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n bool public constant isComptroller = true;\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata cTokens) external returns (uint[] memory);\\n function exitMarket(address cToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address cToken, address minter, uint mintAmount) external returns (uint);\\n function mintVerify(address cToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address cToken, address redeemer, uint redeemTokens) external returns (uint);\\n function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address cToken, address borrower, uint borrowAmount) external returns (uint);\\n function borrowVerify(address cToken, address borrower, uint borrowAmount) external;\\n\\n function repayBorrowAllowed(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount) external returns (uint);\\n function repayBorrowVerify(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex) external;\\n\\n function liquidateBorrowAllowed(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount) external returns (uint);\\n function liquidateBorrowVerify(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens) external;\\n\\n function seizeAllowed(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external returns (uint);\\n function seizeVerify(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external;\\n\\n function transferAllowed(address cToken, address src, address dst, uint transferTokens) external returns (uint);\\n function transferVerify(address cToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n uint repayAmount) external view returns (uint, uint);\\n}\\n\",\"keccak256\":\"0xede7670d2dd7b25d0187aecd2c28b7b5ca7d7c1bdac144fbedecf5d4bdd92a6b\"},\"contracts/ComptrollerStorage.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.sol\\\";\\nimport \\\"./PriceOracle.sol\\\";\\n\\ncontract UnitrollerAdminStorage {\\n /**\\n * @notice Administrator for this contract\\n */\\n address public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address public pendingAdmin;\\n\\n /**\\n * @notice Active brains of Unitroller\\n */\\n address public comptrollerImplementation;\\n\\n /**\\n * @notice Pending brains of Unitroller\\n */\\n address public pendingComptrollerImplementation;\\n}\\n\\ncontract ComptrollerV1Storage is UnitrollerAdminStorage {\\n\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n PriceOracle public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives\\n */\\n uint public liquidationIncentiveMantissa;\\n\\n /**\\n * @notice Max number of assets a single account can participate in (borrow or use as collateral)\\n */\\n uint public maxAssets;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\\n */\\n mapping(address => CToken[]) public accountAssets;\\n\\n}\\n\\ncontract ComptrollerV2Storage is ComptrollerV1Storage {\\n struct Market {\\n /// @notice Whether or not this market is listed\\n bool isListed;\\n\\n /**\\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\\n * For instance, 0.9 to allow borrowing 90% of collateral value.\\n * Must be between 0 and 1, and stored as a mantissa.\\n */\\n uint collateralFactorMantissa;\\n\\n /// @notice Per-market mapping of \\\"accounts in this asset\\\"\\n mapping(address => bool) accountMembership;\\n\\n /// @notice Whether or not this market receives COMP\\n bool isComped;\\n }\\n\\n /**\\n * @notice Official mapping of cTokens -> Market metadata\\n * @dev Used e.g. to determine if a market is supported\\n */\\n mapping(address => Market) public markets;\\n\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n * Actions which allow users to remove their own assets cannot be paused.\\n * Liquidation / seizing / transfer can only be paused globally, not by market.\\n */\\n address public pauseGuardian;\\n bool public _mintGuardianPaused;\\n bool public _borrowGuardianPaused;\\n bool public transferGuardianPaused;\\n bool public seizeGuardianPaused;\\n mapping(address => bool) public mintGuardianPaused;\\n mapping(address => bool) public borrowGuardianPaused;\\n}\\n\\ncontract ComptrollerV3Storage is ComptrollerV2Storage {\\n struct CompMarketState {\\n /// @notice The market's last updated compBorrowIndex or compSupplyIndex\\n uint224 index;\\n\\n /// @notice The block number the index was last updated at\\n uint32 block;\\n }\\n\\n /// @notice A list of all markets\\n CToken[] public allMarkets;\\n\\n /// @notice The rate at which the flywheel distributes COMP, per block\\n uint public compRate;\\n\\n /// @notice The portion of compRate that each market currently receives\\n mapping(address => uint) public compSpeeds;\\n\\n /// @notice The COMP market supply state for each market\\n mapping(address => CompMarketState) public compSupplyState;\\n\\n /// @notice The COMP market borrow state for each market\\n mapping(address => CompMarketState) public compBorrowState;\\n\\n /// @notice The COMP borrow index for each market for each supplier as of the last time they accrued COMP\\n mapping(address => mapping(address => uint)) public compSupplierIndex;\\n\\n /// @notice The COMP borrow index for each market for each borrower as of the last time they accrued COMP\\n mapping(address => mapping(address => uint)) public compBorrowerIndex;\\n\\n /// @notice The COMP accrued but not yet transferred to each user\\n mapping(address => uint) public compAccrued;\\n}\\n\\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\\n // @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\\n address public borrowCapGuardian;\\n\\n // @notice Borrow caps enforced by borrowAllowed for each cToken address. Defaults to zero which corresponds to unlimited borrowing.\\n mapping(address => uint) public borrowCaps;\\n}\\n\\ncontract ComptrollerV5Storage is ComptrollerV4Storage {\\n /// @notice The portion of COMP that each contributor receives per block\\n mapping(address => uint) public compContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's COMP rewards have been allocated\\n mapping(address => uint) public lastContributorBlock;\\n}\\n\",\"keccak256\":\"0x5db970485549f493618b5e36bfd4d799d4f8701a136bf71ed6e0117e1ed8c254\"},\"contracts/EIP20Interface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title ERC 20 Token Standard Interface\\n * https://eips.ethereum.org/EIPS/eip-20\\n */\\ninterface EIP20Interface {\\n function name() external view returns (string memory);\\n function symbol() external view returns (string memory);\\n function decimals() external view returns (uint8);\\n\\n /**\\n * @notice Get the total number of tokens in circulation\\n * @return The supply of tokens\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @notice Gets the balance of the specified address\\n * @param owner The address from which the balance will be retrieved\\n * @return The balance\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transfer(address dst, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferFrom(address src, address dst, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (-1 means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (-1 means infinite)\\n */\\n function allowance(address owner, address spender) external view returns (uint256 remaining);\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n}\\n\",\"keccak256\":\"0xfd8ed2eac6d0b4d9ee6b32628ba68bae17544b66f190a5f7ce0c6ad024579dc8\"},\"contracts/EIP20NonStandardInterface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title EIP20NonStandardInterface\\n * @dev Version of ERC20 with no return values for `transfer` and `transferFrom`\\n * See https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\\n */\\ninterface EIP20NonStandardInterface {\\n\\n /**\\n * @notice Get the total number of tokens in circulation\\n * @return The supply of tokens\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @notice Gets the balance of the specified address\\n * @param owner The address from which the balance will be retrieved\\n * @return The balance\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n ///\\n /// !!!!!!!!!!!!!!\\n /// !!! NOTICE !!! `transfer` does not return a value, in violation of the ERC-20 specification\\n /// !!!!!!!!!!!!!!\\n ///\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n */\\n function transfer(address dst, uint256 amount) external;\\n\\n ///\\n /// !!!!!!!!!!!!!!\\n /// !!! NOTICE !!! `transferFrom` does not return a value, in violation of the ERC-20 specification\\n /// !!!!!!!!!!!!!!\\n ///\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n */\\n function transferFrom(address src, address dst, uint256 amount) external;\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent\\n */\\n function allowance(address owner, address spender) external view returns (uint256 remaining);\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n}\\n\",\"keccak256\":\"0x9719f12e4b80b51147ac195553a198cf8b0c516e7e4d04fc324a23ed15cbafb2\"},\"contracts/ErrorReporter.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\ncontract ComptrollerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\",\"keccak256\":\"0x5179afb1071c0fd555e5c1f1d2565f72dbe1740cc3dd02f6e52037f150afc5c9\"},\"contracts/Exponential.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CarefulMath.sol\\\";\\nimport \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @dev Legacy contract for compatibility reasons with existing contracts that still use MathError\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: rational}));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({mantissa: result}));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({mantissa: result}));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: scaledMantissa}));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: descaledMantissa}));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) pure internal returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({mantissa: 0}));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({mantissa: product}));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) pure internal returns (MathError, Exp memory) {\\n return mulExp(Exp({mantissa: a}), Exp({mantissa: b}));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) pure internal returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6ff054d65a0289dbb43c9f437d6909f9cf1207c9b8f984b3cb8e97a9de76a434\"},\"contracts/ExponentialNoError.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\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 Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) pure internal returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) pure internal returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) pure internal returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) pure internal returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) pure internal returns (uint224) {\\n require(n < 2**224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) pure internal returns (uint32) {\\n require(n < 2**32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: add_(a.mantissa, b.mantissa)});\\n }\\n\\n function add_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: add_(a.mantissa, b.mantissa)});\\n }\\n\\n function add_(uint a, uint b) pure internal returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: sub_(a.mantissa, b.mantissa)});\\n }\\n\\n function sub_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: sub_(a.mantissa, b.mantissa)});\\n }\\n\\n function sub_(uint a, uint b) pure internal returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: mul_(a.mantissa, b.mantissa) / expScale});\\n }\\n\\n function mul_(Exp memory a, uint b) pure internal returns (Exp memory) {\\n return Exp({mantissa: mul_(a.mantissa, b)});\\n }\\n\\n function mul_(uint a, Exp memory b) pure internal returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: mul_(a.mantissa, b.mantissa) / doubleScale});\\n }\\n\\n function mul_(Double memory a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: mul_(a.mantissa, b)});\\n }\\n\\n function mul_(uint a, Double memory b) pure internal returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) pure internal returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) pure internal 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) pure internal returns (Exp memory) {\\n return Exp({mantissa: div_(mul_(a.mantissa, expScale), b.mantissa)});\\n }\\n\\n function div_(Exp memory a, uint b) pure internal returns (Exp memory) {\\n return Exp({mantissa: div_(a.mantissa, b)});\\n }\\n\\n function div_(uint a, Exp memory b) pure internal returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa)});\\n }\\n\\n function div_(Double memory a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(a.mantissa, b)});\\n }\\n\\n function div_(uint a, Double memory b) pure internal returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) pure internal returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(mul_(a, doubleScale), b)});\\n }\\n}\\n\",\"keccak256\":\"0x7cb184b7cee71a5e707053dfba7eebbd46f11974004028100510ccce19b6694d\"},\"contracts/Governance/Comp.sol\":{\"content\":\"pragma solidity ^0.5.16;\\npragma experimental ABIEncoderV2;\\n\\ncontract Comp {\\n /// @notice EIP-20 token name for this token\\n string public constant name = \\\"Compound\\\";\\n\\n /// @notice EIP-20 token symbol for this token\\n string public constant symbol = \\\"COMP\\\";\\n\\n /// @notice EIP-20 token decimals for this token\\n uint8 public constant decimals = 18;\\n\\n /// @notice Total number of tokens in circulation\\n uint public constant totalSupply = 10000000e18; // 10 million Comp\\n\\n /// @notice Allowance amounts on behalf of others\\n mapping (address => mapping (address => uint96)) internal allowances;\\n\\n /// @notice Official record of token balances for each account\\n mapping (address => uint96) internal balances;\\n\\n /// @notice A record of each accounts delegate\\n mapping (address => address) public delegates;\\n\\n /// @notice A checkpoint for marking number of votes from a given block\\n struct Checkpoint {\\n uint32 fromBlock;\\n uint96 votes;\\n }\\n\\n /// @notice A record of votes checkpoints for each account, by index\\n mapping (address => mapping (uint32 => Checkpoint)) public checkpoints;\\n\\n /// @notice The number of checkpoints for each account\\n mapping (address => uint32) public numCheckpoints;\\n\\n /// @notice The EIP-712 typehash for the contract's domain\\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\\\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\\\");\\n\\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\\\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\\\");\\n\\n /// @notice A record of states for signing / validating signatures\\n mapping (address => uint) public nonces;\\n\\n /// @notice An event thats emitted when an account changes its delegate\\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\\n\\n /// @notice An event thats emitted when a delegate account's vote balance changes\\n event DelegateVotesChanged(address indexed delegate, uint previousBalance, uint newBalance);\\n\\n /// @notice The standard EIP-20 transfer event\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n\\n /// @notice The standard EIP-20 approval event\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n\\n /**\\n * @notice Construct a new Comp token\\n * @param account The initial account to grant all the tokens\\n */\\n constructor(address account) public {\\n balances[account] = uint96(totalSupply);\\n emit Transfer(address(0), account, totalSupply);\\n }\\n\\n /**\\n * @notice Get the number of tokens `spender` is approved to spend on behalf of `account`\\n * @param account The address of the account holding the funds\\n * @param spender The address of the account spending the funds\\n * @return The number of tokens approved\\n */\\n function allowance(address account, address spender) external view returns (uint) {\\n return allowances[account][spender];\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param rawAmount The number of tokens that are approved (2^256-1 means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint rawAmount) external returns (bool) {\\n uint96 amount;\\n if (rawAmount == uint(-1)) {\\n amount = uint96(-1);\\n } else {\\n amount = safe96(rawAmount, \\\"Comp::approve: amount exceeds 96 bits\\\");\\n }\\n\\n allowances[msg.sender][spender] = amount;\\n\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the number of tokens held by the `account`\\n * @param account The address of the account to get the balance of\\n * @return The number of tokens held\\n */\\n function balanceOf(address account) external view returns (uint) {\\n return balances[account];\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param rawAmount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transfer(address dst, uint rawAmount) external returns (bool) {\\n uint96 amount = safe96(rawAmount, \\\"Comp::transfer: amount exceeds 96 bits\\\");\\n _transferTokens(msg.sender, dst, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param rawAmount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferFrom(address src, address dst, uint rawAmount) external returns (bool) {\\n address spender = msg.sender;\\n uint96 spenderAllowance = allowances[src][spender];\\n uint96 amount = safe96(rawAmount, \\\"Comp::approve: amount exceeds 96 bits\\\");\\n\\n if (spender != src && spenderAllowance != uint96(-1)) {\\n uint96 newAllowance = sub96(spenderAllowance, amount, \\\"Comp::transferFrom: transfer amount exceeds spender allowance\\\");\\n allowances[src][spender] = newAllowance;\\n\\n emit Approval(src, spender, newAllowance);\\n }\\n\\n _transferTokens(src, dst, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Delegate votes from `msg.sender` to `delegatee`\\n * @param delegatee The address to delegate votes to\\n */\\n function delegate(address delegatee) public {\\n return _delegate(msg.sender, delegatee);\\n }\\n\\n /**\\n * @notice Delegates votes from signatory to `delegatee`\\n * @param delegatee The address to delegate votes to\\n * @param nonce The contract state required to match the signature\\n * @param expiry The time at which to expire the signature\\n * @param v The recovery byte of the signature\\n * @param r Half of the ECDSA signature pair\\n * @param s Half of the ECDSA signature pair\\n */\\n function delegateBySig(address delegatee, uint nonce, uint expiry, uint8 v, bytes32 r, bytes32 s) public {\\n bytes32 domainSeparator = keccak256(abi.encode(DOMAIN_TYPEHASH, keccak256(bytes(name)), getChainId(), address(this)));\\n bytes32 structHash = keccak256(abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry));\\n bytes32 digest = keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash));\\n address signatory = ecrecover(digest, v, r, s);\\n require(signatory != address(0), \\\"Comp::delegateBySig: invalid signature\\\");\\n require(nonce == nonces[signatory]++, \\\"Comp::delegateBySig: invalid nonce\\\");\\n require(now <= expiry, \\\"Comp::delegateBySig: signature expired\\\");\\n return _delegate(signatory, delegatee);\\n }\\n\\n /**\\n * @notice Gets the current votes balance for `account`\\n * @param account The address to get votes balance\\n * @return The number of current votes for `account`\\n */\\n function getCurrentVotes(address account) external view returns (uint96) {\\n uint32 nCheckpoints = numCheckpoints[account];\\n return nCheckpoints > 0 ? checkpoints[account][nCheckpoints - 1].votes : 0;\\n }\\n\\n /**\\n * @notice Determine the prior number of votes for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param account The address of the account to check\\n * @param blockNumber The block number to get the vote balance at\\n * @return The number of votes the account had as of the given block\\n */\\n function getPriorVotes(address account, uint blockNumber) public view returns (uint96) {\\n require(blockNumber < block.number, \\\"Comp::getPriorVotes: not yet determined\\\");\\n\\n uint32 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (checkpoints[account][nCheckpoints - 1].fromBlock <= blockNumber) {\\n return checkpoints[account][nCheckpoints - 1].votes;\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[account][0].fromBlock > blockNumber) {\\n return 0;\\n }\\n\\n uint32 lower = 0;\\n uint32 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[account][center];\\n if (cp.fromBlock == blockNumber) {\\n return cp.votes;\\n } else if (cp.fromBlock < blockNumber) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return checkpoints[account][lower].votes;\\n }\\n\\n function _delegate(address delegator, address delegatee) internal {\\n address currentDelegate = delegates[delegator];\\n uint96 delegatorBalance = balances[delegator];\\n delegates[delegator] = delegatee;\\n\\n emit DelegateChanged(delegator, currentDelegate, delegatee);\\n\\n _moveDelegates(currentDelegate, delegatee, delegatorBalance);\\n }\\n\\n function _transferTokens(address src, address dst, uint96 amount) internal {\\n require(src != address(0), \\\"Comp::_transferTokens: cannot transfer from the zero address\\\");\\n require(dst != address(0), \\\"Comp::_transferTokens: cannot transfer to the zero address\\\");\\n\\n balances[src] = sub96(balances[src], amount, \\\"Comp::_transferTokens: transfer amount exceeds balance\\\");\\n balances[dst] = add96(balances[dst], amount, \\\"Comp::_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 && amount > 0) {\\n if (srcRep != address(0)) {\\n uint32 srcRepNum = numCheckpoints[srcRep];\\n uint96 srcRepOld = srcRepNum > 0 ? checkpoints[srcRep][srcRepNum - 1].votes : 0;\\n uint96 srcRepNew = sub96(srcRepOld, amount, \\\"Comp::_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 > 0 ? checkpoints[dstRep][dstRepNum - 1].votes : 0;\\n uint96 dstRepNew = add96(dstRepOld, amount, \\\"Comp::_moveVotes: vote amount overflows\\\");\\n _writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew);\\n }\\n }\\n }\\n\\n function _writeCheckpoint(address delegatee, uint32 nCheckpoints, uint96 oldVotes, uint96 newVotes) internal {\\n uint32 blockNumber = safe32(block.number, \\\"Comp::_writeCheckpoint: block number exceeds 32 bits\\\");\\n\\n if (nCheckpoints > 0 && checkpoints[delegatee][nCheckpoints - 1].fromBlock == blockNumber) {\\n checkpoints[delegatee][nCheckpoints - 1].votes = newVotes;\\n } else {\\n checkpoints[delegatee][nCheckpoints] = Checkpoint(blockNumber, newVotes);\\n numCheckpoints[delegatee] = nCheckpoints + 1;\\n }\\n\\n emit DelegateVotesChanged(delegatee, oldVotes, newVotes);\\n }\\n\\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\\n require(n < 2**32, errorMessage);\\n return uint32(n);\\n }\\n\\n function safe96(uint n, string memory errorMessage) internal pure returns (uint96) {\\n require(n < 2**96, errorMessage);\\n return uint96(n);\\n }\\n\\n function add96(uint96 a, uint96 b, string memory errorMessage) internal pure returns (uint96) {\\n uint96 c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub96(uint96 a, uint96 b, string memory errorMessage) internal pure returns (uint96) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function getChainId() internal pure returns (uint) {\\n uint256 chainId;\\n assembly { chainId := chainid() }\\n return chainId;\\n }\\n}\\n\",\"keccak256\":\"0x539f7158013dd91efd3ad42dc6a56e0f7aebdca06063d40ce7b6e9a981b726a3\"},\"contracts/InterestRateModel.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Compound's InterestRateModel Interface\\n * @author Compound\\n */\\ncontract InterestRateModel {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint cash, uint borrows, uint reserves) external view returns (uint);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) external view returns (uint);\\n\\n}\\n\",\"keccak256\":\"0x929282d73c79e6d700ebe79f9fafc1e414b3848acff5a56d6740afd1dc908678\"},\"contracts/PriceOracle.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.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 cToken asset\\n * @param cToken The cToken to get the underlying price of\\n * @return The underlying asset price mantissa (scaled by 1e18).\\n * Zero means the price is unavailable.\\n */\\n function getUnderlyingPrice(CToken cToken) external view returns (uint);\\n}\\n\",\"keccak256\":\"0xe79ebc23bba508eb2479e7b3340abf566da1ab62131f106aee1aac3dc53816ef\"},\"contracts/Unitroller.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ErrorReporter.sol\\\";\\nimport \\\"./ComptrollerStorage.sol\\\";\\n/**\\n * @title ComptrollerCore\\n * @dev Storage for the comptroller is at this address, while execution is delegated to the `comptrollerImplementation`.\\n * CTokens should reference this contract as their comptroller.\\n */\\ncontract Unitroller is UnitrollerAdminStorage, ComptrollerErrorReporter {\\n\\n /**\\n * @notice Emitted when pendingComptrollerImplementation is changed\\n */\\n event NewPendingImplementation(address oldPendingImplementation, address newPendingImplementation);\\n\\n /**\\n * @notice Emitted when pendingComptrollerImplementation is accepted, which means comptroller implementation is updated\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Emitted when pendingAdmin is accepted, which means admin is updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n constructor() public {\\n // Set admin to caller\\n admin = msg.sender;\\n }\\n\\n /*** Admin Functions ***/\\n function _setPendingImplementation(address newPendingImplementation) public returns (uint) {\\n\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_IMPLEMENTATION_OWNER_CHECK);\\n }\\n\\n address oldPendingImplementation = pendingComptrollerImplementation;\\n\\n pendingComptrollerImplementation = newPendingImplementation;\\n\\n emit NewPendingImplementation(oldPendingImplementation, pendingComptrollerImplementation);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts new implementation of comptroller. msg.sender must be pendingImplementation\\n * @dev Admin function for new implementation to accept it's role as implementation\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptImplementation() public returns (uint) {\\n // Check caller is pendingImplementation and pendingImplementation \\u2260 address(0)\\n if (msg.sender != pendingComptrollerImplementation || pendingComptrollerImplementation == address(0)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldImplementation = comptrollerImplementation;\\n address oldPendingImplementation = pendingComptrollerImplementation;\\n\\n comptrollerImplementation = pendingComptrollerImplementation;\\n\\n pendingComptrollerImplementation = address(0);\\n\\n emit NewImplementation(oldImplementation, comptrollerImplementation);\\n emit NewPendingImplementation(oldPendingImplementation, pendingComptrollerImplementation);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPendingAdmin(address newPendingAdmin) public returns (uint) {\\n // Check caller = admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\\n }\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptAdmin() public returns (uint) {\\n // Check caller is pendingAdmin and pendingAdmin \\u2260 address(0)\\n if (msg.sender != pendingAdmin || msg.sender == address(0)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = address(0);\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return 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 () payable external {\\n // delegate all other functions to current implementation\\n (bool success, ) = comptrollerImplementation.delegatecall(msg.data);\\n\\n assembly {\\n let free_mem_ptr := mload(0x40)\\n returndatacopy(free_mem_ptr, 0, returndatasize)\\n\\n switch success\\n case 0 { revert(free_mem_ptr, returndatasize) }\\n default { return(free_mem_ptr, returndatasize) }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x51f81451eab9d5c4849507e724f2b2c53e41f54e5359fdbeae89432a727c16df\"},\"tests/Contracts/ComptrollerScenarioG5.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"../../contracts/ComptrollerG5.sol\\\";\\n\\ncontract ComptrollerScenarioG5 is ComptrollerG5 {\\n uint public blockNumber;\\n address public compAddress;\\n\\n constructor() ComptrollerG5() public {}\\n\\n function setCompAddress(address compAddress_) public {\\n compAddress = compAddress_;\\n }\\n\\n function getCompAddress() public view returns (address) {\\n return compAddress;\\n }\\n\\n function membershipLength(CToken cToken) public view returns (uint) {\\n return accountAssets[address(cToken)].length;\\n }\\n\\n function fastForward(uint blocks) public returns (uint) {\\n blockNumber += blocks;\\n\\n return blockNumber;\\n }\\n\\n function setBlockNumber(uint number) public {\\n blockNumber = number;\\n }\\n\\n function getBlockNumber() public view returns (uint) {\\n return blockNumber;\\n }\\n\\n function getCompMarkets() public view returns (address[] memory) {\\n uint m = allMarkets.length;\\n uint n = 0;\\n for (uint i = 0; i < m; i++) {\\n if (markets[address(allMarkets[i])].isComped) {\\n n++;\\n }\\n }\\n\\n address[] memory compMarkets = new address[](n);\\n uint k = 0;\\n for (uint i = 0; i < m; i++) {\\n if (markets[address(allMarkets[i])].isComped) {\\n compMarkets[k++] = address(allMarkets[i]);\\n }\\n }\\n return compMarkets;\\n }\\n\\n function unlist(CToken cToken) public {\\n markets[address(cToken)].isListed = false;\\n }\\n}\\n\",\"keccak256\":\"0x7ce585b8ede5e3f22561d5dfb8ce30500c961cde92a2888ed1780557a9fdb16b\"}},\"version\":1}" + }, + "tests/Contracts/ComptrollerScenarioG6.sol:ComptrollerScenarioG6": { + "abi": "[{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"action\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"pauseState\",\"type\":\"bool\"}],\"name\":\"ActionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"action\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"pauseState\",\"type\":\"bool\"}],\"name\":\"ActionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"CompGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSpeed\",\"type\":\"uint256\"}],\"name\":\"CompSpeedUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"contributor\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSpeed\",\"type\":\"uint256\"}],\"name\":\"ContributorCompSpeedUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compBorrowIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedBorrowerComp\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"supplier\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compSupplyIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedSupplierComp\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isComped\",\"type\":\"bool\"}],\"name\":\"MarketComped\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketEntered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketExited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"MarketListed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newBorrowCap\",\"type\":\"uint256\"}],\"name\":\"NewBorrowCap\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldBorrowCapGuardian\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newBorrowCapGuardian\",\"type\":\"address\"}],\"name\":\"NewBorrowCapGuardian\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCloseFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCloseFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCollateralFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCollateralFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCompRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCompRate\",\"type\":\"uint256\"}],\"name\":\"NewCompRate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldLiquidationIncentiveMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"NewLiquidationIncentive\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldPauseGuardian\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"NewPauseGuardian\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"oldPriceOracle\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"newPriceOracle\",\"type\":\"address\"}],\"name\":\"NewPriceOracle\",\"type\":\"event\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"_addCompMarkets\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract Unitroller\",\"name\":\"unitroller\",\"type\":\"address\"}],\"name\":\"_become\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"_dropCompMarket\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"_grantComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"newBorrowCapGuardian\",\"type\":\"address\"}],\"name\":\"_setBorrowCapGuardian\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setBorrowPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCloseFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCollateralFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"compRate_\",\"type\":\"uint256\"}],\"name\":\"_setCompRate\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"contributor\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"compSpeed\",\"type\":\"uint256\"}],\"name\":\"_setContributorCompSpeed\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"_setLiquidationIncentive\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"cTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"newBorrowCaps\",\"type\":\"uint256[]\"}],\"name\":\"_setMarketBorrowCaps\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setMintPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"_setPauseGuardian\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"newOracle\",\"type\":\"address\"}],\"name\":\"_setPriceOracle\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setSeizePaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setTransferPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"_supportMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allMarkets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"blockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"borrowCapGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"checkMembership\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"},{\"internalType\":\"contract CToken[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"holders\",\"type\":\"address[]\"},{\"internalType\":\"contract CToken[]\",\"name\":\"cTokens\",\"type\":\"address[]\"},{\"internalType\":\"bool\",\"name\":\"borrowers\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"suppliers\",\"type\":\"bool\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compAccrued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compBorrowState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compBorrowerIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compClaimThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compContributorSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compInitialIndex\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSupplierIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSupplyState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"enterMarkets\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenAddress\",\"type\":\"address\"}],\"name\":\"exitMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blocks\",\"type\":\"uint256\"}],\"name\":\"fastForward\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getAllMarkets\",\"outputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAssetsIn\",\"outputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getCompAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenModify\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"getHypotheticalAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"isComptroller\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"lastContributorBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateCalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"liquidationIncentiveMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"markets\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isComped\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"membershipLength\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"mintAmount\",\"type\":\"uint256\"}],\"name\":\"mintAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualMintAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"mintTokens\",\"type\":\"uint256\"}],\"name\":\"mintVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"refreshCompSpeeds\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"repayBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowerIndex\",\"type\":\"uint256\"}],\"name\":\"repayBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"seizeGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"}],\"name\":\"setBlockNumber\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"compAddress_\",\"type\":\"address\"}],\"name\":\"setCompAddress\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"compSpeed\",\"type\":\"uint256\"}],\"name\":\"setCompSpeed\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"transferGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"unlist\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"contributor\",\"type\":\"address\"}],\"name\":\"updateContributorRewards\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + "bin": "608060405234801561001057600080fd5b50600080546001600160a01b03191633179055615fb680620000336000396000f3fe608060405234801561001057600080fd5b50600436106104cc5760003560e01c8063731f0c2b11610283578063bb82aa5e1161015c578063dce15449116100ce578063e875544611610092578063e875544614611404578063e9af02921461140c578063eabe7d9114611432578063ede4edd014611468578063f851a4401461148e578063fccbe7f614611496576104cc565b8063dce1544914611370578063dcfbc0c71461139c578063e4028eee146113a4578063e6653f3d146113d0578063e6d8c252146113d8576104cc565b8063c488847b11610120578063c488847b146111b0578063ca0af043146111ff578063cc7ebdc41461122d578063ce485c5e14611253578063d02f7351146112f4578063da3d454c1461133a576104cc565b8063bb82aa5e1461107f578063bdcdc25814611087578063bde3672d146110c3578063bea6b8b8146110e9578063c29982381461110f576104cc565b806394b2294b116101f5578063a8c3c850116101b9578063a8c3c85014610fa6578063aa90075414610fc3578063abfceffc14610fcb578063ac0b0bb714611041578063b0772d0b14611049578063b21be7fd14611051576104cc565b806394b2294b14610f26578063986ab83814610f2e5780639d1b5a0a14610f54578063a76b3fda14610f5c578063a7f0e23114610f82576104cc565b8063858aa5e511610247578063858aa5e514610e3d57806387f7630314610e635780638c57804e14610e6b5780638e8f294b14610e915780638ebf636414610ed9578063929fe9a114610ef8576104cc565b8063731f0c2b14610dd9578063741b252514610dff578063747026c914610e255780637d3ab61a14610e2d5780637dc0d1d014610e35576104cc565b80634ada90af116103b55780635c778605116103275780636810dfa6116102eb5780636810dfa614610b9a5780636a49111214610cc65780636a56947e14610ce35780636b79c38d14610d1f5780636d154ea514610d6d5780636d35bf9114610d93576104cc565b80635c77860514610a145780635ec88c7914610a4a5780635f5af1aa14610a705780635fc7e71e14610a96578063607ef6c114610adc576104cc565b80634fd42e17116103795780634fd42e171461094457806351dff9891461096157806352d84d1e1461099d57806355ee1fe1146109ba57806357e871e7146109e0578063598ee1cb146109e8576104cc565b80634ada90af1461087e5780634bca0d8c146108865780634d8e5037146108ac5780634e79238f146108b45780634ef4c3e11461090e576104cc565b806327efe3cb1161044e5780633bcf7ec1116104125780633bcf7ec1146107925780633c94786f146107c057806341c728b9146107c857806342cbb15c1461080457806347ef3b3b1461080c5780634a58443214610858576104cc565b806327efe3cb146106de5780632d70db781461070a578063317b0b7714610729578063391957d7146107465780633aa729b41461076c576104cc565b80631ededc91116104955780631ededc911461062c57806321af45691461066e57806324008a621461069257806324a3d622146106ce57806326782247146106d6576104cc565b80627e3dd2146104d157806318c882a5146104ed5780631c3db2e01461051b5780631d504dc6146105ce5780631d7b33d7146105f4575b600080fd5b6104d96114b3565b604080519115158252519081900360200190f35b6104d96004803603604081101561050357600080fd5b506001600160a01b03813516906020013515156114b8565b6105cc6004803603604081101561053157600080fd5b6001600160a01b038235169190810190604081016020820135600160201b81111561055b57600080fd5b82018360208201111561056d57600080fd5b803590602001918460208302840111600160201b8311171561058e57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550611658945050505050565b005b6105cc600480360360208110156105e457600080fd5b50356001600160a01b03166116ba565b61061a6004803603602081101561060a57600080fd5b50356001600160a01b0316611819565b60408051918252519081900360200190f35b6105cc600480360360a081101561064257600080fd5b506001600160a01b0381358116916020810135821691604082013516906060810135906080013561182b565b610676611832565b604080516001600160a01b039092168252519081900360200190f35b61061a600480360360808110156106a857600080fd5b506001600160a01b03813581169160208101358216916040820135169060600135611841565b61067661190a565b610676611919565b6105cc600480360360408110156106f457600080fd5b506001600160a01b038135169060200135611928565b6104d96004803603602081101561072057600080fd5b50351515611a2b565b61061a6004803603602081101561073f57600080fd5b5035611b65565b6105cc6004803603602081101561075c57600080fd5b50356001600160a01b0316611c12565b6105cc6004803603602081101561078257600080fd5b50356001600160a01b0316611cbe565b6104d9600480360360408110156107a857600080fd5b506001600160a01b0381351690602001351515611def565b6104d9611f8a565b6105cc600480360360808110156107de57600080fd5b506001600160a01b03813581169160208101359091169060408101359060600135611f9a565b61061a611fa0565b6105cc600480360360c081101561082257600080fd5b506001600160a01b0381358116916020810135821691604082013581169160608101359091169060808101359060a00135611fa7565b61061a6004803603602081101561086e57600080fd5b50356001600160a01b0316611faf565b61061a611fc1565b61061a6004803603602081101561089c57600080fd5b50356001600160a01b0316611fc7565b6105cc611fe2565b6108f0600480360360808110156108ca57600080fd5b506001600160a01b0381358116916020810135909116906040810135906060013561202a565b60408051938452602084019290925282820152519081900360600190f35b61061a6004803603606081101561092457600080fd5b506001600160a01b03813581169160208101359091169060400135612064565b61061a6004803603602081101561095a57600080fd5b503561210c565b6105cc6004803603608081101561097757600080fd5b506001600160a01b0381358116916020810135909116906040810135906060013561217c565b610676600480360360208110156109b357600080fd5b50356121d0565b61061a600480360360208110156109d057600080fd5b50356001600160a01b03166121f7565b61061a61227c565b6105cc600480360360408110156109fe57600080fd5b506001600160a01b038135169060200135612282565b6105cc60048036036060811015610a2a57600080fd5b506001600160a01b0381358116916020810135909116906040013561236d565b6108f060048036036020811015610a6057600080fd5b50356001600160a01b0316612372565b61061a60048036036020811015610a8657600080fd5b50356001600160a01b03166123a7565b61061a600480360360a0811015610aac57600080fd5b506001600160a01b038135811691602081013582169160408201358116916060810135909116906080013561242b565b6105cc60048036036040811015610af257600080fd5b810190602081018135600160201b811115610b0c57600080fd5b820183602082011115610b1e57600080fd5b803590602001918460208302840111600160201b83111715610b3f57600080fd5b919390929091602081019035600160201b811115610b5c57600080fd5b820183602082011115610b6e57600080fd5b803590602001918460208302840111600160201b83111715610b8f57600080fd5b509092509050612590565b6105cc60048036036080811015610bb057600080fd5b810190602081018135600160201b811115610bca57600080fd5b820183602082011115610bdc57600080fd5b803590602001918460208302840111600160201b83111715610bfd57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b811115610c4c57600080fd5b820183602082011115610c5e57600080fd5b803590602001918460208302840111600160201b83111715610c7f57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550505050803515159150602001351515612720565b6105cc60048036036020811015610cdc57600080fd5b50356128c9565b6105cc60048036036080811015610cf957600080fd5b506001600160a01b03813581169160208101358216916040820135169060600135611f9a565b610d4560048036036020811015610d3557600080fd5b50356001600160a01b031661296d565b604080516001600160e01b03909316835263ffffffff90911660208301528051918290030190f35b6104d960048036036020811015610d8357600080fd5b50356001600160a01b0316612997565b6105cc600480360360a0811015610da957600080fd5b506001600160a01b038135811691602081013582169160408201358116916060810135909116906080013561182b565b6104d960048036036020811015610def57600080fd5b50356001600160a01b03166129ac565b6105cc60048036036020811015610e1557600080fd5b50356001600160a01b03166129c1565b61061a612a84565b610676612a8f565b610676612a9e565b6105cc60048036036020811015610e5357600080fd5b50356001600160a01b0316612aad565b6104d9612acf565b610d4560048036036020811015610e8157600080fd5b50356001600160a01b0316612adf565b610eb760048036036020811015610ea757600080fd5b50356001600160a01b0316612b09565b6040805193151584526020840192909252151582820152519081900360600190f35b6104d960048036036020811015610eef57600080fd5b50351515612b2f565b6104d960048036036040811015610f0e57600080fd5b506001600160a01b0381358116916020013516612c68565b61061a612c9b565b61061a60048036036020811015610f4457600080fd5b50356001600160a01b0316612ca1565b610676612cb3565b61061a60048036036020811015610f7257600080fd5b50356001600160a01b0316612cc2565b610f8a612e1f565b604080516001600160e01b039092168252519081900360200190f35b6105cc60048036036020811015610fbc57600080fd5b5035612e32565b61061a612e37565b610ff160048036036020811015610fe157600080fd5b50356001600160a01b0316612e3d565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561102d578181015183820152602001611015565b505050509050019250505060405180910390f35b6104d9612ec6565b610ff1612ed6565b61061a6004803603604081101561106757600080fd5b506001600160a01b0381358116916020013516612f38565b610676612f55565b61061a6004803603608081101561109d57600080fd5b506001600160a01b03813581169160208101358216916040820135169060600135612f64565b6105cc600480360360208110156110d957600080fd5b50356001600160a01b0316612ff8565b61061a600480360360208110156110ff57600080fd5b50356001600160a01b0316613019565b610ff16004803603602081101561112557600080fd5b810190602081018135600160201b81111561113f57600080fd5b82018360208201111561115157600080fd5b803590602001918460208302840111600160201b8311171561117257600080fd5b91908080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525092955061302b945050505050565b6111e6600480360360608110156111c657600080fd5b506001600160a01b038135811691602081013590911690604001356130c2565b6040805192835260208301919091528051918290030190f35b61061a6004803603604081101561121557600080fd5b506001600160a01b03813581169160200135166132ea565b61061a6004803603602081101561124357600080fd5b50356001600160a01b0316613307565b6105cc6004803603602081101561126957600080fd5b810190602081018135600160201b81111561128357600080fd5b82018360208201111561129557600080fd5b803590602001918460208302840111600160201b831117156112b657600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550613319945050505050565b61061a600480360360a081101561130a57600080fd5b506001600160a01b03813581169160208101358216916040820135811691606081013590911690608001356133ab565b61061a6004803603606081101561135057600080fd5b506001600160a01b03813581169160208101359091169060400135613563565b6106766004803603604081101561138657600080fd5b506001600160a01b03813516906020013561393f565b610676613974565b61061a600480360360408110156113ba57600080fd5b506001600160a01b038135169060200135613983565b6104d9613b33565b6105cc600480360360408110156113ee57600080fd5b506001600160a01b038135169060200135613b43565b61061a613b5f565b6105cc6004803603602081101561142257600080fd5b50356001600160a01b0316613b65565b61061a6004803603606081101561144857600080fd5b506001600160a01b03813581169160208101359091169060400135613bc9565b61061a6004803603602081101561147e57600080fd5b50356001600160a01b0316613c06565b610676613f19565b61061a600480360360208110156114ac57600080fd5b5035613f28565b600181565b6001600160a01b03821660009081526009602052604081205460ff1661150f5760405162461bcd60e51b8152600401808060200182810382526028815260200180615e3b6028913960400191505060405180910390fd5b600a546001600160a01b031633148061153257506000546001600160a01b031633145b61156d5760405162461bcd60e51b8152600401808060200182810382526027815260200180615e946027913960400191505060405180910390fd5b6000546001600160a01b031633148061158857506001821515145b6115d2576040805162461bcd60e51b81526020600482015260166024820152756f6e6c792061646d696e2063616e20756e706175736560501b604482015290519081900360640190fd5b6001600160a01b0383166000818152600c6020908152604091829020805486151560ff199091168117909155825193845283830152606090830181905260069083015265426f72726f7760d01b6080830152517f71aec636243f9709bb0007ae15e9afb8150ab01716d75fd7573be5cc096e03b09181900360a00190a150805b92915050565b60408051600180825281830190925260609160208083019080388339019050509050828160008151811061168857fe5b60200260200101906001600160a01b031690816001600160a01b0316815250506116b58183600180612720565b505050565b806001600160a01b031663f851a4406040518163ffffffff1660e01b815260040160206040518083038186803b1580156116f357600080fd5b505afa158015611707573d6000803e3d6000fd5b505050506040513d602081101561171d57600080fd5b50516001600160a01b031633146117655760405162461bcd60e51b8152600401808060200182810382526027815260200180615f5b6027913960400191505060405180910390fd5b806001600160a01b031663c1e803346040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156117a057600080fd5b505af11580156117b4573d6000803e3d6000fd5b505050506040513d60208110156117ca57600080fd5b505115611816576040805162461bcd60e51b815260206004820152601560248201527418da185b99d9481b9bdd08185d5d1a1bdc9a5e9959605a1b604482015290519081900360640190fd5b50565b600f6020526000908152604090205481565b5050505050565b6015546001600160a01b031681565b6001600160a01b03841660009081526009602052604081205460ff1661186957506009611902565b611871615d7b565b6040518060200160405280876001600160a01b031663aa5af0fd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156118b557600080fd5b505afa1580156118c9573d6000803e3d6000fd5b505050506040513d60208110156118df57600080fd5b5051905290506118ef8682613f37565b6118fc86858360006141bf565b60009150505b949350505050565b600a546001600160a01b031681565b6001546001600160a01b031681565b6119306143a9565b611981576040805162461bcd60e51b815260206004820152601960248201527f6f6e6c792061646d696e2063616e206772616e7420636f6d7000000000000000604482015290519081900360640190fd5b600061198d83836143d2565b905080156119e2576040805162461bcd60e51b815260206004820152601b60248201527f696e73756666696369656e7420636f6d7020666f72206772616e740000000000604482015290519081900360640190fd5b604080516001600160a01b03851681526020810184905281517f98b2f82a3a07f223a0be64b3d0f47711c64dccd1feafb94aa28156b38cd9695c929181900390910190a1505050565b600a546000906001600160a01b0316331480611a5157506000546001600160a01b031633145b611a8c5760405162461bcd60e51b8152600401808060200182810382526027815260200180615e946027913960400191505060405180910390fd5b6000546001600160a01b0316331480611aa757506001821515145b611af1576040805162461bcd60e51b81526020600482015260166024820152756f6e6c792061646d696e2063616e20756e706175736560501b604482015290519081900360640190fd5b600a8054831515600160b81b810260ff60b81b1990921691909117909155604080516020810192909252808252600582820152645365697a6560d81b6060830152517fef159d9a32b2472e32b098f954f3ce62d232939f1c207070b584df1814de2de09181900360800190a150805b919050565b600080546001600160a01b03163314611bc5576040805162461bcd60e51b815260206004820152601f60248201527f6f6e6c792061646d696e2063616e2073657420636c6f736520666163746f7200604482015290519081900360640190fd5b6005805490839055604080518281526020810185905281517f3b9670cf975d26958e754b57098eaa2ac914d8d2a31b83257997b9f346110fd9929181900390910190a160005b9392505050565b6000546001600160a01b03163314611c5b5760405162461bcd60e51b8152600401808060200182810382526026815260200180615ebb6026913960400191505060405180910390fd5b601580546001600160a01b038381166001600160a01b0319831681179093556040805191909216808252602082019390935281517feda98690e518e9a05f8ec6837663e188211b2da8f4906648b323f2c1d4434e29929181900390910190a15050565b6000546001600160a01b03163314611d1d576040805162461bcd60e51b815260206004820152601f60248201527f6f6e6c792061646d696e2063616e2064726f7020636f6d70206d61726b657400604482015290519081900360640190fd5b6001600160a01b0381166000908152600960205260409020600381015460ff161515600114611d93576040805162461bcd60e51b815260206004820152601b60248201527f6d61726b6574206973206e6f74206120636f6d70206d61726b65740000000000604482015290519081900360640190fd5b60038101805460ff19169055604080516001600160a01b03841681526000602082015281517f93c1f3e36ed71139f466a4ce8c9751790e2e33f5afb2df0dcfb3aeabe55d5aa2929181900390910190a1611deb6144ff565b5050565b6001600160a01b03821660009081526009602052604081205460ff16611e465760405162461bcd60e51b8152600401808060200182810382526028815260200180615e3b6028913960400191505060405180910390fd5b600a546001600160a01b0316331480611e6957506000546001600160a01b031633145b611ea45760405162461bcd60e51b8152600401808060200182810382526027815260200180615e946027913960400191505060405180910390fd5b6000546001600160a01b0316331480611ebf57506001821515145b611f09576040805162461bcd60e51b81526020600482015260166024820152756f6e6c792061646d696e2063616e20756e706175736560501b604482015290519081900360640190fd5b6001600160a01b0383166000818152600b6020908152604091829020805486151560ff199091168117909155825193845283830152606090830181905260049083015263135a5b9d60e21b6080830152517f71aec636243f9709bb0007ae15e9afb8150ab01716d75fd7573be5cc096e03b09181900360a00190a150919050565b600a54600160a01b900460ff1681565b50505050565b6019545b90565b505050505050565b60166020526000908152604090205481565b60065481565b6001600160a01b031660009081526008602052604090205490565b3332146120205760405162461bcd60e51b8152600401808060200182810382526031815260200180615e636031913960400191505060405180910390fd5b6120286144ff565b565b60008060008060008061203f8a8a8a8a6148c4565b92509250925082601181111561205157fe5b95509093509150505b9450945094915050565b6001600160a01b0383166000908152600b602052604081205460ff16156120c3576040805162461bcd60e51b815260206004820152600e60248201526d1b5a5b9d081a5cc81c185d5cd95960921b604482015290519081900360640190fd5b6001600160a01b03841660009081526009602052604090205460ff166120ed5760095b9050611c0b565b6120f684614bfc565b61210284846000614e7a565b6000949350505050565b600080546001600160a01b031633146121325761212b6001600b615072565b9050611b60565b6006805490839055604080518281526020810185905281517faeba5a6c40a8ac138134bff1aaa65debf25971188a58804bad717f82f0ec1316929181900390910190a16000611c0b565b8015801561218a5750600082115b15611f9a576040805162461bcd60e51b815260206004820152601160248201527072656465656d546f6b656e73207a65726f60781b604482015290519081900360640190fd5b600d81815481106121dd57fe5b6000918252602090912001546001600160a01b0316905081565b600080546001600160a01b031633146122165761212b60016010615072565b600480546001600160a01b038481166001600160a01b0319831681179093556040805191909216808252602082019390935281517fd52b2b9b7e9ee655fcb95d2e5b9e0c9f69e7ef2b8e9d2d0ea78402d576d22e22929181900390910190a16000611c0b565b60195481565b61228a6143a9565b6122db576040805162461bcd60e51b815260206004820152601d60248201527f6f6e6c792061646d696e2063616e2073657420636f6d70207370656564000000604482015290519081900360640190fd5b6122e4826129c1565b80612303576001600160a01b0382166000908152601860205260408120555b61230b611fa0565b6001600160a01b03831660008181526018602090815260408083209490945560178152908390208490558251848152925191927f386537fa92edc3319af95f1f904dcf1900021e4f3f4e08169a577a09076e66b3929081900390910190a25050565b6116b5565b6000806000806000806123898760008060006148c4565b92509250925082601181111561239b57fe5b97919650945092505050565b600080546001600160a01b031633146123c65761212b60016013615072565b600a80546001600160a01b038481166001600160a01b0319831617928390556040805192821680845293909116602083015280517f0613b6ee6a04f0d09f390e4d9318894b9f6ac7fd83897cd8d18896ba579c401e9281900390910190a16000611c0b565b6001600160a01b03851660009081526009602052604081205460ff16158061246c57506001600160a01b03851660009081526009602052604090205460ff16155b1561247b5760095b9050612587565b600080612487856150d8565b9193509091506000905082601181111561249d57fe5b146124b7578160118111156124ae57fe5b92505050612587565b806124c35760036124ae565b6000886001600160a01b03166395dd9193876040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561251b57600080fd5b505afa15801561252f573d6000803e3d6000fd5b505050506040513d602081101561254557600080fd5b50516040805160208101909152600554815290915060009061256790836150f8565b90508086111561257e576011945050505050612587565b60009450505050505b95945050505050565b6000546001600160a01b03163314806125b357506015546001600160a01b031633145b6125ee5760405162461bcd60e51b8152600401808060200182810382526035815260200180615ee16035913960400191505060405180910390fd5b828181158015906125fe57508082145b61263f576040805162461bcd60e51b815260206004820152600d60248201526c1a5b9d985b1a59081a5b9c1d5d609a1b604482015290519081900360640190fd5b60005b828110156127175784848281811061265657fe5b905060200201356016600089898581811061266d57fe5b905060200201356001600160a01b03166001600160a01b03166001600160a01b03168152602001908152602001600020819055508686828181106126ad57fe5b905060200201356001600160a01b03166001600160a01b03167f6f1951b2aad10f3fc81b86d91105b413a5b3f847a34bbc5ce1904201b14438f68686848181106126f357fe5b905060200201356040518082815260200191505060405180910390a2600101612642565b50505050505050565b60005b835181101561182b57600084828151811061273a57fe5b6020908102919091018101516001600160a01b0381166000908152600990925260409091205490915060ff166127af576040805162461bcd60e51b81526020600482015260156024820152741b585c9ad95d081b5d5cdd081899481b1a5cdd1959605a1b604482015290519081900360640190fd5b60018415151415612877576127c2615d7b565b6040518060200160405280836001600160a01b031663aa5af0fd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561280657600080fd5b505afa15801561281a573d6000803e3d6000fd5b505050506040513d602081101561283057600080fd5b5051905290506128408282613f37565b60005b87518110156128745761286c8389838151811061285c57fe5b60200260200101518460016141bf565b600101612843565b50505b600183151514156128c05761288b81614bfc565b60005b86518110156128be576128b6828883815181106128a757fe5b60200260200101516001614e7a565b60010161288e565b505b50600101612723565b6128d16143a9565b612922576040805162461bcd60e51b815260206004820152601f60248201527f6f6e6c792061646d696e2063616e206368616e676520636f6d70207261746500604482015290519081900360640190fd5b600e805490829055604080518281526020810184905281517fc227c9272633c3a307d9845bf2bc2509cefb20d655b5f3c1002d8e1e3f22c8b0929181900390910190a1611deb6144ff565b6010602052600090815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b600c6020526000908152604090205460ff1681565b600b6020526000908152604090205460ff1681565b6001600160a01b038116600090815260176020526040812054906129e3611fa0565b6001600160a01b03841660009081526018602052604081205491925090612a0b908390615117565b9050600081118015612a1d5750600083115b15611f9a576000612a2e8285615151565b6001600160a01b03861660009081526014602052604081205491925090612a559083615193565b6001600160a01b0387166000908152601460209081526040808320939093556018905220849055505050505050565b66038d7ea4c6800081565b601a546001600160a01b031681565b6004546001600160a01b031681565b601a80546001600160a01b0319166001600160a01b0392909216919091179055565b600a54600160b01b900460ff1681565b6011602052600090815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b60096020526000908152604090208054600182015460039092015460ff91821692911683565b600a546000906001600160a01b0316331480612b5557506000546001600160a01b031633145b612b905760405162461bcd60e51b8152600401808060200182810382526027815260200180615e946027913960400191505060405180910390fd5b6000546001600160a01b0316331480612bab57506001821515145b612bf5576040805162461bcd60e51b81526020600482015260166024820152756f6e6c792061646d696e2063616e20756e706175736560501b604482015290519081900360640190fd5b600a8054831515600160b01b810260ff60b01b1990921691909117909155604080516020810192909252808252600882820152672a3930b739b332b960c11b6060830152517fef159d9a32b2472e32b098f954f3ce62d232939f1c207070b584df1814de2de09181900360800190a15090565b6001600160a01b038082166000908152600960209081526040808320938616835260029093019052205460ff1692915050565b60075481565b60176020526000908152604090205481565b601a546001600160a01b031690565b600080546001600160a01b03163314612ce15761212b60016012615072565b6001600160a01b03821660009081526009602052604090205460ff1615612d0e5761212b600a6011615072565b816001600160a01b031663fe9c44ae6040518163ffffffff1660e01b815260040160206040518083038186803b158015612d4757600080fd5b505afa158015612d5b573d6000803e3d6000fd5b505050506040513d6020811015612d7157600080fd5b5050604080516060810182526001808252600060208381018281528486018381526001600160a01b03891684526009909252949091209251835490151560ff19918216178455935191830191909155516003909101805491151591909216179055612ddb826151c9565b604080516001600160a01b038416815290517fcf583bb0c569eb967f806b11601c4cb93c10310485c67add5f8362c2f212321f9181900360200190a1600092915050565b6ec097ce7bc90715b34b9f100000000081565b601955565b600e5481565b60608060086000846001600160a01b03166001600160a01b03168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015612eb957602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612e9b575b5093979650505050505050565b600a54600160b81b900460ff1681565b6060600d805480602002602001604051908101604052809291908181526020018280548015612f2e57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612f10575b5050505050905090565b601260209081526000928352604080842090915290825290205481565b6002546001600160a01b031681565b600a54600090600160b01b900460ff1615612fbb576040805162461bcd60e51b81526020600482015260126024820152711d1c985b9cd9995c881a5cc81c185d5cd95960721b604482015290519081900360640190fd5b6000612fc88686856152a7565b90508015612fd7579050611902565b612fe086614bfc565b612fec86866000614e7a565b6118fc86856000614e7a565b6001600160a01b03166000908152600960205260409020805460ff19169055565b60186020526000908152604090205481565b606060008251905060608160405190808252806020026020018201604052801561305f578160200160208202803883390190505b50905060005b828110156130ba57600085828151811061307b57fe5b6020026020010151905061308f8133615353565b601181111561309a57fe5b8383815181106130a657fe5b602090810291909101015250600101613065565b509392505050565b600480546040805163fc57d4df60e01b81526001600160a01b038781169482019490945290516000938493849391169163fc57d4df91602480820192602092909190829003018186803b15801561311857600080fd5b505afa15801561312c573d6000803e3d6000fd5b505050506040513d602081101561314257600080fd5b5051600480546040805163fc57d4df60e01b81526001600160a01b038a8116948201949094529051939450600093929091169163fc57d4df91602480820192602092909190829003018186803b15801561319b57600080fd5b505afa1580156131af573d6000803e3d6000fd5b505050506040513d60208110156131c557600080fd5b505190508115806131d4575080155b156131e957600d9350600092506132e2915050565b6000866001600160a01b031663182df0f56040518163ffffffff1660e01b815260040160206040518083038186803b15801561322457600080fd5b505afa158015613238573d6000803e3d6000fd5b505050506040513d602081101561324e57600080fd5b50519050600061325c615d7b565b613264615d7b565b61326c615d7b565b613294604051806020016040528060065481525060405180602001604052808a815250615449565b92506132bc604051806020016040528088815250604051806020016040528088815250615449565b91506132c88383615488565b90506132d4818b6150f8565b600099509750505050505050505b935093915050565b601360209081526000928352604080842090915290825290205481565b60146020526000908152604090205481565b6133216143a9565b613372576040805162461bcd60e51b815260206004820152601e60248201527f6f6e6c792061646d696e2063616e2061646420636f6d70206d61726b65740000604482015290519081900360640190fd5b60005b81518110156133a25761339a82828151811061338d57fe5b60200260200101516154c4565b600101613375565b506118166144ff565b600a54600090600160b81b900460ff16156133ff576040805162461bcd60e51b815260206004820152600f60248201526e1cd95a5e99481a5cc81c185d5cd959608a1b604482015290519081900360640190fd5b6001600160a01b03861660009081526009602052604090205460ff16158061344057506001600160a01b03851660009081526009602052604090205460ff16155b1561344c576009612474565b846001600160a01b0316635fe3b5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561348557600080fd5b505afa158015613499573d6000803e3d6000fd5b505050506040513d60208110156134af57600080fd5b505160408051635fe3b56760e01b815290516001600160a01b0392831692891691635fe3b567916004808301926020929190829003018186803b1580156134f557600080fd5b505afa158015613509573d6000803e3d6000fd5b505050506040513d602081101561351f57600080fd5b50516001600160a01b031614613536576002612474565b61353f86614bfc565b61354b86846000614e7a565b61355786856000614e7a565b60009695505050505050565b6001600160a01b0383166000908152600c602052604081205460ff16156135c4576040805162461bcd60e51b815260206004820152601060248201526f189bdc9c9bddc81a5cc81c185d5cd95960821b604482015290519081900360640190fd5b6001600160a01b03841660009081526009602052604090205460ff166135eb5760096120e6565b6001600160a01b038085166000908152600960209081526040808320938716835260029093019052205460ff166136db57336001600160a01b03851614613671576040805162461bcd60e51b815260206004820152601560248201527439b2b73232b91036bab9ba1031329031aa37b5b2b760591b604482015290519081900360640190fd5b600061367d3385615353565b9050600081601181111561368d57fe5b146136a65780601181111561369e57fe5b915050611c0b565b6001600160a01b038086166000908152600960209081526040808320938816835260029093019052205460ff166136d957fe5b505b600480546040805163fc57d4df60e01b81526001600160a01b03888116948201949094529051929091169163fc57d4df91602480820192602092909190829003018186803b15801561372c57600080fd5b505afa158015613740573d6000803e3d6000fd5b505050506040513d602081101561375657600080fd5b505161376357600d6120e6565b6001600160a01b0384166000908152601660205260409020548015613850576000856001600160a01b03166347bd37186040518163ffffffff1660e01b815260040160206040518083038186803b1580156137bd57600080fd5b505afa1580156137d1573d6000803e3d6000fd5b505050506040513d60208110156137e757600080fd5b5051905060006137f78286615193565b905082811061384d576040805162461bcd60e51b815260206004820152601960248201527f6d61726b657420626f72726f7720636170207265616368656400000000000000604482015290519081900360640190fd5b50505b60008061386086886000886148c4565b9193509091506000905082601181111561387657fe5b146138915781601181111561388757fe5b9350505050611c0b565b801561389e576004613887565b6138a6615d7b565b6040518060200160405280896001600160a01b031663aa5af0fd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156138ea57600080fd5b505afa1580156138fe573d6000803e3d6000fd5b505050506040513d602081101561391457600080fd5b5051905290506139248882613f37565b61393188888360006141bf565b600098975050505050505050565b6008602052816000526040600020818154811061395857fe5b6000918252602090912001546001600160a01b03169150829050565b6003546001600160a01b031681565b600080546001600160a01b031633146139a9576139a260016006615072565b9050611652565b6001600160a01b0383166000908152600960205260409020805460ff166139de576139d660096007615072565b915050611652565b6139e6615d7b565b5060408051602081019091528381526139fd615d7b565b506040805160208101909152670c7d713b49da00008152613a1e81836157df565b15613a3957613a2f60066008615072565b9350505050611652565b8415801590613ac25750600480546040805163fc57d4df60e01b81526001600160a01b038a8116948201949094529051929091169163fc57d4df91602480820192602092909190829003018186803b158015613a9457600080fd5b505afa158015613aa8573d6000803e3d6000fd5b505050506040513d6020811015613abe57600080fd5b5051155b15613ad357613a2f600d6009615072565b60018301805490869055604080516001600160a01b03891681526020810183905280820188905290517f70483e6592cd5182d45ac970e05bc62cdcc90e9d8ef2c2dbe686cf383bcd7fc59181900360600190a16000979650505050505050565b600a54600160a81b900460ff1681565b6001600160a01b039091166000908152600f6020526040902055565b60055481565b61181681600d805480602002602001604051908101604052809291908181526020018280548015613bbf57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311613ba1575b5050505050611658565b600080613bd78585856152a7565b90508015613be6579050611c0b565b613bef85614bfc565b613bfb85856000614e7a565b600095945050505050565b6000808290506000806000836001600160a01b031663c37f68e2336040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060806040518083038186803b158015613c6757600080fd5b505afa158015613c7b573d6000803e3d6000fd5b505050506040513d6080811015613c9157600080fd5b508051602082015160409092015190945090925090508215613ce45760405162461bcd60e51b8152600401808060200182810382526025815260200180615f166025913960400191505060405180910390fd5b8015613d0157613cf6600c6002615072565b945050505050611b60565b6000613d0e8733856152a7565b90508015613d2f57613d23600e6003836157e6565b95505050505050611b60565b6001600160a01b0385166000908152600960209081526040808320338452600281019092529091205460ff16613d6e5760009650505050505050611b60565b3360009081526002820160209081526040808320805460ff191690556008825291829020805483518184028101840190945280845260609392830182828015613de057602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311613dc2575b5050835193945083925060009150505b82811015613e3557896001600160a01b0316848281518110613e0e57fe5b60200260200101516001600160a01b03161415613e2d57809150613e35565b600101613df0565b50818110613e3f57fe5b336000908152600860205260409020805481906000198101908110613e6057fe5b9060005260206000200160009054906101000a90046001600160a01b0316818381548110613e8a57fe5b600091825260209091200180546001600160a01b0319166001600160a01b03929092169190911790558054613ec3826000198301615d8e565b50604080516001600160a01b038c16815233602082015281517fe699a64c18b07ac5b7301aa273f36a2287239eb9501d81950672794afba29a0d929181900390910190a160009c9b505050505050505050505050565b6000546001600160a01b031681565b60198054820190819055919050565b6001600160a01b0382166000908152601160209081526040808320600f9092528220549091613f64611fa0565b8354909150600090613f84908390600160e01b900463ffffffff16615117565b9050600081118015613f965750600083115b1561416557600061400b876001600160a01b03166347bd37186040518163ffffffff1660e01b815260040160206040518083038186803b158015613fd957600080fd5b505afa158015613fed573d6000803e3d6000fd5b505050506040513d602081101561400357600080fd5b50518761584c565b905060006140198386615151565b9050614023615d7b565b60008311614040576040518060200160405280600081525061404a565b61404a828461586a565b9050614054615d7b565b604080516020810190915288546001600160e01b03168152614076908361589f565b905060405180604001604052806140c683600001516040518060400160405280601a81526020017f6e657720696e64657820657863656564732032323420626974730000000000008152506158c4565b6001600160e01b03168152602001614101886040518060400160405280601c8152602001600080516020615f3b83398151915281525061595e565b63ffffffff9081169091526001600160a01b038c166000908152601160209081526040909120835181549490920151909216600160e01b026001600160e01b039182166001600160e01b0319909416939093171691909117905550611fa792505050565b8015611fa757614198826040518060400160405280601c8152602001600080516020615f3b83398151915281525061595e565b845463ffffffff91909116600160e01b026001600160e01b03909116178455505050505050565b6001600160a01b03841660009081526011602052604090206141df615d7b565b50604080516020810190915281546001600160e01b03168152614200615d7b565b5060408051602080820183526001600160a01b03808a16600090815260138352848120918a16808252828452948120805485528651959091529152919091558051156127175761424e615d7b565b61425883836159b3565b905060006142e7896001600160a01b03166395dd91938a6040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b1580156142b557600080fd5b505afa1580156142c9573d6000803e3d6000fd5b505050506040513d60208110156142df57600080fd5b50518861584c565b905060006142f582846159d8565b6001600160a01b038a166000908152601460205260408120549192509061431c9083615193565b905061433d8a828a6143355766038d7ea4c68000614338565b60005b615a07565b6001600160a01b03808c1660008181526014602090815260409182902094909455895181518781529485015280519193928f16927f1fc3ecc087d8d2d15e23d0032af5a47059c3892d003d8e139fdcb6bb327c99a6929081900390910190a35050505050505050505050565b600080546001600160a01b03163314806143cd57506002546001600160a01b031633145b905090565b6000806143dd612cb3565b604080516370a0823160e01b815230600482015290519192506000916001600160a01b038416916370a08231916024808301926020929190829003018186803b15801561442957600080fd5b505afa15801561443d573d6000803e3d6000fd5b505050506040513d602081101561445357600080fd5b505190508084116144f657816001600160a01b031663a9059cbb86866040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b1580156144be57600080fd5b505af11580156144d2573d6000803e3d6000fd5b505050506040513d60208110156144e857600080fd5b506000935061165292505050565b50919392505050565b6060600d80548060200260200160405190810160405280929190818152602001828054801561455757602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311614539575b50939450600093505050505b815181101561461d57600082828151811061457a57fe5b6020026020010151905061458c615d7b565b6040518060200160405280836001600160a01b031663aa5af0fd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156145d057600080fd5b505afa1580156145e4573d6000803e3d6000fd5b505050506040513d60208110156145fa57600080fd5b50519052905061460982614bfc565b6146138282613f37565b5050600101614563565b50614626615d7b565b6040518060200160405280600081525090506060825160405190808252806020026020018201604052801561467557816020015b614662615d7b565b81526020019060019003908161465a5790505b50905060005b83518110156147fb57600084828151811061469257fe5b6020908102919091018101516001600160a01b0381166000908152600990925260409091206003015490915060ff16156147f2576146ce615d7b565b60408051602080820180845260045463fc57d4df60e01b9091526001600160a01b03868116602485015293519293849391169163fc57d4df916044808601929190818703018186803b15801561472357600080fd5b505afa158015614737573d6000803e3d6000fd5b505050506040513d602081101561474d57600080fd5b50519052905061475b615d7b565b6147c982846001600160a01b03166347bd37186040518163ffffffff1660e01b815260040160206040518083038186803b15801561479857600080fd5b505afa1580156147ac573d6000803e3d6000fd5b505050506040513d60208110156147c257600080fd5b5051615b4c565b9050808585815181106147d857fe5b60200260200101819052506147ed868261589f565b955050505b5060010161467b565b5060005b8351811015611f9a576000600d828154811061481757fe5b600091825260208220015485516001600160a01b03909116925061483c576000614864565b614864600e5461485f86868151811061485157fe5b602002602001015188615488565b615b6d565b6001600160a01b0383166000818152600f60209081526040918290208490558151848152915193945091927f2ab93f65628379309f36cb125e90d7c902454a545c4f8b8cb0794af75c24b807929181900390910190a250506001016147ff565b60008060006148d1615db2565b6001600160a01b0388166000908152600860209081526040808320805482518185028101850190935280835260609383018282801561493957602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161491b575b50939450600093505050505b8151811015614bbd57600082828151811061495c57fe5b60200260200101519050806001600160a01b031663c37f68e28d6040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060806040518083038186803b1580156149bc57600080fd5b505afa1580156149d0573d6000803e3d6000fd5b505050506040513d60808110156149e657600080fd5b508051602082015160408084015160609485015160808b0152938901939093529187019190915293508315614a2b5750600f96506000955085945061205a9350505050565b60408051602080820183526001600160a01b0380851660008181526009845285902060010154845260c08a01939093528351808301855260808a0151815260e08a015260048054855163fc57d4df60e01b815291820194909452935192169263fc57d4df9260248083019392829003018186803b158015614aab57600080fd5b505afa158015614abf573d6000803e3d6000fd5b505050506040513d6020811015614ad557600080fd5b505160a08601819052614af85750600d96506000955085945061205a9350505050565b604080516020810190915260a0860151815261010086015260c085015160e0860151614b3291614b2791615449565b866101000151615449565b610120860181905260408601518651614b4c929190615b86565b855261010085015160608601516020870151614b69929190615b86565b60208601526001600160a01b03818116908c161415614bb457614b968561012001518b8760200151615b86565b60208601819052610100860151614bae918b90615b86565b60208601525b50600101614945565b50602083015183511115614be3575050602081015190516000945003915082905061205a565b505080516020909101516000945084935003905061205a565b6001600160a01b0381166000908152601060209081526040808320600f9092528220549091614c29611fa0565b8354909150600090614c49908390600160e01b900463ffffffff16615117565b9050600081118015614c5b5750600083115b15614e21576000856001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015614c9b57600080fd5b505afa158015614caf573d6000803e3d6000fd5b505050506040513d6020811015614cc557600080fd5b505190506000614cd58386615151565b9050614cdf615d7b565b60008311614cfc5760405180602001604052806000815250614d06565b614d06828461586a565b9050614d10615d7b565b604080516020810190915288546001600160e01b03168152614d32908361589f565b90506040518060400160405280614d8283600001516040518060400160405280601a81526020017f6e657720696e64657820657863656564732032323420626974730000000000008152506158c4565b6001600160e01b03168152602001614dbd886040518060400160405280601c8152602001600080516020615f3b83398151915281525061595e565b63ffffffff9081169091526001600160a01b038b166000908152601060209081526040909120835181549490920151909216600160e01b026001600160e01b039182166001600160e01b031990941693909317169190911790555061182b92505050565b801561182b57614e54826040518060400160405280601c8152602001600080516020615f3b83398151915281525061595e565b845463ffffffff91909116600160e01b026001600160e01b039091161784555050505050565b6001600160a01b0383166000908152601060205260409020614e9a615d7b565b50604080516020810190915281546001600160e01b03168152614ebb615d7b565b5060408051602080820183526001600160a01b03808916600090815260128352848120918916808252828452948120805485528651959091529152919091558051158015614f095750815115155b15614f21576ec097ce7bc90715b34b9f100000000081525b614f29615d7b565b614f3383836159b3565b90506000876001600160a01b03166370a08231886040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015614f8d57600080fd5b505afa158015614fa1573d6000803e3d6000fd5b505050506040513d6020811015614fb757600080fd5b505190506000614fc782846159d8565b6001600160a01b03891660009081526014602052604081205491925090614fee9083615193565b905061500789828a6143355766038d7ea4c68000614338565b6001600160a01b03808b1660008181526014602090815260409182902094909455895181518781529485015280519193928e16927f2caecd17d02f56fa897705dcc740da2d237c373f70686f4e0d9bd3bf0400ea7a929081900390910190a350505050505050505050565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa08360118111156150a157fe5b8360138111156150ad57fe5b604080519283526020830191909152600082820152519081900360600190a1826011811115611c0b57fe5b60008060006150eb8460008060006148c4565b9250925092509193909250565b6000615102615d7b565b61510c8484615b4c565b905061190281615bae565b6000611c0b8383604051806040016040528060158152602001747375627472616374696f6e20756e646572666c6f7760581b815250615bbd565b6000611c0b83836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f77000000000000000000815250615c17565b6000611c0b8383604051806040016040528060118152602001706164646974696f6e206f766572666c6f7760781b815250615c96565b60005b600d5481101561525457816001600160a01b0316600d82815481106151ed57fe5b6000918252602090912001546001600160a01b0316141561524c576040805162461bcd60e51b81526020600482015260146024820152731b585c9ad95d08185b1c9958591e48185919195960621b604482015290519081900360640190fd5b6001016151cc565b50600d80546001810182556000919091527fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb50180546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b03831660009081526009602052604081205460ff166152ce5760096120e6565b6001600160a01b038085166000908152600960209081526040808320938716835260029093019052205460ff166153065760006120e6565b60008061531685878660006148c4565b9193509091506000905082601181111561532c57fe5b146153465781601181111561533d57fe5b92505050611c0b565b801561355757600461533d565b6001600160a01b0382166000908152600960205260408120805460ff1661537e576009915050611652565b6001600160a01b038316600090815260028201602052604090205460ff161515600114156153b0576000915050611652565b6001600160a01b0380841660008181526002840160209081526040808320805460ff19166001908117909155600883528184208054918201815584529282902090920180549489166001600160a01b031990951685179055815193845283019190915280517f3ab23ab0d51cccc0c3085aec51f99228625aa1a922b3a8ca89a26b0f2027a1a59281900390910190a15060009392505050565b615451615d7b565b6040518060200160405280670de0b6b3a764000061547786600001518660000151615151565b8161547e57fe5b0490529392505050565b615490615d7b565b60405180602001604052806154bb6154b48660000151670de0b6b3a7640000615151565b8551615ceb565b90529392505050565b6001600160a01b0381166000908152600960205260409020805460ff161515600114615537576040805162461bcd60e51b815260206004820152601960248201527f636f6d70206d61726b6574206973206e6f74206c697374656400000000000000604482015290519081900360640190fd5b600381015460ff1615615591576040805162461bcd60e51b815260206004820152601960248201527f636f6d70206d61726b657420616c726561647920616464656400000000000000604482015290519081900360640190fd5b60038101805460ff19166001908117909155604080516001600160a01b0385168152602081019290925280517f93c1f3e36ed71139f466a4ce8c9751790e2e33f5afb2df0dcfb3aeabe55d5aa29281900390910190a16001600160a01b0382166000908152601060205260409020546001600160e01b031615801561563957506001600160a01b038216600090815260106020526040902054600160e01b900463ffffffff16155b156156f65760405180604001604052806ec097ce7bc90715b34b9f10000000006001600160e01b0316815260200161569b615672611fa0565b6040518060400160405280601c8152602001600080516020615f3b83398151915281525061595e565b63ffffffff9081169091526001600160a01b0384166000908152601060209081526040909120835181549490920151909216600160e01b026001600160e01b039182166001600160e01b031990941693909317169190911790555b6001600160a01b0382166000908152601160205260409020546001600160e01b031615801561574857506001600160a01b038216600090815260116020526040902054600160e01b900463ffffffff16155b15611deb5760405180604001604052806ec097ce7bc90715b34b9f10000000006001600160e01b03168152602001615781615672611fa0565b63ffffffff9081169091526001600160a01b0384166000908152601160209081526040909120835181549490920151909216600160e01b026001600160e01b039182166001600160e01b031990941693909317169190911790555050565b5190511090565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa084601181111561581557fe5b84601381111561582157fe5b604080519283526020830191909152818101859052519081900360600190a183601181111561190257fe5b6000611c0b61586384670de0b6b3a7640000615151565b8351615ceb565b615872615d7b565b60405180602001604052806154bb615899866ec097ce7bc90715b34b9f1000000000615151565b85615ceb565b6158a7615d7b565b60405180602001604052806154bb85600001518560000151615193565b600081600160e01b84106159565760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561591b578181015183820152602001615903565b50505050905090810190601f1680156159485780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b509192915050565b600081600160201b84106159565760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561591b578181015183820152602001615903565b6159bb615d7b565b60405180602001604052806154bb85600001518560000151615117565b60006ec097ce7bc90715b34b9f10000000006159f8848460000151615151565b816159ff57fe5b049392505050565b6000818310158015615a195750600083115b15615b44576000615a28612cb3565b604080516370a0823160e01b815230600482015290519192506000916001600160a01b038416916370a08231916024808301926020929190829003018186803b158015615a7457600080fd5b505afa158015615a88573d6000803e3d6000fd5b505050506040513d6020811015615a9e57600080fd5b50519050808511615b4157816001600160a01b031663a9059cbb87876040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b158015615b0957600080fd5b505af1158015615b1d573d6000803e3d6000fd5b505050506040513d6020811015615b3357600080fd5b5060009350611c0b92505050565b50505b509092915050565b615b54615d7b565b60405180602001604052806154bb856000015185615151565b6000670de0b6b3a76400006159f8848460000151615151565b6000615b90615d7b565b615b9a8585615b4c565b9050612587615ba882615bae565b84615193565b51670de0b6b3a7640000900490565b60008184841115615c0f5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561591b578181015183820152602001615903565b505050900390565b6000831580615c24575082155b15615c3157506000611c0b565b83830283858281615c3e57fe5b04148390615c8d5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561591b578181015183820152602001615903565b50949350505050565b60008383018285821015615c8d5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561591b578181015183820152602001615903565b6000611c0b83836040518060400160405280600e81526020016d646976696465206279207a65726f60901b81525060008183615d685760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561591b578181015183820152602001615903565b50828481615d7257fe5b04949350505050565b6040518060200160405280600081525090565b8154818355818111156116b5576000838152602090206116b5918101908301615e1c565b604051806101400160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001615df0615d7b565b8152602001615dfd615d7b565b8152602001615e0a615d7b565b8152602001615e17615d7b565b905290565b611fa491905b80821115615e365760008155600101615e22565b509056fe63616e6e6f742070617573652061206d61726b65742074686174206973206e6f74206c69737465646f6e6c792065787465726e616c6c79206f776e6564206163636f756e7473206d61792072656672657368207370656564736f6e6c7920706175736520677561726469616e20616e642061646d696e2063616e2070617573656f6e6c792061646d696e2063616e2073657420626f72726f772063617020677561726469616e6f6e6c792061646d696e206f7220626f72726f772063617020677561726469616e2063616e2073657420626f72726f772063617073657869744d61726b65743a206765744163636f756e74536e617073686f74206661696c6564626c6f636b206e756d62657220657863656564732033322062697473000000006f6e6c7920756e6974726f6c6c65722061646d696e2063616e206368616e676520627261696e73a265627a7a72315820f275080c724e84a60002ce3e46035348be403fb87cd8b6f1e092550849fdc26f64736f6c63430005100032", + "metadata": "{\"compiler\":{\"version\":\"0.5.16+commit.9c3226ce\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"action\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"pauseState\",\"type\":\"bool\"}],\"name\":\"ActionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"action\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"pauseState\",\"type\":\"bool\"}],\"name\":\"ActionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"CompGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSpeed\",\"type\":\"uint256\"}],\"name\":\"CompSpeedUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"contributor\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSpeed\",\"type\":\"uint256\"}],\"name\":\"ContributorCompSpeedUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compBorrowIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedBorrowerComp\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"supplier\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"compSupplyIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedSupplierComp\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isComped\",\"type\":\"bool\"}],\"name\":\"MarketComped\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketEntered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketExited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"MarketListed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newBorrowCap\",\"type\":\"uint256\"}],\"name\":\"NewBorrowCap\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldBorrowCapGuardian\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newBorrowCapGuardian\",\"type\":\"address\"}],\"name\":\"NewBorrowCapGuardian\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCloseFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCloseFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCollateralFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCollateralFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCompRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCompRate\",\"type\":\"uint256\"}],\"name\":\"NewCompRate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldLiquidationIncentiveMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"NewLiquidationIncentive\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldPauseGuardian\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"NewPauseGuardian\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"oldPriceOracle\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract PriceOracle\",\"name\":\"newPriceOracle\",\"type\":\"address\"}],\"name\":\"NewPriceOracle\",\"type\":\"event\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"_addCompMarkets\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract Unitroller\",\"name\":\"unitroller\",\"type\":\"address\"}],\"name\":\"_become\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"_dropCompMarket\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"_grantComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"newBorrowCapGuardian\",\"type\":\"address\"}],\"name\":\"_setBorrowCapGuardian\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setBorrowPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCloseFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCollateralFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"compRate_\",\"type\":\"uint256\"}],\"name\":\"_setCompRate\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"contributor\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"compSpeed\",\"type\":\"uint256\"}],\"name\":\"_setContributorCompSpeed\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"_setLiquidationIncentive\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"cTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"newBorrowCaps\",\"type\":\"uint256[]\"}],\"name\":\"_setMarketBorrowCaps\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setMintPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"_setPauseGuardian\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"newOracle\",\"type\":\"address\"}],\"name\":\"_setPriceOracle\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setSeizePaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setTransferPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"_supportMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allMarkets\",\"outputs\":[{\"internalType\":\"contract CToken\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"blockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"borrowCapGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"checkMembership\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"},{\"internalType\":\"contract CToken[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"holders\",\"type\":\"address[]\"},{\"internalType\":\"contract CToken[]\",\"name\":\"cTokens\",\"type\":\"address[]\"},{\"internalType\":\"bool\",\"name\":\"borrowers\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"suppliers\",\"type\":\"bool\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"}],\"name\":\"claimComp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compAccrued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compBorrowState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compBorrowerIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compClaimThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compContributorSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compInitialIndex\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"compRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSupplierIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"compSupplyState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"cTokens\",\"type\":\"address[]\"}],\"name\":\"enterMarkets\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenAddress\",\"type\":\"address\"}],\"name\":\"exitMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blocks\",\"type\":\"uint256\"}],\"name\":\"fastForward\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getAllMarkets\",\"outputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAssetsIn\",\"outputs\":[{\"internalType\":\"contract CToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getCompAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenModify\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"getHypotheticalAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"isComptroller\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"lastContributorBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateCalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"liquidationIncentiveMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"markets\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isComped\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"membershipLength\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"mintAmount\",\"type\":\"uint256\"}],\"name\":\"mintAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualMintAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"mintTokens\",\"type\":\"uint256\"}],\"name\":\"mintVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract PriceOracle\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"refreshCompSpeeds\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"repayBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowerIndex\",\"type\":\"uint256\"}],\"name\":\"repayBorrowVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"seizeGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"}],\"name\":\"setBlockNumber\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"compAddress_\",\"type\":\"address\"}],\"name\":\"setCompAddress\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"compSpeed\",\"type\":\"uint256\"}],\"name\":\"setCompSpeed\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"transferGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"cToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferVerify\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract CToken\",\"name\":\"cToken\",\"type\":\"address\"}],\"name\":\"unlist\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"contributor\",\"type\":\"address\"}],\"name\":\"updateContributorRewards\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"methods\":{\"_addCompMarkets(address[])\":{\"params\":{\"cTokens\":\"The addresses of the markets to add\"}},\"_dropCompMarket(address)\":{\"params\":{\"cToken\":\"The address of the market to drop\"}},\"_grantComp(address,uint256)\":{\"details\":\"Note: If there is not enough COMP, we do not perform the transfer all.\",\"params\":{\"amount\":\"The amount of COMP to (possibly) transfer\",\"recipient\":\"The address of the recipient to transfer COMP to\"}},\"_setBorrowCapGuardian(address)\":{\"params\":{\"newBorrowCapGuardian\":\"The address of the new Borrow Cap Guardian\"}},\"_setCloseFactor(uint256)\":{\"details\":\"Admin function to set closeFactor\",\"params\":{\"newCloseFactorMantissa\":\"New close factor, scaled by 1e18\"},\"return\":\"uint 0=success, otherwise a failure\"},\"_setCollateralFactor(address,uint256)\":{\"details\":\"Admin function to set per-market collateralFactor\",\"params\":{\"cToken\":\"The market to set the factor on\",\"newCollateralFactorMantissa\":\"The new collateral factor, scaled by 1e18\"},\"return\":\"uint 0=success, otherwise a failure. (See ErrorReporter for details)\"},\"_setCompRate(uint256)\":{\"params\":{\"compRate_\":\"The amount of COMP wei per block to distribute\"}},\"_setContributorCompSpeed(address,uint256)\":{\"params\":{\"compSpeed\":\"New COMP speed for contributor\",\"contributor\":\"The contributor whose COMP speed to update\"}},\"_setLiquidationIncentive(uint256)\":{\"details\":\"Admin function to set liquidationIncentive\",\"params\":{\"newLiquidationIncentiveMantissa\":\"New liquidationIncentive scaled by 1e18\"},\"return\":\"uint 0=success, otherwise a failure. (See ErrorReporter for details)\"},\"_setMarketBorrowCaps(address[],uint256[])\":{\"details\":\"Admin or borrowCapGuardian function to set the borrow caps. A borrow cap of 0 corresponds to unlimited borrowing.\",\"params\":{\"cTokens\":\"The addresses of the markets (tokens) to change the borrow caps for\",\"newBorrowCaps\":\"The new borrow cap values in underlying to be set. A value of 0 corresponds to unlimited borrowing.\"}},\"_setPauseGuardian(address)\":{\"params\":{\"newPauseGuardian\":\"The address of the new Pause Guardian\"},\"return\":\"uint 0=success, otherwise a failure. (See enum Error for details)\"},\"_setPriceOracle(address)\":{\"details\":\"Admin function to set a new price oracle\",\"return\":\"uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\"},\"_supportMarket(address)\":{\"details\":\"Admin function to set isListed and add support for the market\",\"params\":{\"cToken\":\"The address of the market (token) to list\"},\"return\":\"uint 0=success, otherwise a failure. (See enum Error for details)\"},\"borrowAllowed(address,address,uint256)\":{\"params\":{\"borrowAmount\":\"The amount of underlying the account would borrow\",\"borrower\":\"The account which would borrow the asset\",\"cToken\":\"The market to verify the borrow against\"},\"return\":\"0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"borrowVerify(address,address,uint256)\":{\"params\":{\"borrowAmount\":\"The amount of the underlying asset requested to borrow\",\"borrower\":\"The address borrowing the underlying\",\"cToken\":\"Asset whose underlying is being borrowed\"}},\"checkMembership(address,address)\":{\"params\":{\"account\":\"The address of the account to check\",\"cToken\":\"The cToken to check\"},\"return\":\"True if the account is in the asset, otherwise false.\"},\"claimComp(address)\":{\"params\":{\"holder\":\"The address to claim COMP for\"}},\"claimComp(address,address[])\":{\"params\":{\"cTokens\":\"The list of markets to claim COMP in\",\"holder\":\"The address to claim COMP for\"}},\"claimComp(address[],address[],bool,bool)\":{\"params\":{\"borrowers\":\"Whether or not to claim COMP earned by borrowing\",\"cTokens\":\"The list of markets to claim COMP in\",\"holders\":\"The addresses to claim COMP for\",\"suppliers\":\"Whether or not to claim COMP earned by supplying\"}},\"enterMarkets(address[])\":{\"params\":{\"cTokens\":\"The list of addresses of the cToken markets to be enabled\"},\"return\":\"Success indicator for whether each corresponding market was entered\"},\"exitMarket(address)\":{\"details\":\"Sender must not have an outstanding borrow balance in the asset, or be providing necessary collateral for an outstanding borrow.\",\"params\":{\"cTokenAddress\":\"The address of the asset to be removed\"},\"return\":\"Whether or not the account successfully exited the market\"},\"getAccountLiquidity(address)\":{\"return\":\"(possible error code (semi-opaque), account liquidity in excess of collateral requirements, account shortfall below collateral requirements)\"},\"getAllMarkets()\":{\"details\":\"The automatic getter may be used to access an individual market.\",\"return\":\"The list of market addresses\"},\"getAssetsIn(address)\":{\"params\":{\"account\":\"The address of the account to pull assets for\"},\"return\":\"A dynamic list with the assets the account has entered\"},\"getHypotheticalAccountLiquidity(address,address,uint256,uint256)\":{\"params\":{\"account\":\"The account to determine liquidity for\",\"borrowAmount\":\"The amount of underlying to hypothetically borrow\",\"cTokenModify\":\"The market to hypothetically redeem/borrow in\",\"redeemTokens\":\"The number of tokens to hypothetically redeem\"},\"return\":\"(possible error code (semi-opaque), hypothetical account liquidity in excess of collateral requirements, hypothetical account shortfall below collateral requirements)\"},\"liquidateBorrowAllowed(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"repayAmount\":\"The amount of underlying being repaid\"}},\"liquidateBorrowVerify(address,address,address,address,uint256,uint256)\":{\"params\":{\"actualRepayAmount\":\"The amount of underlying being repaid\",\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\"}},\"liquidateCalculateSeizeTokens(address,address,uint256)\":{\"details\":\"Used in liquidation (called in cToken.liquidateBorrowFresh)\",\"params\":{\"actualRepayAmount\":\"The amount of cTokenBorrowed underlying to convert into cTokenCollateral tokens\",\"cTokenBorrowed\":\"The address of the borrowed cToken\",\"cTokenCollateral\":\"The address of the collateral cToken\"},\"return\":\"(errorCode, number of cTokenCollateral tokens to be seized in a liquidation)\"},\"mintAllowed(address,address,uint256)\":{\"params\":{\"cToken\":\"The market to verify the mint against\",\"mintAmount\":\"The amount of underlying being supplied to the market in exchange for tokens\",\"minter\":\"The account which would get the minted tokens\"},\"return\":\"0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"mintVerify(address,address,uint256,uint256)\":{\"params\":{\"actualMintAmount\":\"The amount of the underlying asset being minted\",\"cToken\":\"Asset being minted\",\"mintTokens\":\"The number of tokens being minted\",\"minter\":\"The address minting the tokens\"}},\"redeemAllowed(address,address,uint256)\":{\"params\":{\"cToken\":\"The market to verify the redeem against\",\"redeemTokens\":\"The number of cTokens to exchange for the underlying asset in the market\",\"redeemer\":\"The account which would redeem the tokens\"},\"return\":\"0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"redeemVerify(address,address,uint256,uint256)\":{\"params\":{\"cToken\":\"Asset being redeemed\",\"redeemAmount\":\"The amount of the underlying asset being redeemed\",\"redeemTokens\":\"The number of tokens being redeemed\",\"redeemer\":\"The address redeeming the tokens\"}},\"repayBorrowAllowed(address,address,address,uint256)\":{\"params\":{\"borrower\":\"The account which would borrowed the asset\",\"cToken\":\"The market to verify the repay against\",\"payer\":\"The account which would repay the asset\",\"repayAmount\":\"The amount of the underlying asset the account would repay\"},\"return\":\"0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"repayBorrowVerify(address,address,address,uint256,uint256)\":{\"params\":{\"actualRepayAmount\":\"The amount of underlying being repaid\",\"borrower\":\"The address of the borrower\",\"cToken\":\"Asset being repaid\",\"payer\":\"The address repaying the borrow\"}},\"seizeAllowed(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"seizeTokens\":\"The number of collateral tokens to seize\"}},\"seizeVerify(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"cTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"cTokenCollateral\":\"Asset which was used as collateral and will be seized\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"seizeTokens\":\"The number of collateral tokens to seize\"}},\"transferAllowed(address,address,address,uint256)\":{\"params\":{\"cToken\":\"The market to verify the transfer against\",\"dst\":\"The account which receives the tokens\",\"src\":\"The account which sources the tokens\",\"transferTokens\":\"The number of cTokens to transfer\"},\"return\":\"0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"},\"transferVerify(address,address,address,uint256)\":{\"params\":{\"cToken\":\"Asset being transferred\",\"dst\":\"The account which receives the tokens\",\"src\":\"The account which sources the tokens\",\"transferTokens\":\"The number of cTokens to transfer\"}},\"updateContributorRewards(address)\":{\"params\":{\"contributor\":\"The address to calculate contributor rewards for\"}}}},\"userdoc\":{\"methods\":{\"_addCompMarkets(address[])\":{\"notice\":\"Add markets to compMarkets, allowing them to earn COMP in the flywheel\"},\"_dropCompMarket(address)\":{\"notice\":\"Remove a market from compMarkets, preventing it from earning COMP in the flywheel\"},\"_grantComp(address,uint256)\":{\"notice\":\"Transfer COMP to the recipient\"},\"_setBorrowCapGuardian(address)\":{\"notice\":\"Admin function to change the Borrow Cap Guardian\"},\"_setCloseFactor(uint256)\":{\"notice\":\"Sets the closeFactor used when liquidating borrows\"},\"_setCollateralFactor(address,uint256)\":{\"notice\":\"Sets the collateralFactor for a market\"},\"_setCompRate(uint256)\":{\"notice\":\"Set the amount of COMP distributed per block\"},\"_setContributorCompSpeed(address,uint256)\":{\"notice\":\"Set COMP speed for a single contributor\"},\"_setLiquidationIncentive(uint256)\":{\"notice\":\"Sets liquidationIncentive\"},\"_setMarketBorrowCaps(address[],uint256[])\":{\"notice\":\"Set the given borrow caps for the given cToken markets. Borrowing that brings total borrows to or above borrow cap will revert.\"},\"_setPauseGuardian(address)\":{\"notice\":\"Admin function to change the Pause Guardian\"},\"_setPriceOracle(address)\":{\"notice\":\"Sets a new price oracle for the comptroller\"},\"_supportMarket(address)\":{\"notice\":\"Add the market to the markets mapping and set it as listed\"},\"borrowAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to borrow the underlying asset of the given market\"},\"borrowVerify(address,address,uint256)\":{\"notice\":\"Validates borrow and reverts on rejection. May emit logs.\"},\"checkMembership(address,address)\":{\"notice\":\"Returns whether the given account is entered in the given asset\"},\"claimComp(address)\":{\"notice\":\"Claim all the comp accrued by holder in all markets\"},\"claimComp(address,address[])\":{\"notice\":\"Claim all the comp accrued by holder in the specified markets\"},\"claimComp(address[],address[],bool,bool)\":{\"notice\":\"Claim all comp accrued by the holders\"},\"enterMarkets(address[])\":{\"notice\":\"Add assets to be included in account liquidity calculation\"},\"exitMarket(address)\":{\"notice\":\"Removes asset from sender's account liquidity calculation\"},\"getAccountLiquidity(address)\":{\"notice\":\"Determine the current account liquidity wrt collateral requirements\"},\"getAllMarkets()\":{\"notice\":\"Return all of the markets\"},\"getAssetsIn(address)\":{\"notice\":\"Returns the assets an account has entered\"},\"getHypotheticalAccountLiquidity(address,address,uint256,uint256)\":{\"notice\":\"Determine what the account liquidity would be if the given amounts were redeemed/borrowed\"},\"liquidateBorrowAllowed(address,address,address,address,uint256)\":{\"notice\":\"Checks if the liquidation should be allowed to occur\"},\"liquidateBorrowVerify(address,address,address,address,uint256,uint256)\":{\"notice\":\"Validates liquidateBorrow and reverts on rejection. May emit logs.\"},\"liquidateCalculateSeizeTokens(address,address,uint256)\":{\"notice\":\"Calculate number of tokens of collateral asset to seize given an underlying amount\"},\"mintAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to mint tokens in the given market\"},\"mintVerify(address,address,uint256,uint256)\":{\"notice\":\"Validates mint and reverts on rejection. May emit logs.\"},\"redeemAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to redeem tokens in the given market\"},\"redeemVerify(address,address,uint256,uint256)\":{\"notice\":\"Validates redeem and reverts on rejection. May emit logs.\"},\"refreshCompSpeeds()\":{\"notice\":\"Recalculate and update COMP speeds for all COMP markets\"},\"repayBorrowAllowed(address,address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to repay a borrow in the given market\"},\"repayBorrowVerify(address,address,address,uint256,uint256)\":{\"notice\":\"Validates repayBorrow and reverts on rejection. May emit logs.\"},\"seizeAllowed(address,address,address,address,uint256)\":{\"notice\":\"Checks if the seizing of assets should be allowed to occur\"},\"seizeVerify(address,address,address,address,uint256)\":{\"notice\":\"Validates seize and reverts on rejection. May emit logs.\"},\"transferAllowed(address,address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to transfer tokens in the given market\"},\"transferVerify(address,address,address,uint256)\":{\"notice\":\"Validates transfer and reverts on rejection. May emit logs.\"},\"updateContributorRewards(address)\":{\"notice\":\"Calculate additional accrued COMP for a contributor since last accrual\"}}}},\"settings\":{\"compilationTarget\":{\"tests/Contracts/ComptrollerScenarioG6.sol\":\"ComptrollerScenarioG6\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/CToken.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./CTokenInterfaces.sol\\\";\\nimport \\\"./ErrorReporter.sol\\\";\\nimport \\\"./Exponential.sol\\\";\\nimport \\\"./EIP20Interface.sol\\\";\\nimport \\\"./InterestRateModel.sol\\\";\\n\\n/**\\n * @title Compound's CToken Contract\\n * @notice Abstract base for CTokens\\n * @author Compound\\n */\\ncontract CToken is CTokenInterface, Exponential, TokenErrorReporter {\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_) public {\\n require(msg.sender == admin, \\\"only admin may initialize the market\\\");\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = getBlockNumber();\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Transfer `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = uint(-1);\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srcTokensNew;\\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, srcTokensNew) = 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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srcTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != uint(-1)) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n // unused function\\n // comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transfer(address dst, uint256 amount) external nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferFrom(address src, address dst, uint256 amount) external nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (-1 means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool) {\\n address src = msg.sender;\\n transferAllowances[src][spender] = amount;\\n emit Approval(src, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (-1 means infinite)\\n */\\n function allowance(address owner, address spender) external view returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external returns (uint) {\\n Exp memory exchangeRate = Exp({mantissa: exchangeRateCurrent()});\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n require(mErr == MathError.NO_ERROR, \\\"balance could not be calculated\\\");\\n return balance;\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view returns (uint, uint, uint, uint) {\\n uint cTokenBalance = accountTokens[account];\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), cTokenBalance, borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @dev Function to simply retrieve block number\\n * This exists mainly for inheriting test contracts to stub this result.\\n */\\n function getBlockNumber() internal view returns (uint) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this cToken\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view returns (uint) {\\n return interestRateModel.getBorrowRate(getCashPrior(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this cToken\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view returns (uint) {\\n return interestRateModel.getSupplyRate(getCashPrior(), totalBorrows, totalReserves, reserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n require(err == MathError.NO_ERROR, \\\"borrowBalanceStored: borrowBalanceStoredInternal failed\\\");\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return (error code, the calculated balance or 0 if error code is non-zero)\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the CToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n require(err == MathError.NO_ERROR, \\\"exchangeRateStored: exchangeRateStoredInternal failed\\\");\\n return result;\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the CToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return (error code, calculated exchange rate scaled by 1e18)\\n */\\n function exchangeRateStoredInternal() internal view returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows - totalReserves) / totalSupply\\n */\\n uint totalCash = getCashPrior();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Get cash balance of this cToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage.\\n */\\n function accrueInterest() public returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = getBlockNumber();\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = getCashPrior();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n require(mathErr == MathError.NO_ERROR, \\\"could not calculate block delta\\\");\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({mantissa: borrowRateMantissa}), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(Exp({mantissa: reserveFactorMantissa}), interestAccumulated, reservesPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives cTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n struct MintLocalVars {\\n Error err;\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives cTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, 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's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the cToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of cTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.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 cTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED\\\");\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\\");\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender redeems cTokens in exchange for the underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemTokens The number of cTokens to redeem into underlying\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemInternal(uint redeemTokens) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(msg.sender, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems cTokens in exchange for a specified amount of underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemAmount The amount of underlying to receive from redeeming cTokens\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemUnderlyingInternal(uint redeemAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(msg.sender, 0, redeemAmount);\\n }\\n\\n struct RedeemLocalVars {\\n Error err;\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n /**\\n * @notice User redeems cTokens in exchange for the underlying asset\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param redeemTokensIn The number of cTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming cTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function redeemFresh(address payable redeemer, uint redeemTokensIn, uint redeemAmountIn) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr));\\n }\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(Exp({mantissa: vars.exchangeRateMantissa}), redeemTokensIn);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(redeemAmountIn, Exp({mantissa: vars.exchangeRateMantissa}));\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REDEEM_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDEEM_FRESHNESS_CHECK);\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED, uint(vars.mathErr));\\n }\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDEEM_TRANSFER_OUT_NOT_POSSIBLE);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We invoke doTransferOut for the redeemer and the redeemAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(redeemer, vars.redeemAmount);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n /* We call the defense hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender borrows assets from the protocol to their own address\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function borrowInternal(uint borrowAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(msg.sender, borrowAmount);\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n /**\\n * @notice Users borrow assets from the protocol to their own address\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function borrowFresh(address payable borrower, uint borrowAmount) internal returns (uint) {\\n /* Fail if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.BORROW_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.BORROW_FRESHNESS_CHECK);\\n }\\n\\n /* Fail gracefully if protocol has insufficient underlying cash */\\n if (getCashPrior() < borrowAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.BORROW_CASH_NOT_AVAILABLE);\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We invoke doTransferOut for the borrower and the borrowAmount.\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(borrower, borrowAmount);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to borrower\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer the account paying off the borrow\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount the amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.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 & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED\\\");\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n require(vars.mathErr == MathError.NO_ERROR, \\\"REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED\\\");\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this cToken to be liquidated\\n * @param cTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) 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 = cTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, cTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this cToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param cTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowFresh(address liquidator, address borrower, uint repayAmount, CTokenInterface cTokenCollateral) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(address(this), address(cTokenCollateral), liquidator, borrower, repayAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify cTokenCollateral market's block number equals current block number */\\n if (cTokenCollateral.accrualBlockNumber() != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = -1 */\\n if (repayAmount == uint(-1)) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & 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(cTokenCollateral), actualRepayAmount);\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(cTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(cTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = cTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(cTokenCollateral), seizeTokens);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.liquidateBorrowVerify(address(this), address(cTokenCollateral), liquidator, borrower, actualRepayAmount, seizeTokens);\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another cToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed cToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of cTokens to seize\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function seize(address liquidator, address borrower, uint seizeTokens) external nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n struct SeizeInternalLocalVars {\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n uint liquidatorSeizeTokens;\\n uint protocolSeizeTokens;\\n uint protocolSeizeAmount;\\n uint exchangeRateMantissa;\\n uint totalReservesNew;\\n uint totalSupplyNew;\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another CToken.\\n * Its absolutely critical to use msg.sender as the seizer cToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed cToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of cTokens to seize\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function seizeInternal(address seizerToken, address liquidator, address borrower, uint seizeTokens) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n SeizeInternalLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (vars.mathErr, vars.borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(vars.mathErr));\\n }\\n\\n vars.protocolSeizeTokens = mul_(seizeTokens, Exp({mantissa: protocolSeizeShareMantissa}));\\n vars.liquidatorSeizeTokens = sub_(seizeTokens, vars.protocolSeizeTokens);\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n require(vars.mathErr == MathError.NO_ERROR, \\\"exchange rate math error\\\");\\n\\n vars.protocolSeizeAmount = mul_ScalarTruncate(Exp({mantissa: vars.exchangeRateMantissa}), vars.protocolSeizeTokens);\\n\\n vars.totalReservesNew = add_(totalReserves, vars.protocolSeizeAmount);\\n vars.totalSupplyNew = sub_(totalSupply, vars.protocolSeizeTokens);\\n\\n (vars.mathErr, vars.liquidatorTokensNew) = addUInt(accountTokens[liquidator], vars.liquidatorSeizeTokens);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(vars.mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n totalReserves = vars.totalReservesNew;\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[borrower] = vars.borrowerTokensNew;\\n accountTokens[liquidator] = vars.liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, vars.liquidatorSeizeTokens);\\n emit Transfer(borrower, address(this), vars.protocolSeizeTokens);\\n emit ReservesAdded(address(this), vars.protocolSeizeAmount, vars.totalReservesNew);\\n\\n /* We call the defense hook */\\n // unused function\\n // comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n\\n /*** Admin Functions ***/\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPendingAdmin(address payable newPendingAdmin) external returns (uint) {\\n // Check caller = admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\\n }\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptAdmin() external returns (uint) {\\n // Check caller is pendingAdmin and pendingAdmin \\u2260 address(0)\\n if (msg.sender != pendingAdmin || msg.sender == address(0)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = address(0);\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setComptroller(ComptrollerInterface newComptroller) public returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_COMPTROLLER_OWNER_CHECK);\\n }\\n\\n ComptrollerInterface oldComptroller = comptroller;\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(oldComptroller, newComptroller);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh\\n * @dev Admin function to accrue interest and set a new reserve factor\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setReserveFactor(uint newReserveFactorMantissa) external nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\\n * @dev Admin function to set a new reserve factor\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_RESERVE_FACTOR_ADMIN_CHECK);\\n }\\n\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring from msg.sender\\n * @param addAmount Amount of addition to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\\n * On success, the cToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to admin\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _reduceReserves(uint reduceAmount) external nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to admin\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _reduceReservesFresh(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's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n totalReservesNew = totalReserves - reduceAmount;\\n // We checked reduceAmount <= totalReserves above, so this should never revert.\\n require(totalReservesNew <= 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't be sure if side effects occurred.\\n doTransferOut(admin, reduceAmount);\\n\\n emit ReservesReduced(admin, reduceAmount, totalReservesNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Admin function to accrue interest and update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel);\\n }\\n\\n /**\\n * @notice updates the interest rate model (*requires fresh interest accrual)\\n * @dev Admin function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal returns (uint) {\\n\\n // Used to store old model for use in the event that is emitted on success\\n InterestRateModel oldInterestRateModel;\\n\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_INTEREST_RATE_MODEL_OWNER_CHECK);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != getBlockNumber()) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Track the market's current interest rate model\\n oldInterestRateModel = interestRateModel;\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view returns (uint);\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure tather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal;\\n\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n}\\n\",\"keccak256\":\"0x436ec2e309682995f8a82dfdd9e8f75928599c10a9a680dddbee6c275014008d\"},\"contracts/CTokenInterfaces.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./InterestRateModel.sol\\\";\\nimport \\\"./EIP20NonStandardInterface.sol\\\";\\n\\ncontract CTokenStorage {\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-cToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModel public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first CTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping (address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping (address => mapping (address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Share of seized collateral that is added to reserves\\n */\\n uint public constant protocolSeizeShareMantissa = 2.8e16; //2.8%\\n\\n}\\n\\ncontract CTokenInterface is CTokenStorage {\\n /**\\n * @notice Indicator that this is a CToken contract (for inspection)\\n */\\n bool public constant isCToken = true;\\n\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(address liquidator, address borrower, uint repayAmount, address cTokenCollateral, uint seizeTokens);\\n\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin is updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(InterestRateModel oldInterestRateModel, InterestRateModel newInterestRateModel);\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address admin, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Failure event\\n */\\n event Failure(uint error, uint info, uint detail);\\n\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external returns (bool);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function approve(address spender, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function balanceOfUnderlying(address owner) external returns (uint);\\n function getAccountSnapshot(address account) external view returns (uint, uint, uint, uint);\\n function borrowRatePerBlock() external view returns (uint);\\n function supplyRatePerBlock() external view returns (uint);\\n function totalBorrowsCurrent() external returns (uint);\\n function borrowBalanceCurrent(address account) external returns (uint);\\n function borrowBalanceStored(address account) public view returns (uint);\\n function exchangeRateCurrent() public returns (uint);\\n function exchangeRateStored() public view returns (uint);\\n function getCash() external view returns (uint);\\n function accrueInterest() public returns (uint);\\n function seize(address liquidator, address borrower, uint seizeTokens) external returns (uint);\\n\\n\\n /*** Admin Functions ***/\\n\\n function _setPendingAdmin(address payable newPendingAdmin) external returns (uint);\\n function _acceptAdmin() external returns (uint);\\n function _setComptroller(ComptrollerInterface newComptroller) public returns (uint);\\n function _setReserveFactor(uint newReserveFactorMantissa) external returns (uint);\\n function _reduceReserves(uint reduceAmount) external returns (uint);\\n function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint);\\n}\\n\\ncontract CErc20Storage {\\n /**\\n * @notice Underlying asset for this CToken\\n */\\n address public underlying;\\n}\\n\\ncontract CErc20Interface is CErc20Storage {\\n\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n function redeem(uint redeemTokens) external returns (uint);\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n function borrow(uint borrowAmount) external returns (uint);\\n function repayBorrow(uint repayAmount) external returns (uint);\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n function liquidateBorrow(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) external returns (uint);\\n function sweepToken(EIP20NonStandardInterface token) external;\\n\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ncontract CDelegationStorage {\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n}\\n\\ncontract CDelegatorInterface is CDelegationStorage {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(address implementation_, bool allowResign, bytes memory becomeImplementationData) public;\\n}\\n\\ncontract CDelegateInterface is CDelegationStorage {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) public;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() public;\\n}\\n\",\"keccak256\":\"0x963bbf60b4c0b76900b3fcb2db8c8be634934b37b4113f1055e57a308197d21a\"},\"contracts/CarefulMath.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Careful Math\\n * @author Compound\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c = a * b;\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n return (MathError.NO_ERROR, a - b);\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c = a + b;\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\",\"keccak256\":\"0x0647348f27e41d22555d99eebd217dee02a4d737df6accd7cce5347a7487c7de\"},\"contracts/ComptrollerG6.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.sol\\\";\\nimport \\\"./ErrorReporter.sol\\\";\\nimport \\\"./PriceOracle.sol\\\";\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./ComptrollerStorage.sol\\\";\\nimport \\\"./Unitroller.sol\\\";\\nimport \\\"./Governance/Comp.sol\\\";\\n\\n/**\\n * @title Compound's Comptroller Contract\\n * @author Compound\\n */\\ncontract ComptrollerG6 is ComptrollerV5Storage, ComptrollerInterface, ComptrollerErrorReporter, ExponentialNoError {\\n /// @notice Emitted when an admin supports a market\\n event MarketListed(CToken cToken);\\n\\n /// @notice Emitted when an account enters a market\\n event MarketEntered(CToken cToken, address account);\\n\\n /// @notice Emitted when an account exits a market\\n event MarketExited(CToken cToken, 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(CToken cToken, uint oldCollateralFactorMantissa, uint newCollateralFactorMantissa);\\n\\n /// @notice Emitted when liquidation incentive is changed by admin\\n event NewLiquidationIncentive(uint oldLiquidationIncentiveMantissa, uint newLiquidationIncentiveMantissa);\\n\\n /// @notice Emitted when price oracle is changed\\n event NewPriceOracle(PriceOracle oldPriceOracle, PriceOracle newPriceOracle);\\n\\n /// @notice Emitted when pause guardian is changed\\n event NewPauseGuardian(address oldPauseGuardian, address newPauseGuardian);\\n\\n /// @notice Emitted when an action is paused globally\\n event ActionPaused(string action, bool pauseState);\\n\\n /// @notice Emitted when an action is paused on a market\\n event ActionPaused(CToken cToken, string action, bool pauseState);\\n\\n /// @notice Emitted when market comped status is changed\\n event MarketComped(CToken cToken, bool isComped);\\n\\n /// @notice Emitted when COMP rate is changed\\n event NewCompRate(uint oldCompRate, uint newCompRate);\\n\\n /// @notice Emitted when a new COMP speed is calculated for a market\\n event CompSpeedUpdated(CToken indexed cToken, uint newSpeed);\\n\\n /// @notice Emitted when a new COMP speed is set for a contributor\\n event ContributorCompSpeedUpdated(address indexed contributor, uint newSpeed);\\n\\n /// @notice Emitted when COMP is distributed to a supplier\\n event DistributedSupplierComp(CToken indexed cToken, address indexed supplier, uint compDelta, uint compSupplyIndex);\\n\\n /// @notice Emitted when COMP is distributed to a borrower\\n event DistributedBorrowerComp(CToken indexed cToken, address indexed borrower, uint compDelta, uint compBorrowIndex);\\n\\n /// @notice Emitted when borrow cap for a cToken is changed\\n event NewBorrowCap(CToken indexed cToken, uint newBorrowCap);\\n\\n /// @notice Emitted when borrow cap guardian is changed\\n event NewBorrowCapGuardian(address oldBorrowCapGuardian, address newBorrowCapGuardian);\\n\\n /// @notice Emitted when COMP is granted by admin\\n event CompGranted(address recipient, uint amount);\\n\\n /// @notice The threshold above which the flywheel transfers COMP, in wei\\n uint public constant compClaimThreshold = 0.001e18;\\n\\n /// @notice The initial COMP index for a market\\n uint224 public constant compInitialIndex = 1e36;\\n\\n // closeFactorMantissa must be strictly greater than this value\\n uint internal constant closeFactorMinMantissa = 0.05e18; // 0.05\\n\\n // closeFactorMantissa must not exceed this value\\n uint internal constant closeFactorMaxMantissa = 0.9e18; // 0.9\\n\\n // No collateralFactorMantissa may exceed this value\\n uint internal constant collateralFactorMaxMantissa = 0.9e18; // 0.9\\n\\n constructor() public {\\n admin = msg.sender;\\n }\\n\\n /*** Assets You Are In ***/\\n\\n /**\\n * @notice Returns the assets an account has entered\\n * @param account The address of the account to pull assets for\\n * @return A dynamic list with the assets the account has entered\\n */\\n function getAssetsIn(address account) external view returns (CToken[] memory) {\\n CToken[] memory assetsIn = accountAssets[account];\\n\\n return assetsIn;\\n }\\n\\n /**\\n * @notice Returns whether the given account is entered in the given asset\\n * @param account The address of the account to check\\n * @param cToken The cToken to check\\n * @return True if the account is in the asset, otherwise false.\\n */\\n function checkMembership(address account, CToken cToken) external view returns (bool) {\\n return markets[address(cToken)].accountMembership[account];\\n }\\n\\n /**\\n * @notice Add assets to be included in account liquidity calculation\\n * @param cTokens The list of addresses of the cToken markets to be enabled\\n * @return Success indicator for whether each corresponding market was entered\\n */\\n function enterMarkets(address[] memory cTokens) public returns (uint[] memory) {\\n uint len = cTokens.length;\\n\\n uint[] memory results = new uint[](len);\\n for (uint i = 0; i < len; i++) {\\n CToken cToken = CToken(cTokens[i]);\\n\\n results[i] = uint(addToMarketInternal(cToken, msg.sender));\\n }\\n\\n return results;\\n }\\n\\n /**\\n * @notice Add the market to the borrower's \\\"assets in\\\" for liquidity calculations\\n * @param cToken The market to enter\\n * @param borrower The address of the account to modify\\n * @return Success indicator for whether the market was entered\\n */\\n function addToMarketInternal(CToken cToken, address borrower) internal returns (Error) {\\n Market storage marketToJoin = markets[address(cToken)];\\n\\n if (!marketToJoin.isListed) {\\n // market is not listed, cannot join\\n return Error.MARKET_NOT_LISTED;\\n }\\n\\n if (marketToJoin.accountMembership[borrower] == true) {\\n // already joined\\n return Error.NO_ERROR;\\n }\\n\\n // survived the gauntlet, add to list\\n // NOTE: we store these somewhat redundantly as a significant optimization\\n // this avoids having to iterate through the list for the most common use cases\\n // that is, only when we need to perform liquidity checks\\n // and not whenever we want to check if an account is in a particular market\\n marketToJoin.accountMembership[borrower] = true;\\n accountAssets[borrower].push(cToken);\\n\\n emit MarketEntered(cToken, borrower);\\n\\n return Error.NO_ERROR;\\n }\\n\\n /**\\n * @notice Removes asset from sender's 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 cTokenAddress The address of the asset to be removed\\n * @return Whether or not the account successfully exited the market\\n */\\n function exitMarket(address cTokenAddress) external returns (uint) {\\n CToken cToken = CToken(cTokenAddress);\\n /* Get sender tokensHeld and amountOwed underlying from the cToken */\\n (uint oErr, uint tokensHeld, uint amountOwed, ) = cToken.getAccountSnapshot(msg.sender);\\n require(oErr == 0, \\\"exitMarket: getAccountSnapshot failed\\\"); // semi-opaque error code\\n\\n /* Fail if the sender has a borrow balance */\\n if (amountOwed != 0) {\\n return fail(Error.NONZERO_BORROW_BALANCE, FailureInfo.EXIT_MARKET_BALANCE_OWED);\\n }\\n\\n /* Fail if the sender is not permitted to redeem all of their tokens */\\n uint allowed = redeemAllowedInternal(cTokenAddress, msg.sender, tokensHeld);\\n if (allowed != 0) {\\n return failOpaque(Error.REJECTION, FailureInfo.EXIT_MARKET_REJECTION, allowed);\\n }\\n\\n Market storage marketToExit = markets[address(cToken)];\\n\\n /* Return true if the sender is not already \\u2018in\\u2019 the market */\\n if (!marketToExit.accountMembership[msg.sender]) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Set cToken account membership to false */\\n delete marketToExit.accountMembership[msg.sender];\\n\\n /* Delete cToken from the account\\u2019s list of assets */\\n // load into memory for faster iteration\\n CToken[] memory userAssetList = accountAssets[msg.sender];\\n uint len = userAssetList.length;\\n uint assetIndex = len;\\n for (uint i = 0; i < len; i++) {\\n if (userAssetList[i] == cToken) {\\n assetIndex = i;\\n break;\\n }\\n }\\n\\n // We *must* have found the asset in the list or our redundant data structure is broken\\n assert(assetIndex < len);\\n\\n // copy last item in list to location of item to be removed, reduce length by 1\\n CToken[] storage storedList = accountAssets[msg.sender];\\n storedList[assetIndex] = storedList[storedList.length - 1];\\n storedList.length--;\\n\\n emit MarketExited(cToken, 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 cToken The market to verify the mint against\\n * @param minter The account which would get the minted tokens\\n * @param mintAmount The amount of underlying being supplied to the market in exchange for tokens\\n * @return 0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function mintAllowed(address cToken, address minter, uint mintAmount) external returns (uint) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n require(!mintGuardianPaused[cToken], \\\"mint is paused\\\");\\n\\n // Shh - currently unused\\n minter;\\n mintAmount;\\n\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n // Keep the flywheel moving\\n updateCompSupplyIndex(cToken);\\n distributeSupplierComp(cToken, minter, false);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates mint and reverts on rejection. May emit logs.\\n * @param cToken Asset being minted\\n * @param minter The address minting the tokens\\n * @param actualMintAmount The amount of the underlying asset being minted\\n * @param mintTokens The number of tokens being minted\\n */\\n function mintVerify(address cToken, address minter, uint actualMintAmount, uint mintTokens) external {\\n // Shh - currently unused\\n cToken;\\n minter;\\n actualMintAmount;\\n mintTokens;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to redeem tokens in the given market\\n * @param cToken The market to verify the redeem against\\n * @param redeemer The account which would redeem the tokens\\n * @param redeemTokens The number of cTokens to exchange for the underlying asset in the market\\n * @return 0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function redeemAllowed(address cToken, address redeemer, uint redeemTokens) external returns (uint) {\\n uint allowed = redeemAllowedInternal(cToken, redeemer, redeemTokens);\\n if (allowed != uint(Error.NO_ERROR)) {\\n return allowed;\\n }\\n\\n // Keep the flywheel moving\\n updateCompSupplyIndex(cToken);\\n distributeSupplierComp(cToken, redeemer, false);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n function redeemAllowedInternal(address cToken, address redeemer, uint redeemTokens) internal view returns (uint) {\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!markets[cToken].accountMembership[redeemer]) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n (Error err, , uint shortfall) = getHypotheticalAccountLiquidityInternal(redeemer, CToken(cToken), redeemTokens, 0);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n if (shortfall > 0) {\\n return uint(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates redeem and reverts on rejection. May emit logs.\\n * @param cToken Asset being redeemed\\n * @param redeemer The address redeeming the tokens\\n * @param redeemAmount The amount of the underlying asset being redeemed\\n * @param redeemTokens The number of tokens being redeemed\\n */\\n function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) external {\\n // Shh - currently unused\\n cToken;\\n redeemer;\\n\\n // Require tokens is zero or amount is also zero\\n if (redeemTokens == 0 && redeemAmount > 0) {\\n revert(\\\"redeemTokens zero\\\");\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to borrow the underlying asset of the given market\\n * @param cToken The market to verify the borrow against\\n * @param borrower The account which would borrow the asset\\n * @param borrowAmount The amount of underlying the account would borrow\\n * @return 0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function borrowAllowed(address cToken, address borrower, uint borrowAmount) external returns (uint) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n require(!borrowGuardianPaused[cToken], \\\"borrow is paused\\\");\\n\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n if (!markets[cToken].accountMembership[borrower]) {\\n // only cTokens may call borrowAllowed if borrower not in market\\n require(msg.sender == cToken, \\\"sender must be cToken\\\");\\n\\n // attempt to add borrower to the market\\n Error err = addToMarketInternal(CToken(msg.sender), borrower);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n\\n // it should be impossible to break the important invariant\\n assert(markets[cToken].accountMembership[borrower]);\\n }\\n\\n if (oracle.getUnderlyingPrice(CToken(cToken)) == 0) {\\n return uint(Error.PRICE_ERROR);\\n }\\n\\n\\n uint borrowCap = borrowCaps[cToken];\\n // Borrow cap of 0 corresponds to unlimited borrowing\\n if (borrowCap != 0) {\\n uint totalBorrows = CToken(cToken).totalBorrows();\\n uint nextTotalBorrows = add_(totalBorrows, borrowAmount);\\n require(nextTotalBorrows < borrowCap, \\\"market borrow cap reached\\\");\\n }\\n\\n (Error err, , uint shortfall) = getHypotheticalAccountLiquidityInternal(borrower, CToken(cToken), 0, borrowAmount);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n if (shortfall > 0) {\\n return uint(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n\\n // Keep the flywheel moving\\n Exp memory borrowIndex = Exp({mantissa: CToken(cToken).borrowIndex()});\\n updateCompBorrowIndex(cToken, borrowIndex);\\n distributeBorrowerComp(cToken, borrower, borrowIndex, false);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates borrow and reverts on rejection. May emit logs.\\n * @param cToken Asset whose underlying is being borrowed\\n * @param borrower The address borrowing the underlying\\n * @param borrowAmount The amount of the underlying asset requested to borrow\\n */\\n function borrowVerify(address cToken, address borrower, uint borrowAmount) external {\\n // Shh - currently unused\\n cToken;\\n borrower;\\n borrowAmount;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to repay a borrow in the given market\\n * @param cToken The market to verify the repay against\\n * @param payer The account which would repay the asset\\n * @param borrower The account which would borrowed the asset\\n * @param repayAmount The amount of the underlying asset the account would repay\\n * @return 0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function repayBorrowAllowed(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount) external returns (uint) {\\n // Shh - currently unused\\n payer;\\n borrower;\\n repayAmount;\\n\\n if (!markets[cToken].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n // Keep the flywheel moving\\n Exp memory borrowIndex = Exp({mantissa: CToken(cToken).borrowIndex()});\\n updateCompBorrowIndex(cToken, borrowIndex);\\n distributeBorrowerComp(cToken, borrower, borrowIndex, false);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates repayBorrow and reverts on rejection. May emit logs.\\n * @param cToken Asset being repaid\\n * @param payer The address repaying the borrow\\n * @param borrower The address of the borrower\\n * @param actualRepayAmount The amount of underlying being repaid\\n */\\n function repayBorrowVerify(\\n address cToken,\\n address payer,\\n address borrower,\\n uint actualRepayAmount,\\n uint borrowerIndex) external {\\n // Shh - currently unused\\n cToken;\\n payer;\\n borrower;\\n actualRepayAmount;\\n borrowerIndex;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the liquidation should be allowed to occur\\n * @param cTokenBorrowed Asset which was borrowed by the borrower\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param repayAmount The amount of underlying being repaid\\n */\\n function liquidateBorrowAllowed(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount) external returns (uint) {\\n // Shh - currently unused\\n liquidator;\\n\\n if (!markets[cTokenBorrowed].isListed || !markets[cTokenCollateral].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n /* The borrower must have shortfall in order to be liquidatable */\\n (Error err, , uint shortfall) = getAccountLiquidityInternal(borrower);\\n if (err != Error.NO_ERROR) {\\n return uint(err);\\n }\\n if (shortfall == 0) {\\n return uint(Error.INSUFFICIENT_SHORTFALL);\\n }\\n\\n /* The liquidator may not repay more than what is allowed by the closeFactor */\\n uint borrowBalance = CToken(cTokenBorrowed).borrowBalanceStored(borrower);\\n uint maxClose = mul_ScalarTruncate(Exp({mantissa: closeFactorMantissa}), borrowBalance);\\n if (repayAmount > 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 cTokenBorrowed Asset which was borrowed by the borrower\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param actualRepayAmount The amount of underlying being repaid\\n */\\n function liquidateBorrowVerify(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint actualRepayAmount,\\n uint seizeTokens) external {\\n // Shh - currently unused\\n cTokenBorrowed;\\n cTokenCollateral;\\n liquidator;\\n borrower;\\n actualRepayAmount;\\n seizeTokens;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the seizing of assets should be allowed to occur\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param cTokenBorrowed Asset which was borrowed by the borrower\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param seizeTokens The number of collateral tokens to seize\\n */\\n function seizeAllowed(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external returns (uint) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n require(!seizeGuardianPaused, \\\"seize is paused\\\");\\n\\n // Shh - currently unused\\n seizeTokens;\\n\\n if (!markets[cTokenCollateral].isListed || !markets[cTokenBorrowed].isListed) {\\n return uint(Error.MARKET_NOT_LISTED);\\n }\\n\\n if (CToken(cTokenCollateral).comptroller() != CToken(cTokenBorrowed).comptroller()) {\\n return uint(Error.COMPTROLLER_MISMATCH);\\n }\\n\\n // Keep the flywheel moving\\n updateCompSupplyIndex(cTokenCollateral);\\n distributeSupplierComp(cTokenCollateral, borrower, false);\\n distributeSupplierComp(cTokenCollateral, liquidator, false);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates seize and reverts on rejection. May emit logs.\\n * @param cTokenCollateral Asset which was used as collateral and will be seized\\n * @param cTokenBorrowed Asset which was borrowed by the borrower\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param seizeTokens The number of collateral tokens to seize\\n */\\n function seizeVerify(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external {\\n // Shh - currently unused\\n cTokenCollateral;\\n cTokenBorrowed;\\n liquidator;\\n borrower;\\n seizeTokens;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to transfer tokens in the given market\\n * @param cToken The market to verify the transfer against\\n * @param src The account which sources the tokens\\n * @param dst The account which receives the tokens\\n * @param transferTokens The number of cTokens to transfer\\n * @return 0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function transferAllowed(address cToken, address src, address dst, uint transferTokens) external returns (uint) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n require(!transferGuardianPaused, \\\"transfer is paused\\\");\\n\\n // Currently the only consideration is whether or not\\n // the src is allowed to redeem this many tokens\\n uint allowed = redeemAllowedInternal(cToken, src, transferTokens);\\n if (allowed != uint(Error.NO_ERROR)) {\\n return allowed;\\n }\\n\\n // Keep the flywheel moving\\n updateCompSupplyIndex(cToken);\\n distributeSupplierComp(cToken, src, false);\\n distributeSupplierComp(cToken, dst, false);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates transfer and reverts on rejection. May emit logs.\\n * @param cToken Asset being transferred\\n * @param src The account which sources the tokens\\n * @param dst The account which receives the tokens\\n * @param transferTokens The number of cTokens to transfer\\n */\\n function transferVerify(address cToken, address src, address dst, uint transferTokens) external {\\n // Shh - currently unused\\n cToken;\\n src;\\n dst;\\n transferTokens;\\n\\n // Shh - we don't ever want this hook to be marked pure\\n if (false) {\\n maxAssets = maxAssets;\\n }\\n }\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n /**\\n * @dev Local vars for avoiding stack-depth limits in calculating account liquidity.\\n * Note that `cTokenBalance` is the number of cTokens the account owns in the market,\\n * whereas `borrowBalance` is the amount of underlying that the account has borrowed.\\n */\\n struct AccountLiquidityLocalVars {\\n uint sumCollateral;\\n uint sumBorrowPlusEffects;\\n uint cTokenBalance;\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n uint oraclePriceMantissa;\\n Exp collateralFactor;\\n Exp exchangeRate;\\n Exp oraclePrice;\\n Exp tokensToDenom;\\n }\\n\\n /**\\n * @notice Determine the current account liquidity wrt collateral requirements\\n * @return (possible error code (semi-opaque),\\n account liquidity in excess of collateral requirements,\\n * account shortfall below collateral requirements)\\n */\\n function getAccountLiquidity(address account) public view returns (uint, uint, uint) {\\n (Error err, uint liquidity, uint shortfall) = getHypotheticalAccountLiquidityInternal(account, CToken(0), 0, 0);\\n\\n return (uint(err), liquidity, shortfall);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity wrt collateral requirements\\n * @return (possible error code,\\n account liquidity in excess of collateral requirements,\\n * account shortfall below collateral requirements)\\n */\\n function getAccountLiquidityInternal(address account) internal view returns (Error, uint, uint) {\\n return getHypotheticalAccountLiquidityInternal(account, CToken(0), 0, 0);\\n }\\n\\n /**\\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\\n * @param cTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @return (possible error code (semi-opaque),\\n hypothetical account liquidity in excess of collateral requirements,\\n * hypothetical account shortfall below collateral requirements)\\n */\\n function getHypotheticalAccountLiquidity(\\n address account,\\n address cTokenModify,\\n uint redeemTokens,\\n uint borrowAmount) public view returns (uint, uint, uint) {\\n (Error err, uint liquidity, uint shortfall) = getHypotheticalAccountLiquidityInternal(account, CToken(cTokenModify), 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 cTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @dev Note that we calculate the exchangeRateStored for each collateral cToken using stored data,\\n * without calculating accumulated interest.\\n * @return (possible error code,\\n hypothetical account liquidity in excess of collateral requirements,\\n * hypothetical account shortfall below collateral requirements)\\n */\\n function getHypotheticalAccountLiquidityInternal(\\n address account,\\n CToken cTokenModify,\\n uint redeemTokens,\\n uint borrowAmount) internal view returns (Error, uint, uint) {\\n\\n AccountLiquidityLocalVars memory vars; // Holds all our calculation results\\n uint oErr;\\n\\n // For each asset the account is in\\n CToken[] memory assets = accountAssets[account];\\n for (uint i = 0; i < assets.length; i++) {\\n CToken asset = assets[i];\\n\\n // Read the balances and exchange rate from the cToken\\n (oErr, vars.cTokenBalance, vars.borrowBalance, vars.exchangeRateMantissa) = asset.getAccountSnapshot(account);\\n if (oErr != 0) { // semi-opaque error code, we assume NO_ERROR == 0 is invariant between upgrades\\n return (Error.SNAPSHOT_ERROR, 0, 0);\\n }\\n vars.collateralFactor = Exp({mantissa: markets[address(asset)].collateralFactorMantissa});\\n vars.exchangeRate = Exp({mantissa: vars.exchangeRateMantissa});\\n\\n // Get the normalized price of the asset\\n vars.oraclePriceMantissa = oracle.getUnderlyingPrice(asset);\\n if (vars.oraclePriceMantissa == 0) {\\n return (Error.PRICE_ERROR, 0, 0);\\n }\\n vars.oraclePrice = Exp({mantissa: vars.oraclePriceMantissa});\\n\\n // Pre-compute a conversion factor from tokens -> ether (normalized price value)\\n vars.tokensToDenom = mul_(mul_(vars.collateralFactor, vars.exchangeRate), vars.oraclePrice);\\n\\n // sumCollateral += tokensToDenom * cTokenBalance\\n vars.sumCollateral = mul_ScalarTruncateAddUInt(vars.tokensToDenom, vars.cTokenBalance, vars.sumCollateral);\\n\\n // sumBorrowPlusEffects += oraclePrice * borrowBalance\\n vars.sumBorrowPlusEffects = mul_ScalarTruncateAddUInt(vars.oraclePrice, vars.borrowBalance, vars.sumBorrowPlusEffects);\\n\\n // Calculate effects of interacting with cTokenModify\\n if (asset == cTokenModify) {\\n // redeem effect\\n // sumBorrowPlusEffects += tokensToDenom * redeemTokens\\n vars.sumBorrowPlusEffects = mul_ScalarTruncateAddUInt(vars.tokensToDenom, redeemTokens, vars.sumBorrowPlusEffects);\\n\\n // borrow effect\\n // sumBorrowPlusEffects += oraclePrice * borrowAmount\\n vars.sumBorrowPlusEffects = mul_ScalarTruncateAddUInt(vars.oraclePrice, borrowAmount, vars.sumBorrowPlusEffects);\\n }\\n }\\n\\n // These are safe, as the underflow condition is checked first\\n if (vars.sumCollateral > vars.sumBorrowPlusEffects) {\\n return (Error.NO_ERROR, vars.sumCollateral - vars.sumBorrowPlusEffects, 0);\\n } else {\\n return (Error.NO_ERROR, 0, vars.sumBorrowPlusEffects - vars.sumCollateral);\\n }\\n }\\n\\n /**\\n * @notice Calculate number of tokens of collateral asset to seize given an underlying amount\\n * @dev Used in liquidation (called in cToken.liquidateBorrowFresh)\\n * @param cTokenBorrowed The address of the borrowed cToken\\n * @param cTokenCollateral The address of the collateral cToken\\n * @param actualRepayAmount The amount of cTokenBorrowed underlying to convert into cTokenCollateral tokens\\n * @return (errorCode, number of cTokenCollateral tokens to be seized in a liquidation)\\n */\\n function liquidateCalculateSeizeTokens(address cTokenBorrowed, address cTokenCollateral, uint actualRepayAmount) external view returns (uint, uint) {\\n /* Read oracle prices for borrowed and collateral markets */\\n uint priceBorrowedMantissa = oracle.getUnderlyingPrice(CToken(cTokenBorrowed));\\n uint priceCollateralMantissa = oracle.getUnderlyingPrice(CToken(cTokenCollateral));\\n if (priceBorrowedMantissa == 0 || priceCollateralMantissa == 0) {\\n return (uint(Error.PRICE_ERROR), 0);\\n }\\n\\n /*\\n * Get the exchange rate and calculate the number of collateral tokens to seize:\\n * seizeAmount = actualRepayAmount * liquidationIncentive * priceBorrowed / priceCollateral\\n * seizeTokens = seizeAmount / exchangeRate\\n * = actualRepayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate)\\n */\\n uint exchangeRateMantissa = CToken(cTokenCollateral).exchangeRateStored(); // Note: reverts on error\\n uint seizeTokens;\\n Exp memory numerator;\\n Exp memory denominator;\\n Exp memory ratio;\\n\\n numerator = mul_(Exp({mantissa: liquidationIncentiveMantissa}), Exp({mantissa: priceBorrowedMantissa}));\\n denominator = mul_(Exp({mantissa: priceCollateralMantissa}), Exp({mantissa: exchangeRateMantissa}));\\n ratio = div_(numerator, denominator);\\n\\n seizeTokens = mul_ScalarTruncate(ratio, actualRepayAmount);\\n\\n return (uint(Error.NO_ERROR), seizeTokens);\\n }\\n\\n /*** Admin Functions ***/\\n\\n /**\\n * @notice Sets a new price oracle for the comptroller\\n * @dev Admin function to set a new price oracle\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPriceOracle(PriceOracle newOracle) public returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PRICE_ORACLE_OWNER_CHECK);\\n }\\n\\n // Track the old oracle for the comptroller\\n PriceOracle oldOracle = oracle;\\n\\n // Set comptroller's oracle to newOracle\\n oracle = newOracle;\\n\\n // Emit NewPriceOracle(oldOracle, newOracle)\\n emit NewPriceOracle(oldOracle, newOracle);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets the closeFactor used when liquidating borrows\\n * @dev Admin function to set closeFactor\\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\\n * @return uint 0=success, otherwise a failure\\n */\\n function _setCloseFactor(uint newCloseFactorMantissa) external returns (uint) {\\n // Check caller is admin\\n \\trequire(msg.sender == admin, \\\"only admin can set close factor\\\");\\n\\n uint oldCloseFactorMantissa = closeFactorMantissa;\\n closeFactorMantissa = newCloseFactorMantissa;\\n emit NewCloseFactor(oldCloseFactorMantissa, closeFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets the collateralFactor for a market\\n * @dev Admin function to set per-market collateralFactor\\n * @param cToken The market to set the factor on\\n * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18\\n * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function _setCollateralFactor(CToken cToken, 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(cToken)];\\n if (!market.isListed) {\\n return fail(Error.MARKET_NOT_LISTED, FailureInfo.SET_COLLATERAL_FACTOR_NO_EXISTS);\\n }\\n\\n Exp memory newCollateralFactorExp = Exp({mantissa: newCollateralFactorMantissa});\\n\\n // Check collateral factor <= 0.9\\n Exp memory highLimit = Exp({mantissa: collateralFactorMaxMantissa});\\n if (lessThanExp(highLimit, newCollateralFactorExp)) {\\n return fail(Error.INVALID_COLLATERAL_FACTOR, FailureInfo.SET_COLLATERAL_FACTOR_VALIDATION);\\n }\\n\\n // If collateral factor != 0, fail if price == 0\\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(cToken) == 0) {\\n return fail(Error.PRICE_ERROR, FailureInfo.SET_COLLATERAL_FACTOR_WITHOUT_PRICE);\\n }\\n\\n // Set market's collateral factor to new collateral factor, remember old value\\n uint oldCollateralFactorMantissa = market.collateralFactorMantissa;\\n market.collateralFactorMantissa = newCollateralFactorMantissa;\\n\\n // Emit event with asset, old collateral factor, and new collateral factor\\n emit NewCollateralFactor(cToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets liquidationIncentive\\n * @dev Admin function to set liquidationIncentive\\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\\n * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function _setLiquidationIncentive(uint newLiquidationIncentiveMantissa) external returns (uint) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_LIQUIDATION_INCENTIVE_OWNER_CHECK);\\n }\\n\\n // Save current value for use in log\\n uint oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa;\\n\\n // Set liquidation incentive to new incentive\\n liquidationIncentiveMantissa = newLiquidationIncentiveMantissa;\\n\\n // Emit event with old incentive, new incentive\\n emit NewLiquidationIncentive(oldLiquidationIncentiveMantissa, newLiquidationIncentiveMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Add the market to the markets mapping and set it as listed\\n * @dev Admin function to set isListed and add support for the market\\n * @param cToken The address of the market (token) to list\\n * @return uint 0=success, otherwise a failure. (See enum Error for details)\\n */\\n function _supportMarket(CToken cToken) external returns (uint) {\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SUPPORT_MARKET_OWNER_CHECK);\\n }\\n\\n if (markets[address(cToken)].isListed) {\\n return fail(Error.MARKET_ALREADY_LISTED, FailureInfo.SUPPORT_MARKET_EXISTS);\\n }\\n\\n cToken.isCToken(); // Sanity check to make sure its really a CToken\\n\\n markets[address(cToken)] = Market({isListed: true, isComped: false, collateralFactorMantissa: 0});\\n\\n _addMarketInternal(address(cToken));\\n\\n emit MarketListed(cToken);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n function _addMarketInternal(address cToken) internal {\\n for (uint i = 0; i < allMarkets.length; i ++) {\\n require(allMarkets[i] != CToken(cToken), \\\"market already added\\\");\\n }\\n allMarkets.push(CToken(cToken));\\n }\\n\\n\\n /**\\n * @notice Set the given borrow caps for the given cToken markets. Borrowing that brings total borrows to or above borrow cap will revert.\\n * @dev Admin or borrowCapGuardian function to set the borrow caps. A borrow cap of 0 corresponds to unlimited borrowing.\\n * @param cTokens The addresses of the markets (tokens) to change the borrow caps for\\n * @param newBorrowCaps The new borrow cap values in underlying to be set. A value of 0 corresponds to unlimited borrowing.\\n */\\n function _setMarketBorrowCaps(CToken[] calldata cTokens, uint[] calldata newBorrowCaps) external {\\n \\trequire(msg.sender == admin || msg.sender == borrowCapGuardian, \\\"only admin or borrow cap guardian can set borrow caps\\\"); \\n\\n uint numMarkets = cTokens.length;\\n uint numBorrowCaps = newBorrowCaps.length;\\n\\n require(numMarkets != 0 && numMarkets == numBorrowCaps, \\\"invalid input\\\");\\n\\n for(uint i = 0; i < numMarkets; i++) {\\n borrowCaps[address(cTokens[i])] = newBorrowCaps[i];\\n emit NewBorrowCap(cTokens[i], newBorrowCaps[i]);\\n }\\n }\\n\\n /**\\n * @notice Admin function to change the Borrow Cap Guardian\\n * @param newBorrowCapGuardian The address of the new Borrow Cap Guardian\\n */\\n function _setBorrowCapGuardian(address newBorrowCapGuardian) external {\\n require(msg.sender == admin, \\\"only admin can set borrow cap guardian\\\");\\n\\n // Save current value for inclusion in log\\n address oldBorrowCapGuardian = borrowCapGuardian;\\n\\n // Store borrowCapGuardian with value newBorrowCapGuardian\\n borrowCapGuardian = newBorrowCapGuardian;\\n\\n // Emit NewBorrowCapGuardian(OldBorrowCapGuardian, NewBorrowCapGuardian)\\n emit NewBorrowCapGuardian(oldBorrowCapGuardian, newBorrowCapGuardian);\\n }\\n\\n /**\\n * @notice Admin function to change the Pause Guardian\\n * @param newPauseGuardian The address of the new Pause Guardian\\n * @return uint 0=success, otherwise a failure. (See enum Error for details)\\n */\\n function _setPauseGuardian(address newPauseGuardian) public returns (uint) {\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PAUSE_GUARDIAN_OWNER_CHECK);\\n }\\n\\n // Save current value for inclusion in log\\n address oldPauseGuardian = pauseGuardian;\\n\\n // Store pauseGuardian with value newPauseGuardian\\n pauseGuardian = newPauseGuardian;\\n\\n // Emit NewPauseGuardian(OldPauseGuardian, NewPauseGuardian)\\n emit NewPauseGuardian(oldPauseGuardian, pauseGuardian);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n function _setMintPaused(CToken cToken, bool state) public returns (bool) {\\n require(markets[address(cToken)].isListed, \\\"cannot pause a market that is not listed\\\");\\n require(msg.sender == pauseGuardian || msg.sender == admin, \\\"only pause guardian and admin can pause\\\");\\n require(msg.sender == admin || state == true, \\\"only admin can unpause\\\");\\n\\n mintGuardianPaused[address(cToken)] = state;\\n emit ActionPaused(cToken, \\\"Mint\\\", state);\\n return state;\\n }\\n\\n function _setBorrowPaused(CToken cToken, bool state) public returns (bool) {\\n require(markets[address(cToken)].isListed, \\\"cannot pause a market that is not listed\\\");\\n require(msg.sender == pauseGuardian || msg.sender == admin, \\\"only pause guardian and admin can pause\\\");\\n require(msg.sender == admin || state == true, \\\"only admin can unpause\\\");\\n\\n borrowGuardianPaused[address(cToken)] = state;\\n emit ActionPaused(cToken, \\\"Borrow\\\", state);\\n return state;\\n }\\n\\n function _setTransferPaused(bool state) public returns (bool) {\\n require(msg.sender == pauseGuardian || msg.sender == admin, \\\"only pause guardian and admin can pause\\\");\\n require(msg.sender == admin || state == true, \\\"only admin can unpause\\\");\\n\\n transferGuardianPaused = state;\\n emit ActionPaused(\\\"Transfer\\\", state);\\n return state;\\n }\\n\\n function _setSeizePaused(bool state) public returns (bool) {\\n require(msg.sender == pauseGuardian || msg.sender == admin, \\\"only pause guardian and admin can pause\\\");\\n require(msg.sender == admin || state == true, \\\"only admin can unpause\\\");\\n\\n seizeGuardianPaused = state;\\n emit ActionPaused(\\\"Seize\\\", state);\\n return state;\\n }\\n\\n function _become(Unitroller unitroller) public {\\n require(msg.sender == unitroller.admin(), \\\"only unitroller admin can change brains\\\");\\n require(unitroller._acceptImplementation() == 0, \\\"change not authorized\\\");\\n }\\n\\n /**\\n * @notice Checks caller is admin, or this contract is becoming the new implementation\\n */\\n function adminOrInitializing() internal view returns (bool) {\\n return msg.sender == admin || msg.sender == comptrollerImplementation;\\n }\\n\\n /*** Comp Distribution ***/\\n\\n /**\\n * @notice Recalculate and update COMP speeds for all COMP markets\\n */\\n function refreshCompSpeeds() public {\\n require(msg.sender == tx.origin, \\\"only externally owned accounts may refresh speeds\\\");\\n refreshCompSpeedsInternal();\\n }\\n\\n function refreshCompSpeedsInternal() internal {\\n CToken[] memory allMarkets_ = allMarkets;\\n\\n for (uint i = 0; i < allMarkets_.length; i++) {\\n CToken cToken = allMarkets_[i];\\n Exp memory borrowIndex = Exp({mantissa: cToken.borrowIndex()});\\n updateCompSupplyIndex(address(cToken));\\n updateCompBorrowIndex(address(cToken), borrowIndex);\\n }\\n\\n Exp memory totalUtility = Exp({mantissa: 0});\\n Exp[] memory utilities = new Exp[](allMarkets_.length);\\n for (uint i = 0; i < allMarkets_.length; i++) {\\n CToken cToken = allMarkets_[i];\\n if (markets[address(cToken)].isComped) {\\n Exp memory assetPrice = Exp({mantissa: oracle.getUnderlyingPrice(cToken)});\\n Exp memory utility = mul_(assetPrice, cToken.totalBorrows());\\n utilities[i] = utility;\\n totalUtility = add_(totalUtility, utility);\\n }\\n }\\n\\n for (uint i = 0; i < allMarkets_.length; i++) {\\n CToken cToken = allMarkets[i];\\n uint newSpeed = totalUtility.mantissa > 0 ? mul_(compRate, div_(utilities[i], totalUtility)) : 0;\\n compSpeeds[address(cToken)] = newSpeed;\\n emit CompSpeedUpdated(cToken, newSpeed);\\n }\\n }\\n\\n /**\\n * @notice Accrue COMP to the market by updating the supply index\\n * @param cToken The market whose supply index to update\\n */\\n function updateCompSupplyIndex(address cToken) internal {\\n CompMarketState storage supplyState = compSupplyState[cToken];\\n uint supplySpeed = compSpeeds[cToken];\\n uint blockNumber = getBlockNumber();\\n uint deltaBlocks = sub_(blockNumber, uint(supplyState.block));\\n if (deltaBlocks > 0 && supplySpeed > 0) {\\n uint supplyTokens = CToken(cToken).totalSupply();\\n uint compAccrued = mul_(deltaBlocks, supplySpeed);\\n Double memory ratio = supplyTokens > 0 ? fraction(compAccrued, supplyTokens) : Double({mantissa: 0});\\n Double memory index = add_(Double({mantissa: supplyState.index}), ratio);\\n compSupplyState[cToken] = CompMarketState({\\n index: safe224(index.mantissa, \\\"new index exceeds 224 bits\\\"),\\n block: safe32(blockNumber, \\\"block number exceeds 32 bits\\\")\\n });\\n } else if (deltaBlocks > 0) {\\n supplyState.block = safe32(blockNumber, \\\"block number exceeds 32 bits\\\");\\n }\\n }\\n\\n /**\\n * @notice Accrue COMP to the market by updating the borrow index\\n * @param cToken The market whose borrow index to update\\n */\\n function updateCompBorrowIndex(address cToken, Exp memory marketBorrowIndex) internal {\\n CompMarketState storage borrowState = compBorrowState[cToken];\\n uint borrowSpeed = compSpeeds[cToken];\\n uint blockNumber = getBlockNumber();\\n uint deltaBlocks = sub_(blockNumber, uint(borrowState.block));\\n if (deltaBlocks > 0 && borrowSpeed > 0) {\\n uint borrowAmount = div_(CToken(cToken).totalBorrows(), marketBorrowIndex);\\n uint compAccrued = mul_(deltaBlocks, borrowSpeed);\\n Double memory ratio = borrowAmount > 0 ? fraction(compAccrued, borrowAmount) : Double({mantissa: 0});\\n Double memory index = add_(Double({mantissa: borrowState.index}), ratio);\\n compBorrowState[cToken] = CompMarketState({\\n index: safe224(index.mantissa, \\\"new index exceeds 224 bits\\\"),\\n block: safe32(blockNumber, \\\"block number exceeds 32 bits\\\")\\n });\\n } else if (deltaBlocks > 0) {\\n borrowState.block = safe32(blockNumber, \\\"block number exceeds 32 bits\\\");\\n }\\n }\\n\\n /**\\n * @notice Calculate COMP accrued by a supplier and possibly transfer it to them\\n * @param cToken The market in which the supplier is interacting\\n * @param supplier The address of the supplier to distribute COMP to\\n */\\n function distributeSupplierComp(address cToken, address supplier, bool distributeAll) internal {\\n CompMarketState storage supplyState = compSupplyState[cToken];\\n Double memory supplyIndex = Double({mantissa: supplyState.index});\\n Double memory supplierIndex = Double({mantissa: compSupplierIndex[cToken][supplier]});\\n compSupplierIndex[cToken][supplier] = supplyIndex.mantissa;\\n\\n if (supplierIndex.mantissa == 0 && supplyIndex.mantissa > 0) {\\n supplierIndex.mantissa = compInitialIndex;\\n }\\n\\n Double memory deltaIndex = sub_(supplyIndex, supplierIndex);\\n uint supplierTokens = CToken(cToken).balanceOf(supplier);\\n uint supplierDelta = mul_(supplierTokens, deltaIndex);\\n uint supplierAccrued = add_(compAccrued[supplier], supplierDelta);\\n compAccrued[supplier] = transferComp(supplier, supplierAccrued, distributeAll ? 0 : compClaimThreshold);\\n emit DistributedSupplierComp(CToken(cToken), supplier, supplierDelta, supplyIndex.mantissa);\\n }\\n\\n /**\\n * @notice Calculate COMP accrued by a borrower and possibly transfer it to them\\n * @dev Borrowers will not begin to accrue until after the first interaction with the protocol.\\n * @param cToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute COMP to\\n */\\n function distributeBorrowerComp(address cToken, address borrower, Exp memory marketBorrowIndex, bool distributeAll) internal {\\n CompMarketState storage borrowState = compBorrowState[cToken];\\n Double memory borrowIndex = Double({mantissa: borrowState.index});\\n Double memory borrowerIndex = Double({mantissa: compBorrowerIndex[cToken][borrower]});\\n compBorrowerIndex[cToken][borrower] = borrowIndex.mantissa;\\n\\n if (borrowerIndex.mantissa > 0) {\\n Double memory deltaIndex = sub_(borrowIndex, borrowerIndex);\\n uint borrowerAmount = div_(CToken(cToken).borrowBalanceStored(borrower), marketBorrowIndex);\\n uint borrowerDelta = mul_(borrowerAmount, deltaIndex);\\n uint borrowerAccrued = add_(compAccrued[borrower], borrowerDelta);\\n compAccrued[borrower] = transferComp(borrower, borrowerAccrued, distributeAll ? 0 : compClaimThreshold);\\n emit DistributedBorrowerComp(CToken(cToken), borrower, borrowerDelta, borrowIndex.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Transfer COMP to the user, if they are above the threshold\\n * @dev Note: If there is not enough COMP, we do not perform the transfer all.\\n * @param user The address of the user to transfer COMP to\\n * @param userAccrued The amount of COMP to (possibly) transfer\\n * @return The amount of COMP which was NOT transferred to the user\\n */\\n function transferComp(address user, uint userAccrued, uint threshold) internal returns (uint) {\\n if (userAccrued >= threshold && userAccrued > 0) {\\n Comp comp = Comp(getCompAddress());\\n uint compRemaining = comp.balanceOf(address(this));\\n if (userAccrued <= compRemaining) {\\n comp.transfer(user, userAccrued);\\n return 0;\\n }\\n }\\n return userAccrued;\\n }\\n\\n /**\\n * @notice Calculate additional accrued COMP for a contributor since last accrual\\n * @param contributor The address to calculate contributor rewards for\\n */\\n function updateContributorRewards(address contributor) public {\\n uint compSpeed = compContributorSpeeds[contributor];\\n uint blockNumber = getBlockNumber();\\n uint deltaBlocks = sub_(blockNumber, lastContributorBlock[contributor]);\\n if (deltaBlocks > 0 && compSpeed > 0) {\\n uint newAccrued = mul_(deltaBlocks, compSpeed);\\n uint contributorAccrued = add_(compAccrued[contributor], newAccrued);\\n\\n compAccrued[contributor] = contributorAccrued;\\n lastContributorBlock[contributor] = blockNumber;\\n }\\n }\\n\\n /**\\n * @notice Claim all the comp accrued by holder in all markets\\n * @param holder The address to claim COMP for\\n */\\n function claimComp(address holder) public {\\n return claimComp(holder, allMarkets);\\n }\\n\\n /**\\n * @notice Claim all the comp accrued by holder in the specified markets\\n * @param holder The address to claim COMP for\\n * @param cTokens The list of markets to claim COMP in\\n */\\n function claimComp(address holder, CToken[] memory cTokens) public {\\n address[] memory holders = new address[](1);\\n holders[0] = holder;\\n claimComp(holders, cTokens, true, true);\\n }\\n\\n /**\\n * @notice Claim all comp accrued by the holders\\n * @param holders The addresses to claim COMP for\\n * @param cTokens The list of markets to claim COMP in\\n * @param borrowers Whether or not to claim COMP earned by borrowing\\n * @param suppliers Whether or not to claim COMP earned by supplying\\n */\\n function claimComp(address[] memory holders, CToken[] memory cTokens, bool borrowers, bool suppliers) public {\\n for (uint i = 0; i < cTokens.length; i++) {\\n CToken cToken = cTokens[i];\\n require(markets[address(cToken)].isListed, \\\"market must be listed\\\");\\n if (borrowers == true) {\\n Exp memory borrowIndex = Exp({mantissa: cToken.borrowIndex()});\\n updateCompBorrowIndex(address(cToken), borrowIndex);\\n for (uint j = 0; j < holders.length; j++) {\\n distributeBorrowerComp(address(cToken), holders[j], borrowIndex, true);\\n }\\n }\\n if (suppliers == true) {\\n updateCompSupplyIndex(address(cToken));\\n for (uint j = 0; j < holders.length; j++) {\\n distributeSupplierComp(address(cToken), holders[j], true);\\n }\\n }\\n }\\n }\\n\\n /**\\n * @notice Transfer COMP to the user\\n * @dev Note: If there is not enough COMP, we do not perform the transfer all.\\n * @param user The address of the user to transfer COMP to\\n * @param amount The amount of COMP to (possibly) transfer\\n * @return The amount of COMP which was NOT transferred to the user\\n */\\n function grantCompInternal(address user, uint amount) internal returns (uint) {\\n Comp comp = Comp(getCompAddress());\\n uint compRemaining = comp.balanceOf(address(this));\\n if (amount <= compRemaining) {\\n comp.transfer(user, amount);\\n return 0;\\n }\\n return amount;\\n }\\n\\n /*** Comp Distribution Admin ***/\\n\\n /**\\n * @notice Transfer COMP to the recipient\\n * @dev Note: If there is not enough COMP, we do not perform the transfer all.\\n * @param recipient The address of the recipient to transfer COMP to\\n * @param amount The amount of COMP to (possibly) transfer\\n */\\n function _grantComp(address recipient, uint amount) public {\\n require(adminOrInitializing(), \\\"only admin can grant comp\\\");\\n uint amountLeft = grantCompInternal(recipient, amount);\\n require(amountLeft == 0, \\\"insufficient comp for grant\\\");\\n emit CompGranted(recipient, amount);\\n }\\n\\n /**\\n * @notice Set COMP speed for a single contributor\\n * @param contributor The contributor whose COMP speed to update\\n * @param compSpeed New COMP speed for contributor\\n */\\n function _setContributorCompSpeed(address contributor, uint compSpeed) public {\\n require(adminOrInitializing(), \\\"only admin can set comp speed\\\");\\n\\n // note that COMP speed could be set to 0 to halt liquidity rewards for a contributor\\n updateContributorRewards(contributor);\\n if (compSpeed == 0) {\\n // release storage\\n delete lastContributorBlock[contributor];\\n }\\n lastContributorBlock[contributor] = getBlockNumber();\\n compContributorSpeeds[contributor] = compSpeed;\\n\\n emit ContributorCompSpeedUpdated(contributor, compSpeed);\\n }\\n\\n /**\\n * @notice Set the amount of COMP distributed per block\\n * @param compRate_ The amount of COMP wei per block to distribute\\n */\\n function _setCompRate(uint compRate_) public {\\n require(adminOrInitializing(), \\\"only admin can change comp rate\\\");\\n\\n uint oldRate = compRate;\\n compRate = compRate_;\\n emit NewCompRate(oldRate, compRate_);\\n\\n refreshCompSpeedsInternal();\\n }\\n\\n /**\\n * @notice Add markets to compMarkets, allowing them to earn COMP in the flywheel\\n * @param cTokens The addresses of the markets to add\\n */\\n function _addCompMarkets(address[] memory cTokens) public {\\n require(adminOrInitializing(), \\\"only admin can add comp market\\\");\\n\\n for (uint i = 0; i < cTokens.length; i++) {\\n _addCompMarketInternal(cTokens[i]);\\n }\\n\\n refreshCompSpeedsInternal();\\n }\\n\\n function _addCompMarketInternal(address cToken) internal {\\n Market storage market = markets[cToken];\\n require(market.isListed == true, \\\"comp market is not listed\\\");\\n require(market.isComped == false, \\\"comp market already added\\\");\\n\\n market.isComped = true;\\n emit MarketComped(CToken(cToken), true);\\n\\n if (compSupplyState[cToken].index == 0 && compSupplyState[cToken].block == 0) {\\n compSupplyState[cToken] = CompMarketState({\\n index: compInitialIndex,\\n block: safe32(getBlockNumber(), \\\"block number exceeds 32 bits\\\")\\n });\\n }\\n\\n if (compBorrowState[cToken].index == 0 && compBorrowState[cToken].block == 0) {\\n compBorrowState[cToken] = CompMarketState({\\n index: compInitialIndex,\\n block: safe32(getBlockNumber(), \\\"block number exceeds 32 bits\\\")\\n });\\n }\\n }\\n\\n /**\\n * @notice Remove a market from compMarkets, preventing it from earning COMP in the flywheel\\n * @param cToken The address of the market to drop\\n */\\n function _dropCompMarket(address cToken) public {\\n require(msg.sender == admin, \\\"only admin can drop comp market\\\");\\n\\n Market storage market = markets[cToken];\\n require(market.isComped == true, \\\"market is not a comp market\\\");\\n\\n market.isComped = false;\\n emit MarketComped(CToken(cToken), false);\\n\\n refreshCompSpeedsInternal();\\n }\\n\\n /**\\n * @notice Return all of the markets\\n * @dev The automatic getter may be used to access an individual market.\\n * @return The list of market addresses\\n */\\n function getAllMarkets() public view returns (CToken[] memory) {\\n return allMarkets;\\n }\\n\\n function getBlockNumber() public view returns (uint) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Return the address of the COMP token\\n * @return The address of COMP\\n */\\n function getCompAddress() public view returns (address) {\\n return 0xc00e94Cb662C3520282E6f5717214004A7f26888;\\n }\\n}\\n\",\"keccak256\":\"0xb304abff1f7e652d176e42f867e5ca9bf6b44025c1cc3b142e1a3a0433ee7d82\"},\"contracts/ComptrollerInterface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\ncontract ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n bool public constant isComptroller = true;\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata cTokens) external returns (uint[] memory);\\n function exitMarket(address cToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address cToken, address minter, uint mintAmount) external returns (uint);\\n function mintVerify(address cToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address cToken, address redeemer, uint redeemTokens) external returns (uint);\\n function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address cToken, address borrower, uint borrowAmount) external returns (uint);\\n function borrowVerify(address cToken, address borrower, uint borrowAmount) external;\\n\\n function repayBorrowAllowed(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount) external returns (uint);\\n function repayBorrowVerify(\\n address cToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex) external;\\n\\n function liquidateBorrowAllowed(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount) external returns (uint);\\n function liquidateBorrowVerify(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens) external;\\n\\n function seizeAllowed(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external returns (uint);\\n function seizeVerify(\\n address cTokenCollateral,\\n address cTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens) external;\\n\\n function transferAllowed(address cToken, address src, address dst, uint transferTokens) external returns (uint);\\n function transferVerify(address cToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address cTokenBorrowed,\\n address cTokenCollateral,\\n uint repayAmount) external view returns (uint, uint);\\n}\\n\",\"keccak256\":\"0xede7670d2dd7b25d0187aecd2c28b7b5ca7d7c1bdac144fbedecf5d4bdd92a6b\"},\"contracts/ComptrollerStorage.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.sol\\\";\\nimport \\\"./PriceOracle.sol\\\";\\n\\ncontract UnitrollerAdminStorage {\\n /**\\n * @notice Administrator for this contract\\n */\\n address public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address public pendingAdmin;\\n\\n /**\\n * @notice Active brains of Unitroller\\n */\\n address public comptrollerImplementation;\\n\\n /**\\n * @notice Pending brains of Unitroller\\n */\\n address public pendingComptrollerImplementation;\\n}\\n\\ncontract ComptrollerV1Storage is UnitrollerAdminStorage {\\n\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n PriceOracle public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives\\n */\\n uint public liquidationIncentiveMantissa;\\n\\n /**\\n * @notice Max number of assets a single account can participate in (borrow or use as collateral)\\n */\\n uint public maxAssets;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\\n */\\n mapping(address => CToken[]) public accountAssets;\\n\\n}\\n\\ncontract ComptrollerV2Storage is ComptrollerV1Storage {\\n struct Market {\\n /// @notice Whether or not this market is listed\\n bool isListed;\\n\\n /**\\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\\n * For instance, 0.9 to allow borrowing 90% of collateral value.\\n * Must be between 0 and 1, and stored as a mantissa.\\n */\\n uint collateralFactorMantissa;\\n\\n /// @notice Per-market mapping of \\\"accounts in this asset\\\"\\n mapping(address => bool) accountMembership;\\n\\n /// @notice Whether or not this market receives COMP\\n bool isComped;\\n }\\n\\n /**\\n * @notice Official mapping of cTokens -> Market metadata\\n * @dev Used e.g. to determine if a market is supported\\n */\\n mapping(address => Market) public markets;\\n\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n * Actions which allow users to remove their own assets cannot be paused.\\n * Liquidation / seizing / transfer can only be paused globally, not by market.\\n */\\n address public pauseGuardian;\\n bool public _mintGuardianPaused;\\n bool public _borrowGuardianPaused;\\n bool public transferGuardianPaused;\\n bool public seizeGuardianPaused;\\n mapping(address => bool) public mintGuardianPaused;\\n mapping(address => bool) public borrowGuardianPaused;\\n}\\n\\ncontract ComptrollerV3Storage is ComptrollerV2Storage {\\n struct CompMarketState {\\n /// @notice The market's last updated compBorrowIndex or compSupplyIndex\\n uint224 index;\\n\\n /// @notice The block number the index was last updated at\\n uint32 block;\\n }\\n\\n /// @notice A list of all markets\\n CToken[] public allMarkets;\\n\\n /// @notice The rate at which the flywheel distributes COMP, per block\\n uint public compRate;\\n\\n /// @notice The portion of compRate that each market currently receives\\n mapping(address => uint) public compSpeeds;\\n\\n /// @notice The COMP market supply state for each market\\n mapping(address => CompMarketState) public compSupplyState;\\n\\n /// @notice The COMP market borrow state for each market\\n mapping(address => CompMarketState) public compBorrowState;\\n\\n /// @notice The COMP borrow index for each market for each supplier as of the last time they accrued COMP\\n mapping(address => mapping(address => uint)) public compSupplierIndex;\\n\\n /// @notice The COMP borrow index for each market for each borrower as of the last time they accrued COMP\\n mapping(address => mapping(address => uint)) public compBorrowerIndex;\\n\\n /// @notice The COMP accrued but not yet transferred to each user\\n mapping(address => uint) public compAccrued;\\n}\\n\\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\\n // @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\\n address public borrowCapGuardian;\\n\\n // @notice Borrow caps enforced by borrowAllowed for each cToken address. Defaults to zero which corresponds to unlimited borrowing.\\n mapping(address => uint) public borrowCaps;\\n}\\n\\ncontract ComptrollerV5Storage is ComptrollerV4Storage {\\n /// @notice The portion of COMP that each contributor receives per block\\n mapping(address => uint) public compContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's COMP rewards have been allocated\\n mapping(address => uint) public lastContributorBlock;\\n}\\n\",\"keccak256\":\"0x5db970485549f493618b5e36bfd4d799d4f8701a136bf71ed6e0117e1ed8c254\"},\"contracts/EIP20Interface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title ERC 20 Token Standard Interface\\n * https://eips.ethereum.org/EIPS/eip-20\\n */\\ninterface EIP20Interface {\\n function name() external view returns (string memory);\\n function symbol() external view returns (string memory);\\n function decimals() external view returns (uint8);\\n\\n /**\\n * @notice Get the total number of tokens in circulation\\n * @return The supply of tokens\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @notice Gets the balance of the specified address\\n * @param owner The address from which the balance will be retrieved\\n * @return The balance\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transfer(address dst, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferFrom(address src, address dst, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (-1 means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (-1 means infinite)\\n */\\n function allowance(address owner, address spender) external view returns (uint256 remaining);\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n}\\n\",\"keccak256\":\"0xfd8ed2eac6d0b4d9ee6b32628ba68bae17544b66f190a5f7ce0c6ad024579dc8\"},\"contracts/EIP20NonStandardInterface.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title EIP20NonStandardInterface\\n * @dev Version of ERC20 with no return values for `transfer` and `transferFrom`\\n * See https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\\n */\\ninterface EIP20NonStandardInterface {\\n\\n /**\\n * @notice Get the total number of tokens in circulation\\n * @return The supply of tokens\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @notice Gets the balance of the specified address\\n * @param owner The address from which the balance will be retrieved\\n * @return The balance\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n ///\\n /// !!!!!!!!!!!!!!\\n /// !!! NOTICE !!! `transfer` does not return a value, in violation of the ERC-20 specification\\n /// !!!!!!!!!!!!!!\\n ///\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n */\\n function transfer(address dst, uint256 amount) external;\\n\\n ///\\n /// !!!!!!!!!!!!!!\\n /// !!! NOTICE !!! `transferFrom` does not return a value, in violation of the ERC-20 specification\\n /// !!!!!!!!!!!!!!\\n ///\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n */\\n function transferFrom(address src, address dst, uint256 amount) external;\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 amount) external returns (bool success);\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent\\n */\\n function allowance(address owner, address spender) external view returns (uint256 remaining);\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n}\\n\",\"keccak256\":\"0x9719f12e4b80b51147ac195553a198cf8b0c516e7e4d04fc324a23ed15cbafb2\"},\"contracts/ErrorReporter.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\ncontract ComptrollerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\",\"keccak256\":\"0x5179afb1071c0fd555e5c1f1d2565f72dbe1740cc3dd02f6e52037f150afc5c9\"},\"contracts/Exponential.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CarefulMath.sol\\\";\\nimport \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @dev Legacy contract for compatibility reasons with existing contracts that still use MathError\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: rational}));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({mantissa: result}));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({mantissa: result}));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: scaledMantissa}));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) pure internal returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n return (MathError.NO_ERROR, Exp({mantissa: descaledMantissa}));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) pure internal returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) pure internal returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({mantissa: 0}));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({mantissa: 0}));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({mantissa: product}));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) pure internal returns (MathError, Exp memory) {\\n return mulExp(Exp({mantissa: a}), Exp({mantissa: b}));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) pure internal returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6ff054d65a0289dbb43c9f437d6909f9cf1207c9b8f984b3cb8e97a9de76a434\"},\"contracts/ExponentialNoError.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\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 Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) pure internal returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) pure internal returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) pure internal returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) pure internal returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) pure internal returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) pure internal returns (uint224) {\\n require(n < 2**224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) pure internal returns (uint32) {\\n require(n < 2**32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: add_(a.mantissa, b.mantissa)});\\n }\\n\\n function add_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: add_(a.mantissa, b.mantissa)});\\n }\\n\\n function add_(uint a, uint b) pure internal returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: sub_(a.mantissa, b.mantissa)});\\n }\\n\\n function sub_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: sub_(a.mantissa, b.mantissa)});\\n }\\n\\n function sub_(uint a, uint b) pure internal returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\\n return Exp({mantissa: mul_(a.mantissa, b.mantissa) / expScale});\\n }\\n\\n function mul_(Exp memory a, uint b) pure internal returns (Exp memory) {\\n return Exp({mantissa: mul_(a.mantissa, b)});\\n }\\n\\n function mul_(uint a, Exp memory b) pure internal returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: mul_(a.mantissa, b.mantissa) / doubleScale});\\n }\\n\\n function mul_(Double memory a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: mul_(a.mantissa, b)});\\n }\\n\\n function mul_(uint a, Double memory b) pure internal returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) pure internal returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) pure internal 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) pure internal returns (Exp memory) {\\n return Exp({mantissa: div_(mul_(a.mantissa, expScale), b.mantissa)});\\n }\\n\\n function div_(Exp memory a, uint b) pure internal returns (Exp memory) {\\n return Exp({mantissa: div_(a.mantissa, b)});\\n }\\n\\n function div_(uint a, Exp memory b) pure internal returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa)});\\n }\\n\\n function div_(Double memory a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(a.mantissa, b)});\\n }\\n\\n function div_(uint a, Double memory b) pure internal returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) pure internal returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) pure internal returns (Double memory) {\\n return Double({mantissa: div_(mul_(a, doubleScale), b)});\\n }\\n}\\n\",\"keccak256\":\"0x7cb184b7cee71a5e707053dfba7eebbd46f11974004028100510ccce19b6694d\"},\"contracts/Governance/Comp.sol\":{\"content\":\"pragma solidity ^0.5.16;\\npragma experimental ABIEncoderV2;\\n\\ncontract Comp {\\n /// @notice EIP-20 token name for this token\\n string public constant name = \\\"Compound\\\";\\n\\n /// @notice EIP-20 token symbol for this token\\n string public constant symbol = \\\"COMP\\\";\\n\\n /// @notice EIP-20 token decimals for this token\\n uint8 public constant decimals = 18;\\n\\n /// @notice Total number of tokens in circulation\\n uint public constant totalSupply = 10000000e18; // 10 million Comp\\n\\n /// @notice Allowance amounts on behalf of others\\n mapping (address => mapping (address => uint96)) internal allowances;\\n\\n /// @notice Official record of token balances for each account\\n mapping (address => uint96) internal balances;\\n\\n /// @notice A record of each accounts delegate\\n mapping (address => address) public delegates;\\n\\n /// @notice A checkpoint for marking number of votes from a given block\\n struct Checkpoint {\\n uint32 fromBlock;\\n uint96 votes;\\n }\\n\\n /// @notice A record of votes checkpoints for each account, by index\\n mapping (address => mapping (uint32 => Checkpoint)) public checkpoints;\\n\\n /// @notice The number of checkpoints for each account\\n mapping (address => uint32) public numCheckpoints;\\n\\n /// @notice The EIP-712 typehash for the contract's domain\\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\\\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\\\");\\n\\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\\\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\\\");\\n\\n /// @notice A record of states for signing / validating signatures\\n mapping (address => uint) public nonces;\\n\\n /// @notice An event thats emitted when an account changes its delegate\\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\\n\\n /// @notice An event thats emitted when a delegate account's vote balance changes\\n event DelegateVotesChanged(address indexed delegate, uint previousBalance, uint newBalance);\\n\\n /// @notice The standard EIP-20 transfer event\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n\\n /// @notice The standard EIP-20 approval event\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n\\n /**\\n * @notice Construct a new Comp token\\n * @param account The initial account to grant all the tokens\\n */\\n constructor(address account) public {\\n balances[account] = uint96(totalSupply);\\n emit Transfer(address(0), account, totalSupply);\\n }\\n\\n /**\\n * @notice Get the number of tokens `spender` is approved to spend on behalf of `account`\\n * @param account The address of the account holding the funds\\n * @param spender The address of the account spending the funds\\n * @return The number of tokens approved\\n */\\n function allowance(address account, address spender) external view returns (uint) {\\n return allowances[account][spender];\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param rawAmount The number of tokens that are approved (2^256-1 means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint rawAmount) external returns (bool) {\\n uint96 amount;\\n if (rawAmount == uint(-1)) {\\n amount = uint96(-1);\\n } else {\\n amount = safe96(rawAmount, \\\"Comp::approve: amount exceeds 96 bits\\\");\\n }\\n\\n allowances[msg.sender][spender] = amount;\\n\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the number of tokens held by the `account`\\n * @param account The address of the account to get the balance of\\n * @return The number of tokens held\\n */\\n function balanceOf(address account) external view returns (uint) {\\n return balances[account];\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param rawAmount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transfer(address dst, uint rawAmount) external returns (bool) {\\n uint96 amount = safe96(rawAmount, \\\"Comp::transfer: amount exceeds 96 bits\\\");\\n _transferTokens(msg.sender, dst, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param rawAmount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferFrom(address src, address dst, uint rawAmount) external returns (bool) {\\n address spender = msg.sender;\\n uint96 spenderAllowance = allowances[src][spender];\\n uint96 amount = safe96(rawAmount, \\\"Comp::approve: amount exceeds 96 bits\\\");\\n\\n if (spender != src && spenderAllowance != uint96(-1)) {\\n uint96 newAllowance = sub96(spenderAllowance, amount, \\\"Comp::transferFrom: transfer amount exceeds spender allowance\\\");\\n allowances[src][spender] = newAllowance;\\n\\n emit Approval(src, spender, newAllowance);\\n }\\n\\n _transferTokens(src, dst, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Delegate votes from `msg.sender` to `delegatee`\\n * @param delegatee The address to delegate votes to\\n */\\n function delegate(address delegatee) public {\\n return _delegate(msg.sender, delegatee);\\n }\\n\\n /**\\n * @notice Delegates votes from signatory to `delegatee`\\n * @param delegatee The address to delegate votes to\\n * @param nonce The contract state required to match the signature\\n * @param expiry The time at which to expire the signature\\n * @param v The recovery byte of the signature\\n * @param r Half of the ECDSA signature pair\\n * @param s Half of the ECDSA signature pair\\n */\\n function delegateBySig(address delegatee, uint nonce, uint expiry, uint8 v, bytes32 r, bytes32 s) public {\\n bytes32 domainSeparator = keccak256(abi.encode(DOMAIN_TYPEHASH, keccak256(bytes(name)), getChainId(), address(this)));\\n bytes32 structHash = keccak256(abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry));\\n bytes32 digest = keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash));\\n address signatory = ecrecover(digest, v, r, s);\\n require(signatory != address(0), \\\"Comp::delegateBySig: invalid signature\\\");\\n require(nonce == nonces[signatory]++, \\\"Comp::delegateBySig: invalid nonce\\\");\\n require(now <= expiry, \\\"Comp::delegateBySig: signature expired\\\");\\n return _delegate(signatory, delegatee);\\n }\\n\\n /**\\n * @notice Gets the current votes balance for `account`\\n * @param account The address to get votes balance\\n * @return The number of current votes for `account`\\n */\\n function getCurrentVotes(address account) external view returns (uint96) {\\n uint32 nCheckpoints = numCheckpoints[account];\\n return nCheckpoints > 0 ? checkpoints[account][nCheckpoints - 1].votes : 0;\\n }\\n\\n /**\\n * @notice Determine the prior number of votes for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param account The address of the account to check\\n * @param blockNumber The block number to get the vote balance at\\n * @return The number of votes the account had as of the given block\\n */\\n function getPriorVotes(address account, uint blockNumber) public view returns (uint96) {\\n require(blockNumber < block.number, \\\"Comp::getPriorVotes: not yet determined\\\");\\n\\n uint32 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (checkpoints[account][nCheckpoints - 1].fromBlock <= blockNumber) {\\n return checkpoints[account][nCheckpoints - 1].votes;\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[account][0].fromBlock > blockNumber) {\\n return 0;\\n }\\n\\n uint32 lower = 0;\\n uint32 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[account][center];\\n if (cp.fromBlock == blockNumber) {\\n return cp.votes;\\n } else if (cp.fromBlock < blockNumber) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return checkpoints[account][lower].votes;\\n }\\n\\n function _delegate(address delegator, address delegatee) internal {\\n address currentDelegate = delegates[delegator];\\n uint96 delegatorBalance = balances[delegator];\\n delegates[delegator] = delegatee;\\n\\n emit DelegateChanged(delegator, currentDelegate, delegatee);\\n\\n _moveDelegates(currentDelegate, delegatee, delegatorBalance);\\n }\\n\\n function _transferTokens(address src, address dst, uint96 amount) internal {\\n require(src != address(0), \\\"Comp::_transferTokens: cannot transfer from the zero address\\\");\\n require(dst != address(0), \\\"Comp::_transferTokens: cannot transfer to the zero address\\\");\\n\\n balances[src] = sub96(balances[src], amount, \\\"Comp::_transferTokens: transfer amount exceeds balance\\\");\\n balances[dst] = add96(balances[dst], amount, \\\"Comp::_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 && amount > 0) {\\n if (srcRep != address(0)) {\\n uint32 srcRepNum = numCheckpoints[srcRep];\\n uint96 srcRepOld = srcRepNum > 0 ? checkpoints[srcRep][srcRepNum - 1].votes : 0;\\n uint96 srcRepNew = sub96(srcRepOld, amount, \\\"Comp::_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 > 0 ? checkpoints[dstRep][dstRepNum - 1].votes : 0;\\n uint96 dstRepNew = add96(dstRepOld, amount, \\\"Comp::_moveVotes: vote amount overflows\\\");\\n _writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew);\\n }\\n }\\n }\\n\\n function _writeCheckpoint(address delegatee, uint32 nCheckpoints, uint96 oldVotes, uint96 newVotes) internal {\\n uint32 blockNumber = safe32(block.number, \\\"Comp::_writeCheckpoint: block number exceeds 32 bits\\\");\\n\\n if (nCheckpoints > 0 && checkpoints[delegatee][nCheckpoints - 1].fromBlock == blockNumber) {\\n checkpoints[delegatee][nCheckpoints - 1].votes = newVotes;\\n } else {\\n checkpoints[delegatee][nCheckpoints] = Checkpoint(blockNumber, newVotes);\\n numCheckpoints[delegatee] = nCheckpoints + 1;\\n }\\n\\n emit DelegateVotesChanged(delegatee, oldVotes, newVotes);\\n }\\n\\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\\n require(n < 2**32, errorMessage);\\n return uint32(n);\\n }\\n\\n function safe96(uint n, string memory errorMessage) internal pure returns (uint96) {\\n require(n < 2**96, errorMessage);\\n return uint96(n);\\n }\\n\\n function add96(uint96 a, uint96 b, string memory errorMessage) internal pure returns (uint96) {\\n uint96 c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub96(uint96 a, uint96 b, string memory errorMessage) internal pure returns (uint96) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function getChainId() internal pure returns (uint) {\\n uint256 chainId;\\n assembly { chainId := chainid() }\\n return chainId;\\n }\\n}\\n\",\"keccak256\":\"0x539f7158013dd91efd3ad42dc6a56e0f7aebdca06063d40ce7b6e9a981b726a3\"},\"contracts/InterestRateModel.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @title Compound's InterestRateModel Interface\\n * @author Compound\\n */\\ncontract InterestRateModel {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint cash, uint borrows, uint reserves) external view returns (uint);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) external view returns (uint);\\n\\n}\\n\",\"keccak256\":\"0x929282d73c79e6d700ebe79f9fafc1e414b3848acff5a56d6740afd1dc908678\"},\"contracts/PriceOracle.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.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 cToken asset\\n * @param cToken The cToken to get the underlying price of\\n * @return The underlying asset price mantissa (scaled by 1e18).\\n * Zero means the price is unavailable.\\n */\\n function getUnderlyingPrice(CToken cToken) external view returns (uint);\\n}\\n\",\"keccak256\":\"0xe79ebc23bba508eb2479e7b3340abf566da1ab62131f106aee1aac3dc53816ef\"},\"contracts/Unitroller.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./ErrorReporter.sol\\\";\\nimport \\\"./ComptrollerStorage.sol\\\";\\n/**\\n * @title ComptrollerCore\\n * @dev Storage for the comptroller is at this address, while execution is delegated to the `comptrollerImplementation`.\\n * CTokens should reference this contract as their comptroller.\\n */\\ncontract Unitroller is UnitrollerAdminStorage, ComptrollerErrorReporter {\\n\\n /**\\n * @notice Emitted when pendingComptrollerImplementation is changed\\n */\\n event NewPendingImplementation(address oldPendingImplementation, address newPendingImplementation);\\n\\n /**\\n * @notice Emitted when pendingComptrollerImplementation is accepted, which means comptroller implementation is updated\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Emitted when pendingAdmin is accepted, which means admin is updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n constructor() public {\\n // Set admin to caller\\n admin = msg.sender;\\n }\\n\\n /*** Admin Functions ***/\\n function _setPendingImplementation(address newPendingImplementation) public returns (uint) {\\n\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_IMPLEMENTATION_OWNER_CHECK);\\n }\\n\\n address oldPendingImplementation = pendingComptrollerImplementation;\\n\\n pendingComptrollerImplementation = newPendingImplementation;\\n\\n emit NewPendingImplementation(oldPendingImplementation, pendingComptrollerImplementation);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts new implementation of comptroller. msg.sender must be pendingImplementation\\n * @dev Admin function for new implementation to accept it's role as implementation\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptImplementation() public returns (uint) {\\n // Check caller is pendingImplementation and pendingImplementation \\u2260 address(0)\\n if (msg.sender != pendingComptrollerImplementation || pendingComptrollerImplementation == address(0)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldImplementation = comptrollerImplementation;\\n address oldPendingImplementation = pendingComptrollerImplementation;\\n\\n comptrollerImplementation = pendingComptrollerImplementation;\\n\\n pendingComptrollerImplementation = address(0);\\n\\n emit NewImplementation(oldImplementation, comptrollerImplementation);\\n emit NewPendingImplementation(oldPendingImplementation, pendingComptrollerImplementation);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPendingAdmin(address newPendingAdmin) public returns (uint) {\\n // Check caller = admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\\n }\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptAdmin() public returns (uint) {\\n // Check caller is pendingAdmin and pendingAdmin \\u2260 address(0)\\n if (msg.sender != pendingAdmin || msg.sender == address(0)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = address(0);\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return 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 () payable external {\\n // delegate all other functions to current implementation\\n (bool success, ) = comptrollerImplementation.delegatecall(msg.data);\\n\\n assembly {\\n let free_mem_ptr := mload(0x40)\\n returndatacopy(free_mem_ptr, 0, returndatasize)\\n\\n switch success\\n case 0 { revert(free_mem_ptr, returndatasize) }\\n default { return(free_mem_ptr, returndatasize) }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x51f81451eab9d5c4849507e724f2b2c53e41f54e5359fdbeae89432a727c16df\"},\"tests/Contracts/ComptrollerScenarioG6.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"../../contracts/ComptrollerG6.sol\\\";\\n\\ncontract ComptrollerScenarioG6 is ComptrollerG6 {\\n uint public blockNumber;\\n address public compAddress;\\n\\n constructor() ComptrollerG6() public {}\\n\\n function fastForward(uint blocks) public returns (uint) {\\n blockNumber += blocks;\\n return blockNumber;\\n }\\n\\n function setCompAddress(address compAddress_) public {\\n compAddress = compAddress_;\\n }\\n\\n function getCompAddress() public view returns (address) {\\n return compAddress;\\n }\\n\\n function setBlockNumber(uint number) public {\\n blockNumber = number;\\n }\\n\\n function getBlockNumber() public view returns (uint) {\\n return blockNumber;\\n }\\n\\n function membershipLength(CToken cToken) public view returns (uint) {\\n return accountAssets[address(cToken)].length;\\n }\\n\\n function unlist(CToken cToken) public {\\n markets[address(cToken)].isListed = false;\\n }\\n\\n function setCompSpeed(address cToken, uint compSpeed) public {\\n compSpeeds[cToken] = compSpeed;\\n }\\n}\\n\",\"keccak256\":\"0xa70e8985e88a43b973c618b2ea42cedf822142ea1064b9733a944dd0098c4ef4\"}},\"version\":1}" + } + }, + "version": "0.5.16+commit.9c3226ce.Linux.g++" +} diff --git a/tests/Matchers.js b/tests/Matchers.js index 44c38a5f2..cf950ad40 100644 --- a/tests/Matchers.js +++ b/tests/Matchers.js @@ -2,6 +2,7 @@ const { last } = require('./Utils/JS'); const { address, etherUnsigned } = require('./Utils/Ethereum'); const { default: diff } = require('jest-diff'); const { ComptrollerErr, TokenErr, IRErr, MathErr } = require('./Errors'); +const ethers = require('ethers') function opts(comment) { return { @@ -269,6 +270,29 @@ function revert(actual, msg) { } } +function revertWithCustomError(actual, errorName, errorArgs, reporter) { + const correctMessage = !!actual['message'] && actual.message === `VM Exception while processing transaction: revert` + const err = reporter.CustomErrors[errorName] + let matchingError = false + if (correctMessage && !!err) { + const c = new ethers.utils.Interface([err]) + const expectedReturn = c.functions[errorName].encode(errorArgs) + matchingError = Object.values(actual.results).findIndex(v => v.error === 'revert' && v.return === expectedReturn) >= 0 + } + return { + pass: correctMessage && matchingError, + message: () => { + if (correctMessage && !!err) { + return `did not find Custom Error: ${errorName}(${errorArgs.join(',')})` + } else if (!err) { + return `Custom Error not found` + } else { + return `expected revert, but transaction succeeded: ${JSON.stringify(actual)}` + } + } + } +} + function toBeWithinDelta(received, expected, delta) { const pass = Math.abs(Number(received) - Number(expected)) < delta; if (pass) { @@ -354,6 +378,10 @@ expect.extend({ return revert.call(this, actual, msg); }, + toRevertWithCustomError(actual, errorName, errorArgs=[], reporter=TokenErr) { + return revertWithCustomError.call(this, actual, errorName, errorArgs, reporter) + }, + toRevertWithError(trx, expectedErrorName, reason='revert', reporter=TokenErr) { return revert.call(this, trx, `${reason} (${reporter.Error[expectedErrorName].padStart(2, '0')})`); }, diff --git a/tests/Models/InterestRateModelTest.js b/tests/Models/InterestRateModelTest.js index 2568cc6ce..787ad85a8 100644 --- a/tests/Models/InterestRateModelTest.js +++ b/tests/Models/InterestRateModelTest.js @@ -109,21 +109,21 @@ describe('InterestRateModel', () => { // Only need to do these for the WhitePaper it('handles overflowed cash + borrows', async () => { - await expect(getBorrowRate(model, UInt256Max(), UInt256Max(), 0)).rejects.toRevert("revert SafeMath: addition overflow"); + await expect(getBorrowRate(model, UInt256Max(), UInt256Max(), 0)).rejects.toRevert(); }); it('handles failing to get exp of borrows / cash + borrows', async () => { - await expect(getBorrowRate(model, 0, UInt256Max(), 0)).rejects.toRevert("revert SafeMath: multiplication overflow"); + await expect(getBorrowRate(model, 0, UInt256Max(), 0)).rejects.toRevert(); }); it('handles overflow utilization rate times slope', async () => { const badModel = await makeInterestRateModel({ kind, baseRate: 0, multiplier: -1, jump: -1 }); - await expect(getBorrowRate(badModel, 1, 1, 0)).rejects.toRevert("revert SafeMath: multiplication overflow"); + await expect(getBorrowRate(badModel, 1, 1, 0)).rejects.toRevert(); }); it('handles overflow utilization rate times slope + base', async () => { const badModel = await makeInterestRateModel({ kind, baseRate: -1, multiplier: 1e48, jump: 1e48 }); - await expect(getBorrowRate(badModel, 0, 1, 0)).rejects.toRevert("revert SafeMath: multiplication overflow"); + await expect(getBorrowRate(badModel, 0, 1, 0)).rejects.toRevert(); }); } }); diff --git a/tests/Tokens/accrueInterestTest.js b/tests/Tokens/accrueInterestTest.js index 7a96664b2..f2be3b0b4 100644 --- a/tests/Tokens/accrueInterestTest.js +++ b/tests/Tokens/accrueInterestTest.js @@ -52,31 +52,31 @@ describe('CToken', () => { it('fails if simple interest factor calculation fails', async () => { await pretendBlock(cToken, blockNumber, 5e70); - expect(await send(cToken, 'accrueInterest')).toHaveTokenFailure('MATH_ERROR', 'ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED'); + await expect(send(cToken, 'accrueInterest')).rejects.toRevert(); }); it('fails if new borrow index calculation fails', async () => { await pretendBlock(cToken, blockNumber, 5e60); - expect(await send(cToken, 'accrueInterest')).toHaveTokenFailure('MATH_ERROR', 'ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED'); + await expect(send(cToken, 'accrueInterest')).rejects.toRevert(); }); it('fails if new borrow interest index calculation fails', async () => { await pretendBlock(cToken) await send(cToken, 'harnessSetBorrowIndex', [UInt256Max()]); - expect(await send(cToken, 'accrueInterest')).toHaveTokenFailure('MATH_ERROR', 'ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED'); + await expect(send(cToken, 'accrueInterest')).rejects.toRevert(); }); it('fails if interest accumulated calculation fails', async () => { await send(cToken, 'harnessExchangeRateDetails', [0, UInt256Max(), 0]); await pretendBlock(cToken) - expect(await send(cToken, 'accrueInterest')).toHaveTokenFailure('MATH_ERROR', 'ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED'); + await expect(send(cToken, 'accrueInterest')).rejects.toRevert(); }); it('fails if new total borrows calculation fails', async () => { await setBorrowRate(cToken, 1e-18); await pretendBlock(cToken) await send(cToken, 'harnessExchangeRateDetails', [0, UInt256Max(), 0]); - expect(await send(cToken, 'accrueInterest')).toHaveTokenFailure('MATH_ERROR', 'ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED'); + await expect(send(cToken, 'accrueInterest')).rejects.toRevert(); }); it('fails if interest accumulated for reserves calculation fails', async () => { @@ -84,7 +84,7 @@ describe('CToken', () => { await send(cToken, 'harnessExchangeRateDetails', [0, etherUnsigned(1e30), UInt256Max()]); await send(cToken, 'harnessSetReserveFactorFresh', [etherUnsigned(1e10)]); await pretendBlock(cToken, blockNumber, 5e20) - expect(await send(cToken, 'accrueInterest')).toHaveTokenFailure('MATH_ERROR', 'ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED'); + await expect(send(cToken, 'accrueInterest')).rejects.toRevert(); }); it('fails if new total reserves calculation fails', async () => { @@ -92,7 +92,7 @@ describe('CToken', () => { await send(cToken, 'harnessExchangeRateDetails', [0, etherUnsigned(1e56), UInt256Max()]); await send(cToken, 'harnessSetReserveFactorFresh', [etherUnsigned(1e17)]); await pretendBlock(cToken) - expect(await send(cToken, 'accrueInterest')).toHaveTokenFailure('MATH_ERROR', 'ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED'); + await expect(send(cToken, 'accrueInterest')).rejects.toRevert(); }); it('succeeds and saves updated values in storage on success', async () => { diff --git a/tests/Tokens/adminTest.js b/tests/Tokens/adminTest.js index 8e57d2f02..88d8dfe16 100644 --- a/tests/Tokens/adminTest.js +++ b/tests/Tokens/adminTest.js @@ -23,11 +23,10 @@ describe('admin / _setPendingAdmin / _acceptAdmin', () => { describe('_setPendingAdmin()', () => { it('should only be callable by admin', async () => { - expect( - await send(cToken, '_setPendingAdmin', [accounts[0]], {from: accounts[0]}) - ).toHaveTokenFailure( - 'UNAUTHORIZED', - 'SET_PENDING_ADMIN_OWNER_CHECK' + await expect( + send(cToken, '_setPendingAdmin', [accounts[0]], {from: accounts[0]}) + ).rejects.toRevertWithCustomError( + 'SetPendingAdminOwnerCheck' ); // Check admin stays the same @@ -63,11 +62,10 @@ describe('admin / _setPendingAdmin / _acceptAdmin', () => { describe('_acceptAdmin()', () => { it('should fail when pending admin is zero', async () => { - expect( - await send(cToken, '_acceptAdmin') - ).toHaveTokenFailure( - 'UNAUTHORIZED', - 'ACCEPT_ADMIN_PENDING_ADMIN_CHECK' + await expect( + send(cToken, '_acceptAdmin') + ).rejects.toRevertWithCustomError( + 'AcceptAdminPendingAdminCheck' ); // Check admin stays the same @@ -77,11 +75,10 @@ describe('admin / _setPendingAdmin / _acceptAdmin', () => { it('should fail when called by another account (e.g. root)', async () => { expect(await send(cToken, '_setPendingAdmin', [accounts[0]])).toSucceed(); - expect( - await send(cToken, '_acceptAdmin') - ).toHaveTokenFailure( - 'UNAUTHORIZED', - 'ACCEPT_ADMIN_PENDING_ADMIN_CHECK' + await expect( + send(cToken, '_acceptAdmin') + ).rejects.toRevertWithCustomError( + 'AcceptAdminPendingAdminCheck' ); // Check admin stays the same diff --git a/tests/Tokens/borrowAndRepayCEtherTest.js b/tests/Tokens/borrowAndRepayCEtherTest.js index 2f546503e..63ab2e5ce 100644 --- a/tests/Tokens/borrowAndRepayCEtherTest.js +++ b/tests/Tokens/borrowAndRepayCEtherTest.js @@ -77,7 +77,7 @@ describe('CEther', function () { it("fails if comptroller tells it to", async () => { await send(cToken.comptroller, 'setBorrowAllowed', [false]); - expect(await borrowFresh(cToken, borrower, borrowAmount)).toHaveTrollReject('BORROW_COMPTROLLER_REJECTION'); + await expect(borrowFresh(cToken, borrower, borrowAmount)).rejects.toRevertWithCustomError('BorrowComptrollerRejection', [11]); }); it("proceeds if comptroller tells it to", async () => { @@ -86,7 +86,7 @@ describe('CEther', function () { it("fails if market not fresh", async () => { await fastForward(cToken); - expect(await borrowFresh(cToken, borrower, borrowAmount)).toHaveTokenFailure('MARKET_NOT_FRESH', 'BORROW_FRESHNESS_CHECK'); + await expect(borrowFresh(cToken, borrower, borrowAmount)).rejects.toRevertWithCustomError('BorrowFreshnessCheck'); }); it("continues if fresh", async () => { @@ -95,22 +95,22 @@ describe('CEther', function () { }); it("fails if protocol has less than borrowAmount of underlying", async () => { - expect(await borrowFresh(cToken, borrower, borrowAmount.plus(1))).toHaveTokenFailure('TOKEN_INSUFFICIENT_CASH', 'BORROW_CASH_NOT_AVAILABLE'); + await expect(borrowFresh(cToken, borrower, borrowAmount.plus(1))).rejects.toRevertWithCustomError('BorrowCashNotAvailable'); }); it("fails if borrowBalanceStored fails (due to non-zero stored principal with zero account index)", async () => { await pretendBorrow(cToken, borrower, 0, 3e18, 5e18); - expect(await borrowFresh(cToken, borrower, borrowAmount)).toHaveTokenFailure('MATH_ERROR', 'BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED'); + await expect(borrowFresh(cToken, borrower, borrowAmount)).rejects.toRevert(); }); it("fails if calculating account new total borrow balance overflows", async () => { await pretendBorrow(cToken, borrower, 1e-18, 1e-18, UInt256Max()); - expect(await borrowFresh(cToken, borrower, borrowAmount)).toHaveTokenFailure('MATH_ERROR', 'BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED'); + await expect(borrowFresh(cToken, borrower, borrowAmount)).rejects.toRevert(); }); it("fails if calculation of new total borrow balance overflows", async () => { await send(cToken, 'harnessSetTotalBorrows', [UInt256Max()]); - expect(await borrowFresh(cToken, borrower, borrowAmount)).toHaveTokenFailure('MATH_ERROR', 'BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED'); + await expect(borrowFresh(cToken, borrower, borrowAmount)).rejects.toRevert(); }); it("reverts if transfer out fails", async () => { @@ -163,8 +163,8 @@ describe('CEther', function () { await expect(borrow(cToken, borrower, borrowAmount)).rejects.toRevert("revert INTEREST_RATE_MODEL_ERROR"); }); - it("returns error from borrowFresh without emitting any extra logs", async () => { - expect(await borrow(cToken, borrower, borrowAmount.plus(1))).toHaveTokenFailure('TOKEN_INSUFFICIENT_CASH', 'BORROW_CASH_NOT_AVAILABLE'); + it("refverts in borrowFresh without emitting any extra logs", async () => { + await expect(borrow(cToken, borrower, borrowAmount.plus(1))).rejects.toRevert(); }); it("returns success from borrowFresh and transfers the correct amount", async () => { @@ -195,22 +195,22 @@ describe('CEther', function () { it("fails if repay is not allowed", async () => { await send(cToken.comptroller, 'setRepayBorrowAllowed', [false]); - expect(await repayBorrowFresh(cToken, payer, borrower, repayAmount)).toHaveTrollReject('REPAY_BORROW_COMPTROLLER_REJECTION', 'MATH_ERROR'); + await expect(repayBorrowFresh(cToken, payer, borrower, repayAmount)).rejects.toRevertWithCustomError('RepayBorrowComptrollerRejection', [11]); }); it("fails if block number ≠ current block number", async () => { await fastForward(cToken); - expect(await repayBorrowFresh(cToken, payer, borrower, repayAmount)).toHaveTokenFailure('MARKET_NOT_FRESH', 'REPAY_BORROW_FRESHNESS_CHECK'); + await expect(repayBorrowFresh(cToken, payer, borrower, repayAmount)).rejects.toRevertWithCustomError('RepayBorrowFreshnessCheck'); }); it("returns an error if calculating account new account borrow balance fails", async () => { await pretendBorrow(cToken, borrower, 1, 1, 1); - await expect(repayBorrowFresh(cToken, payer, borrower, repayAmount)).rejects.toRevert('revert REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED'); + await expect(repayBorrowFresh(cToken, payer, borrower, repayAmount)).rejects.toRevert(); }); it("returns an error if calculation of new total borrow balance fails", async () => { await send(cToken, 'harnessSetTotalBorrows', [1]); - await expect(repayBorrowFresh(cToken, payer, borrower, repayAmount)).rejects.toRevert('revert REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED'); + await expect(repayBorrowFresh(cToken, payer, borrower, repayAmount)).rejects.toRevert(); }); it("reverts if checkTransferIn fails", async () => { @@ -280,7 +280,7 @@ describe('CEther', function () { it("reverts when repay borrow fresh fails", async () => { await send(cToken.comptroller, 'setRepayBorrowAllowed', [false]); - await expect(repayBorrow(cToken, borrower, repayAmount)).rejects.toRevertWithError('COMPTROLLER_REJECTION', "revert repayBorrow failed"); + await expect(repayBorrow(cToken, borrower, repayAmount)).rejects.toRevertWithCustomError('RepayBorrowComptrollerRejection', [11]); }); it("returns success from repayBorrowFresh and repays the right amount", async () => { @@ -294,7 +294,7 @@ describe('CEther', function () { it("reverts if overpaying", async () => { const beforeAccountBorrowSnap = await borrowSnapshot(cToken, borrower); let tooMuch = new BigNumber(beforeAccountBorrowSnap.principal).plus(1); - await expect(repayBorrow(cToken, borrower, tooMuch)).rejects.toRevert("revert REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED"); + await expect(repayBorrow(cToken, borrower, tooMuch)).rejects.toRevert(); // await assert.toRevertWithError(repayBorrow(cToken, borrower, tooMuch), 'MATH_ERROR', "revert repayBorrow failed"); }); }); @@ -314,7 +314,7 @@ describe('CEther', function () { it("reverts from within repay borrow fresh", async () => { await send(cToken.comptroller, 'setRepayBorrowAllowed', [false]); - await expect(repayBorrowBehalf(cToken, payer, borrower, repayAmount)).rejects.toRevertWithError('COMPTROLLER_REJECTION', "revert repayBorrowBehalf failed"); + await expect(repayBorrowBehalf(cToken, payer, borrower, repayAmount)).rejects.toRevertWithCustomError('RepayBorrowComptrollerRejection', [11]); }); it("returns success from repayBorrowFresh and repays the right amount", async () => { diff --git a/tests/Tokens/borrowAndRepayTest.js b/tests/Tokens/borrowAndRepayTest.js index 70ebfee18..b1805447a 100644 --- a/tests/Tokens/borrowAndRepayTest.js +++ b/tests/Tokens/borrowAndRepayTest.js @@ -78,7 +78,7 @@ describe('CToken', function () { it("fails if comptroller tells it to", async () => { await send(cToken.comptroller, 'setBorrowAllowed', [false]); - expect(await borrowFresh(cToken, borrower, borrowAmount)).toHaveTrollReject('BORROW_COMPTROLLER_REJECTION'); + await expect(borrowFresh(cToken, borrower, borrowAmount)).rejects.toRevertWithCustomError('BorrowComptrollerRejection', [11]); }); it("proceeds if comptroller tells it to", async () => { @@ -87,7 +87,7 @@ describe('CToken', function () { it("fails if market not fresh", async () => { await fastForward(cToken); - expect(await borrowFresh(cToken, borrower, borrowAmount)).toHaveTokenFailure('MARKET_NOT_FRESH', 'BORROW_FRESHNESS_CHECK'); + await expect(borrowFresh(cToken, borrower, borrowAmount)).rejects.toRevertWithCustomError('BorrowFreshnessCheck'); }); it("continues if fresh", async () => { @@ -96,22 +96,23 @@ describe('CToken', function () { }); it("fails if error if protocol has less than borrowAmount of underlying", async () => { - expect(await borrowFresh(cToken, borrower, borrowAmount.plus(1))).toHaveTokenFailure('TOKEN_INSUFFICIENT_CASH', 'BORROW_CASH_NOT_AVAILABLE'); + await expect(borrowFresh(cToken, borrower, borrowAmount.plus(1))) + .rejects.toRevertWithCustomError('BorrowCashNotAvailable'); }); it("fails if borrowBalanceStored fails (due to non-zero stored principal with zero account index)", async () => { await pretendBorrow(cToken, borrower, 0, 3e18, 5e18); - expect(await borrowFresh(cToken, borrower, borrowAmount)).toHaveTokenFailure('MATH_ERROR', 'BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED'); + await expect(borrowFresh(cToken, borrower, borrowAmount)).rejects.toRevert(); }); it("fails if calculating account new total borrow balance overflows", async () => { await pretendBorrow(cToken, borrower, 1e-18, 1e-18, UInt256Max()); - expect(await borrowFresh(cToken, borrower, borrowAmount)).toHaveTokenFailure('MATH_ERROR', 'BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED'); + await expect(borrowFresh(cToken, borrower, borrowAmount)).rejects.toRevert(); }); it("fails if calculation of new total borrow balance overflows", async () => { await send(cToken, 'harnessSetTotalBorrows', [UInt256Max()]); - expect(await borrowFresh(cToken, borrower, borrowAmount)).toHaveTokenFailure('MATH_ERROR', 'BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED'); + await expect(borrowFresh(cToken, borrower, borrowAmount)).rejects.toRevert(); }); it("reverts if transfer out fails", async () => { @@ -166,7 +167,7 @@ describe('CToken', function () { }); it("returns error from borrowFresh without emitting any extra logs", async () => { - expect(await borrow(cToken, borrower, borrowAmount.plus(1))).toHaveTokenFailure('TOKEN_INSUFFICIENT_CASH', 'BORROW_CASH_NOT_AVAILABLE'); + await expect(borrow(cToken, borrower, borrowAmount.plus(1))).rejects.toRevertWithCustomError('BorrowCashNotAvailable'); }); it("returns success from borrowFresh and transfers the correct amount", async () => { @@ -189,12 +190,12 @@ describe('CToken', function () { it("fails if repay is not allowed", async () => { await send(cToken.comptroller, 'setRepayBorrowAllowed', [false]); - expect(await repayBorrowFresh(cToken, payer, borrower, repayAmount)).toHaveTrollReject('REPAY_BORROW_COMPTROLLER_REJECTION', 'MATH_ERROR'); + await expect(repayBorrowFresh(cToken, payer, borrower, repayAmount)).rejects.toRevertWithCustomError('RepayBorrowComptrollerRejection', [11]); }); it("fails if block number ≠ current block number", async () => { await fastForward(cToken); - expect(await repayBorrowFresh(cToken, payer, borrower, repayAmount)).toHaveTokenFailure('MARKET_NOT_FRESH', 'REPAY_BORROW_FRESHNESS_CHECK'); + await expect(repayBorrowFresh(cToken, payer, borrower, repayAmount)).rejects.toRevertWithCustomError('RepayBorrowFreshnessCheck'); }); it("fails if insufficient approval", async() => { @@ -210,12 +211,12 @@ describe('CToken', function () { it("returns an error if calculating account new account borrow balance fails", async () => { await pretendBorrow(cToken, borrower, 1, 1, 1); - await expect(repayBorrowFresh(cToken, payer, borrower, repayAmount)).rejects.toRevert("revert REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED"); + await expect(repayBorrowFresh(cToken, payer, borrower, repayAmount)).rejects.toRevert(); }); it("returns an error if calculation of new total borrow balance fails", async () => { await send(cToken, 'harnessSetTotalBorrows', [1]); - await expect(repayBorrowFresh(cToken, payer, borrower, repayAmount)).rejects.toRevert("revert REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED"); + await expect(repayBorrowFresh(cToken, payer, borrower, repayAmount)).rejects.toRevert(); }); diff --git a/tests/Tokens/cTokenTest.js b/tests/Tokens/cTokenTest.js index a42445b53..496f35659 100644 --- a/tests/Tokens/cTokenTest.js +++ b/tests/Tokens/cTokenTest.js @@ -162,12 +162,12 @@ describe('CToken', function () { it("reverts on overflow of principal", async () => { await pretendBorrow(cToken, borrower, 1, 3, UInt256Max()); - await expect(call(cToken, 'borrowBalanceStored', [borrower])).rejects.toRevert("revert borrowBalanceStored: borrowBalanceStoredInternal failed"); + await expect(call(cToken, 'borrowBalanceStored', [borrower])).rejects.toRevert(); }); it("reverts on non-zero stored principal with zero account index", async () => { await pretendBorrow(cToken, borrower, 0, 3, 5); - await expect(call(cToken, 'borrowBalanceStored', [borrower])).rejects.toRevert("revert borrowBalanceStored: borrowBalanceStoredInternal failed"); + await expect(call(cToken, 'borrowBalanceStored', [borrower])).rejects.toRevert(); }); }); diff --git a/tests/Tokens/liquidateTest.js b/tests/Tokens/liquidateTest.js index 15f0657d8..00f1b8882 100644 --- a/tests/Tokens/liquidateTest.js +++ b/tests/Tokens/liquidateTest.js @@ -2,7 +2,7 @@ const { etherGasCost, etherUnsigned, etherMantissa, - UInt256Max, + UInt256Max, etherExp } = require('../Utils/Ethereum'); @@ -74,7 +74,7 @@ describe('CToken', function () { cTokenCollateral = await makeCToken({comptroller: cToken.comptroller}); expect(await send(cTokenCollateral, 'harnessSetExchangeRate', [exchangeRate])).toSucceed(); }); - + beforeEach(async () => { await preLiquidate(cToken, liquidator, borrower, repayAmount, cTokenCollateral); }); @@ -82,9 +82,8 @@ describe('CToken', function () { describe('liquidateBorrowFresh', () => { it("fails if comptroller tells it to", async () => { await send(cToken.comptroller, 'setLiquidateBorrowAllowed', [false]); - expect( - await liquidateFresh(cToken, liquidator, borrower, repayAmount, cTokenCollateral) - ).toHaveTrollReject('LIQUIDATE_COMPTROLLER_REJECTION', 'MATH_ERROR'); + await expect(liquidateFresh(cToken, liquidator, borrower, repayAmount, cTokenCollateral)) + .rejects.toRevertWithCustomError('LiquidateComptrollerRejection', [11]); }); it("proceeds if comptroller tells it to", async () => { @@ -95,28 +94,26 @@ describe('CToken', function () { it("fails if market not fresh", async () => { await fastForward(cToken); - expect( - await liquidateFresh(cToken, liquidator, borrower, repayAmount, cTokenCollateral) - ).toHaveTokenFailure('MARKET_NOT_FRESH', 'LIQUIDATE_FRESHNESS_CHECK'); + await expect(liquidateFresh(cToken, liquidator, borrower, repayAmount, cTokenCollateral)) + .rejects.toRevertWithCustomError('LiquidateFreshnessCheck'); }); it("fails if collateral market not fresh", async () => { await fastForward(cToken); await fastForward(cTokenCollateral); await send(cToken, 'accrueInterest'); - expect( - await liquidateFresh(cToken, liquidator, borrower, repayAmount, cTokenCollateral) - ).toHaveTokenFailure('MARKET_NOT_FRESH', 'LIQUIDATE_COLLATERAL_FRESHNESS_CHECK'); + await expect(liquidateFresh(cToken, liquidator, borrower, repayAmount, cTokenCollateral)) + .rejects.toRevertWithCustomError('LiquidateCollateralFreshnessCheck'); }); it("fails if borrower is equal to liquidator", async () => { - expect( - await liquidateFresh(cToken, borrower, borrower, repayAmount, cTokenCollateral) - ).toHaveTokenFailure('INVALID_ACCOUNT_PAIR', 'LIQUIDATE_LIQUIDATOR_IS_BORROWER'); + await expect(liquidateFresh(cToken, borrower, borrower, repayAmount, cTokenCollateral)) + .rejects.toRevertWithCustomError('LiquidateLiquidatorIsBorrower'); }); it("fails if repayAmount = 0", async () => { - expect(await liquidateFresh(cToken, liquidator, borrower, 0, cTokenCollateral)).toHaveTokenFailure('INVALID_CLOSE_AMOUNT_REQUESTED', 'LIQUIDATE_CLOSE_AMOUNT_IS_ZERO'); + await expect(liquidateFresh(cToken, liquidator, borrower, 0, cTokenCollateral)) + .rejects.toRevertWithCustomError('LiquidateCloseAmountIsZero'); }); it("fails if calculating seize tokens fails and does not adjust balances", async () => { @@ -131,16 +128,15 @@ describe('CToken', function () { it("fails if repay fails", async () => { await send(cToken.comptroller, 'setRepayBorrowAllowed', [false]); - expect( - await liquidateFresh(cToken, liquidator, borrower, repayAmount, cTokenCollateral) - ).toHaveTrollReject('LIQUIDATE_REPAY_BORROW_FRESH_FAILED'); + await expect(liquidateFresh(cToken, liquidator, borrower, repayAmount, cTokenCollateral)) + .rejects.toRevertWithCustomError('RepayBorrowComptrollerRejection', [11]); }); it("reverts if seize fails", async () => { await send(cToken.comptroller, 'setSeizeAllowed', [false]); await expect( liquidateFresh(cToken, liquidator, borrower, repayAmount, cTokenCollateral) - ).rejects.toRevert("revert token seizure failed"); + ).rejects.toRevertWithCustomError('LiquidateSeizeComptrollerRejection', [11]); }); xit("reverts if liquidateBorrowVerify fails", async() => { @@ -202,7 +198,7 @@ describe('CToken', function () { }); it("returns error from liquidateBorrowFresh without emitting any extra logs", async () => { - expect(await liquidate(cToken, liquidator, borrower, 0, cTokenCollateral)).toHaveTokenFailure('INVALID_CLOSE_AMOUNT_REQUESTED', 'LIQUIDATE_CLOSE_AMOUNT_IS_ZERO'); + await expect(liquidate(cToken, liquidator, borrower, 0, cTokenCollateral)).rejects.toRevertWithCustomError('LiquidateCloseAmountIsZero'); }); it("returns success from liquidateBorrowFresh and transfers the correct amounts", async () => { @@ -231,17 +227,17 @@ describe('CToken', function () { it("fails if seize is not allowed", async () => { await send(cToken.comptroller, 'setSeizeAllowed', [false]); - expect(await seize(cTokenCollateral, liquidator, borrower, seizeTokens)).toHaveTrollReject('LIQUIDATE_SEIZE_COMPTROLLER_REJECTION', 'MATH_ERROR'); + await expect(seize(cTokenCollateral, liquidator, borrower, seizeTokens)).rejects.toRevertWithCustomError('LiquidateSeizeComptrollerRejection', [11]); }); it("fails if cTokenBalances[borrower] < amount", async () => { await setBalance(cTokenCollateral, borrower, 1); - expect(await seize(cTokenCollateral, liquidator, borrower, seizeTokens)).toHaveTokenMathFailure('LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED', 'INTEGER_UNDERFLOW'); + await expect(seize(cTokenCollateral, liquidator, borrower, seizeTokens)).rejects.toRevert(); }); it("fails if cTokenBalances[liquidator] overflows", async () => { await setBalance(cTokenCollateral, liquidator, UInt256Max()); - expect(await seize(cTokenCollateral, liquidator, borrower, seizeTokens)).toHaveTokenMathFailure('LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED', 'INTEGER_OVERFLOW'); + await expect(seize(cTokenCollateral, liquidator, borrower, seizeTokens)).rejects.toRevert(); }); it("succeeds, updates balances, adds to reserves, and emits Transfer and ReservesAdded events", async () => { @@ -307,7 +303,7 @@ describe('Comptroller', () => { // show deprecated markets can be liquidated even if healthy expect(await send(comptroller, 'liquidateBorrowAllowed', [cTokenBorrow._address, cTokenCollat._address, liquidator, borrower, borrowAmount])).toSucceed(); - + // even if deprecated, cant over repay await expect(send(comptroller, 'liquidateBorrowAllowed', [cTokenBorrow._address, cTokenCollat._address, liquidator, borrower, borrowAmount * 2])).rejects.toRevert('revert Can not repay more than the total borrow'); }); diff --git a/tests/Tokens/mintAndRedeemCEtherTest.js b/tests/Tokens/mintAndRedeemCEtherTest.js index cc3dff6fd..7e88d794a 100644 --- a/tests/Tokens/mintAndRedeemCEtherTest.js +++ b/tests/Tokens/mintAndRedeemCEtherTest.js @@ -103,7 +103,7 @@ describe('CEther', () => { }); it("returns error from redeemFresh without emitting any extra logs", async () => { - expect(await redeem(cToken, redeemer, redeemTokens.multipliedBy(5), redeemAmount.multipliedBy(5))).toHaveTokenFailure('MATH_ERROR', 'REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED'); + await expect(redeem(cToken, redeemer, redeemTokens.multipliedBy(5), redeemAmount.multipliedBy(5))).rejects.toRevert(); }); it("returns success from redeemFresh and redeems the correct amount", async () => { diff --git a/tests/Tokens/mintAndRedeemTest.js b/tests/Tokens/mintAndRedeemTest.js index 4a7b66351..82adc25a3 100644 --- a/tests/Tokens/mintAndRedeemTest.js +++ b/tests/Tokens/mintAndRedeemTest.js @@ -72,7 +72,9 @@ describe('CToken', function () { it("fails if comptroller tells it to", async () => { await send(cToken.comptroller, 'setMintAllowed', [false]); - expect(await mintFresh(cToken, minter, mintAmount)).toHaveTrollReject('MINT_COMPTROLLER_REJECTION', 'MATH_ERROR'); + await expect(mintFresh(cToken, minter, mintAmount)).rejects.toRevertWithCustomError( + 'MintComptrollerRejection', [11] + ); }); it("proceeds if comptroller tells it to", async () => { @@ -81,7 +83,7 @@ describe('CToken', function () { it("fails if not fresh", async () => { await fastForward(cToken); - expect(await mintFresh(cToken, minter, mintAmount)).toHaveTokenFailure('MARKET_NOT_FRESH', 'MINT_FRESHNESS_CHECK'); + await expect(mintFresh(cToken, minter, mintAmount)).rejects.toRevertWithCustomError('MintFreshnessCheck'); }); it("continues if fresh", async () => { @@ -107,7 +109,7 @@ describe('CToken', function () { it("fails if exchange calculation fails", async () => { expect(await send(cToken, 'harnessSetExchangeRate', [0])).toSucceed(); - await expect(mintFresh(cToken, minter, mintAmount)).rejects.toRevert('revert MINT_EXCHANGE_CALCULATION_FAILED'); + await expect(mintFresh(cToken, minter, mintAmount)).rejects.toRevert(); }); it("fails if transferring in fails", async () => { @@ -178,12 +180,15 @@ describe('CToken', function () { it("fails if comptroller tells it to", async () =>{ await send(cToken.comptroller, 'setRedeemAllowed', [false]); - expect(await redeemFresh(cToken, redeemer, redeemTokens, redeemAmount)).toHaveTrollReject('REDEEM_COMPTROLLER_REJECTION'); + await expect(redeemFresh(cToken, redeemer, redeemTokens, redeemAmount)).rejects.toRevertWithCustomError( + 'RedeemComptrollerRejection', [11] + ); }); it("fails if not fresh", async () => { await fastForward(cToken); - expect(await redeemFresh(cToken, redeemer, redeemTokens, redeemAmount)).toHaveTokenFailure('MARKET_NOT_FRESH', 'REDEEM_FRESHNESS_CHECK'); + await expect(redeemFresh(cToken, redeemer, redeemTokens, redeemAmount)) + .rejects.toRevertWithCustomError('RedeemFreshnessCheck') }); it("continues if fresh", async () => { @@ -193,16 +198,17 @@ describe('CToken', function () { it("fails if insufficient protocol cash to transfer out", async() => { await send(cToken.underlying, 'harnessSetBalance', [cToken._address, 1]); - expect(await redeemFresh(cToken, redeemer, redeemTokens, redeemAmount)).toHaveTokenFailure('TOKEN_INSUFFICIENT_CASH', 'REDEEM_TRANSFER_OUT_NOT_POSSIBLE'); + await expect(redeemFresh(cToken, redeemer, redeemTokens, redeemAmount)).rejects + .toRevertWithCustomError('RedeemTransferOutNotPossible'); }); it("fails if exchange calculation fails", async () => { if (redeemFresh == redeemFreshTokens) { expect(await send(cToken, 'harnessSetExchangeRate', [UInt256Max()])).toSucceed(); - expect(await redeemFresh(cToken, redeemer, redeemTokens, redeemAmount)).toHaveTokenFailure('MATH_ERROR', 'REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED'); + await expect(redeemFresh(cToken, redeemer, redeemTokens, redeemAmount)).rejects.toRevert(); } else { expect(await send(cToken, 'harnessSetExchangeRate', [0])).toSucceed(); - expect(await redeemFresh(cToken, redeemer, redeemTokens, redeemAmount)).toHaveTokenFailure('MATH_ERROR', 'REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED'); + await expect(redeemFresh(cToken, redeemer, redeemTokens, redeemAmount)).rejects.toRevert(); } }); @@ -213,12 +219,12 @@ describe('CToken', function () { it("fails if total supply < redemption amount", async () => { await send(cToken, 'harnessExchangeRateDetails', [0, 0, 0]); - expect(await redeemFresh(cToken, redeemer, redeemTokens, redeemAmount)).toHaveTokenFailure('MATH_ERROR', 'REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED'); + await expect(redeemFresh(cToken, redeemer, redeemTokens, redeemAmount)).rejects.toRevert(); }); it("reverts if new account balance underflows", async () => { await send(cToken, 'harnessSetBalance', [redeemer, 0]); - expect(await redeemFresh(cToken, redeemer, redeemTokens, redeemAmount)).toHaveTokenFailure('MATH_ERROR', 'REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED'); + await expect(redeemFresh(cToken, redeemer, redeemTokens, redeemAmount)).rejects.toRevert(); }); it("transfers the underlying cash, tokens, and emits Redeem, Transfer events", async () => { @@ -258,7 +264,7 @@ describe('CToken', function () { it("returns error from redeemFresh without emitting any extra logs", async () => { await setBalance(cToken.underlying, cToken._address, 0); - expect(await quickRedeem(cToken, redeemer, redeemTokens, {exchangeRate})).toHaveTokenFailure('TOKEN_INSUFFICIENT_CASH', 'REDEEM_TRANSFER_OUT_NOT_POSSIBLE'); + await expect(quickRedeem(cToken, redeemer, redeemTokens, {exchangeRate})).rejects.toRevert(); }); it("returns success from redeemFresh and redeems the right amount", async () => { diff --git a/tests/Tokens/reservesTest.js b/tests/Tokens/reservesTest.js index 2ceadcb67..e0d2765c2 100644 --- a/tests/Tokens/reservesTest.js +++ b/tests/Tokens/reservesTest.js @@ -26,20 +26,20 @@ describe('CToken', function () { }); it("rejects change by non-admin", async () => { - expect( - await send(cToken, 'harnessSetReserveFactorFresh', [factor], {from: accounts[0]}) - ).toHaveTokenFailure('UNAUTHORIZED', 'SET_RESERVE_FACTOR_ADMIN_CHECK'); + await expect( + send(cToken, 'harnessSetReserveFactorFresh', [factor], {from: accounts[0]}) + ).rejects.toRevertWithCustomError('SetReserveFactorAdminCheck'); expect(await call(cToken, 'reserveFactorMantissa')).toEqualNumber(0); }); it("rejects change if market not fresh", async () => { expect(await send(cToken, 'harnessFastForward', [5])).toSucceed(); - expect(await send(cToken, 'harnessSetReserveFactorFresh', [factor])).toHaveTokenFailure('MARKET_NOT_FRESH', 'SET_RESERVE_FACTOR_FRESH_CHECK'); + await expect(send(cToken, 'harnessSetReserveFactorFresh', [factor])).rejects.toRevertWithCustomError('SetReserveFactorFreshCheck'); expect(await call(cToken, 'reserveFactorMantissa')).toEqualNumber(0); }); it("rejects newReserveFactor that descales to 1", async () => { - expect(await send(cToken, 'harnessSetReserveFactorFresh', [etherMantissa(1.01)])).toHaveTokenFailure('BAD_INPUT', 'SET_RESERVE_FACTOR_BOUNDS_CHECK'); + await expect(send(cToken, 'harnessSetReserveFactorFresh', [etherMantissa(1.01)])).rejects.toRevertWithCustomError('SetReserveFactorBoundsCheck'); expect(await call(cToken, 'reserveFactorMantissa')).toEqualNumber(0); }); @@ -85,9 +85,7 @@ describe('CToken', function () { }); it("returns error from setReserveFactorFresh without emitting any extra logs", async () => { - const {reply, receipt} = await both(cToken, '_setReserveFactor', [etherMantissa(2)]); - expect(reply).toHaveTokenError('BAD_INPUT'); - expect(receipt).toHaveTokenFailure('BAD_INPUT', 'SET_RESERVE_FACTOR_BOUNDS_CHECK'); + await expect(send(cToken, '_setReserveFactor', [etherMantissa(2)])).rejects.toRevert(); expect(await call(cToken, 'reserveFactorMantissa')).toEqualNumber(0); }); @@ -110,27 +108,27 @@ describe('CToken', function () { }); it("fails if called by non-admin", async () => { - expect( - await send(cToken, 'harnessReduceReservesFresh', [reduction], {from: accounts[0]}) - ).toHaveTokenFailure('UNAUTHORIZED', 'REDUCE_RESERVES_ADMIN_CHECK'); + await expect( + send(cToken, 'harnessReduceReservesFresh', [reduction], {from: accounts[0]}) + ).rejects.toRevertWithCustomError('ReduceReservesAdminCheck'); expect(await call(cToken, 'totalReserves')).toEqualNumber(reserves); }); it("fails if market not fresh", async () => { expect(await send(cToken, 'harnessFastForward', [5])).toSucceed(); - expect(await send(cToken, 'harnessReduceReservesFresh', [reduction])).toHaveTokenFailure('MARKET_NOT_FRESH', 'REDUCE_RESERVES_FRESH_CHECK'); + await expect(send(cToken, 'harnessReduceReservesFresh', [reduction])).rejects.toRevertWithCustomError('ReduceReservesFreshCheck'); expect(await call(cToken, 'totalReserves')).toEqualNumber(reserves); }); it("fails if amount exceeds reserves", async () => { - expect(await send(cToken, 'harnessReduceReservesFresh', [reserves.plus(1)])).toHaveTokenFailure('BAD_INPUT', 'REDUCE_RESERVES_VALIDATION'); + await expect(send(cToken, 'harnessReduceReservesFresh', [reserves.plus(1)])).rejects.toRevertWithCustomError('ReduceReservesCashValidation'); expect(await call(cToken, 'totalReserves')).toEqualNumber(reserves); }); it("fails if amount exceeds available cash", async () => { const cashLessThanReserves = reserves.minus(2); await send(cToken.underlying, 'harnessSetBalance', [cToken._address, cashLessThanReserves]); - expect(await send(cToken, 'harnessReduceReservesFresh', [reserves])).toHaveTokenFailure('TOKEN_INSUFFICIENT_CASH', 'REDUCE_RESERVES_CASH_NOT_AVAILABLE'); + await expect(send(cToken, 'harnessReduceReservesFresh', [reserves])).rejects.toRevertWithCustomError('ReduceReservesCashNotAvailable'); expect(await call(cToken, 'totalReserves')).toEqualNumber(reserves); }); @@ -169,9 +167,7 @@ describe('CToken', function () { }); it("returns error from _reduceReservesFresh without emitting any extra logs", async () => { - const {reply, receipt} = await both(cToken, 'harnessReduceReservesFresh', [reserves.plus(1)]); - expect(reply).toHaveTokenError('BAD_INPUT'); - expect(receipt).toHaveTokenFailure('BAD_INPUT', 'REDUCE_RESERVES_VALIDATION'); + await expect(send(cToken, 'harnessReduceReservesFresh', [reserves.plus(1)])).rejects.toRevert(); }); it("returns success code from _reduceReservesFresh and reduces the correct amount", async () => { diff --git a/tests/Tokens/setComptrollerTest.js b/tests/Tokens/setComptrollerTest.js index 1df2839b0..3b1f77d92 100644 --- a/tests/Tokens/setComptrollerTest.js +++ b/tests/Tokens/setComptrollerTest.js @@ -16,21 +16,22 @@ describe('CToken', function () { describe('_setComptroller', () => { it("should fail if called by non-admin", async () => { - expect( - await send(cToken, '_setComptroller', [newComptroller._address], { from: accounts[0] }) - ).toHaveTokenFailure('UNAUTHORIZED', 'SET_COMPTROLLER_OWNER_CHECK'); + await expect(send(cToken, '_setComptroller', [newComptroller._address], { from: accounts[0] })) + .rejects.toRevertWithCustomError('SetComptrollerOwnerCheck'); expect(await call(cToken, 'comptroller')).toEqual(oldComptroller._address); }); it("reverts if passed a contract that doesn't implement isComptroller", async () => { - await expect(send(cToken, '_setComptroller', [cToken.underlying._address])).rejects.toRevert("revert"); + await expect(send(cToken, '_setComptroller', [cToken.underlying._address])) + .rejects.toRevert("revert"); expect(await call(cToken, 'comptroller')).toEqual(oldComptroller._address); }); it("reverts if passed a contract that implements isComptroller as false", async () => { // extremely unlikely to occur, of course, but let's be exhaustive const badComptroller = await makeComptroller({ kind: 'false-marker' }); - await expect(send(cToken, '_setComptroller', [badComptroller._address])).rejects.toRevert("revert marker method returned false"); + await expect(send(cToken, '_setComptroller', [badComptroller._address])) + .rejects.toRevert("revert marker method returned false"); expect(await call(cToken, 'comptroller')).toEqual(oldComptroller._address); }); diff --git a/tests/Tokens/setInterestRateModelTest.js b/tests/Tokens/setInterestRateModelTest.js index f48b0e3ce..6b0df97e1 100644 --- a/tests/Tokens/setInterestRateModelTest.js +++ b/tests/Tokens/setInterestRateModelTest.js @@ -22,38 +22,35 @@ describe('CToken', function () { }); it("fails if called by non-admin", async () => { - expect( - await send(cToken, 'harnessSetInterestRateModelFresh', [newModel._address], {from: accounts[0]}) - ).toHaveTokenFailure('UNAUTHORIZED', 'SET_INTEREST_RATE_MODEL_OWNER_CHECK'); + await expect(send(cToken, 'harnessSetInterestRateModelFresh', [newModel._address], {from: accounts[0]})) + .rejects.toRevertWithCustomError('SetInterestRateModelOwnerCheck'); expect(await call(cToken, 'interestRateModel')).toEqual(oldModel._address); }); it("fails if market not fresh", async () => { expect(await send(cToken, 'harnessFastForward', [5])).toSucceed(); - expect( - await send(cToken, 'harnessSetInterestRateModelFresh', [newModel._address]) - ).toHaveTokenFailure('MARKET_NOT_FRESH', 'SET_INTEREST_RATE_MODEL_FRESH_CHECK'); + await expect(send(cToken, 'harnessSetInterestRateModelFresh', [newModel._address])) + .rejects.toRevertWithCustomError('SetInterestRateModelFreshCheck'); expect(await call(cToken, 'interestRateModel')).toEqual(oldModel._address); }); it("reverts if passed a contract that doesn't implement isInterestRateModel", async () => { - await expect( - send(cToken, 'harnessSetInterestRateModelFresh', [cToken.underlying._address]) - ).rejects.toRevert(); + await expect(send(cToken, 'harnessSetInterestRateModelFresh', [cToken.underlying._address])) + .rejects.toRevert(); expect(await call(cToken, 'interestRateModel')).toEqual(oldModel._address); }); it("reverts if passed a contract that implements isInterestRateModel as false", async () => { // extremely unlikely to occur, of course, but let's be exhaustive const badModel = await makeInterestRateModel({kind: 'false-marker'}); - await expect(send(cToken, 'harnessSetInterestRateModelFresh', [badModel._address])).rejects.toRevert("revert marker method returned false"); + await expect(send(cToken, 'harnessSetInterestRateModelFresh', [badModel._address])) + .rejects.toRevert("revert marker method returned false"); expect(await call(cToken, 'interestRateModel')).toEqual(oldModel._address); }); it("accepts new valid interest rate model", async () => { - expect( - await send(cToken, 'harnessSetInterestRateModelFresh', [newModel._address]) - ).toSucceed(); + expect(await send(cToken, 'harnessSetInterestRateModelFresh', [newModel._address])) + .toSucceed(); expect(await call(cToken, 'interestRateModel')).toEqual(newModel._address); }); @@ -81,13 +78,12 @@ describe('CToken', function () { it("emits a set market interest rate model failure if interest accrual fails", async () => { await send(cToken.interestRateModel, 'setFailBorrowRate', [true]); await fastForward(cToken, 1); - await expect(send(cToken, '_setInterestRateModel', [newModel._address])).rejects.toRevert("revert INTEREST_RATE_MODEL_ERROR"); + await expect(send(cToken, '_setInterestRateModel', [newModel._address])).rejects.toRevert('revert INTEREST_RATE_MODEL_ERROR'); }); - it("returns error from _setInterestRateModelFresh without emitting any extra logs", async () => { - const {reply, receipt} = await both(cToken, '_setInterestRateModel', [newModel._address], {from: accounts[0]}); - expect(reply).toHaveTokenError('UNAUTHORIZED'); - expect(receipt).toHaveTokenFailure('UNAUTHORIZED', 'SET_INTEREST_RATE_MODEL_OWNER_CHECK'); + it("reverts from _setInterestRateModelFresh", async () => { + await expect(send(cToken, '_setInterestRateModel', [newModel._address], {from: accounts[0]})) + .rejects.toRevertWithCustomError('SetInterestRateModelOwnerCheck'); }); it("reports success when _setInterestRateModelFresh succeeds", async () => { diff --git a/tests/Tokens/transferTest.js b/tests/Tokens/transferTest.js index 0fd1031c7..ba4f36ddf 100644 --- a/tests/Tokens/transferTest.js +++ b/tests/Tokens/transferTest.js @@ -10,7 +10,7 @@ describe('CToken', function () { it("cannot transfer from a zero balance", async () => { const cToken = await makeCToken({supportMarket: true}); expect(await call(cToken, 'balanceOf', [root])).toEqualNumber(0); - expect(await send(cToken, 'transfer', [accounts[0], 100])).toHaveTokenFailure('MATH_ERROR', 'TRANSFER_NOT_ENOUGH'); + await expect(send(cToken, 'transfer', [accounts[0], 100])).rejects.toRevert(); }); it("transfers 50 tokens", async () => { @@ -26,7 +26,7 @@ describe('CToken', function () { const cToken = await makeCToken({supportMarket: true}); await send(cToken, 'harnessSetBalance', [root, 100]); expect(await call(cToken, 'balanceOf', [root])).toEqualNumber(100); - expect(await send(cToken, 'transfer', [root, 50])).toHaveTokenFailure('BAD_INPUT', 'TRANSFER_NOT_ALLOWED'); + await expect(send(cToken, 'transfer', [root, 50])).rejects.toRevertWithCustomError('TransferNotAllowed'); }); it("rejects transfer when not allowed and reverts if not verified", async () => { @@ -35,7 +35,7 @@ describe('CToken', function () { expect(await call(cToken, 'balanceOf', [root])).toEqualNumber(100); await send(cToken.comptroller, 'setTransferAllowed', [false]) - expect(await send(cToken, 'transfer', [root, 50])).toHaveTrollReject('TRANSFER_COMPTROLLER_REJECTION'); + await expect(send(cToken, 'transfer', [root, 50])).rejects.toRevertWithCustomError('TransferComptrollerRejection', [11]); await send(cToken.comptroller, 'setTransferAllowed', [true]) await send(cToken.comptroller, 'setTransferVerify', [false]) @@ -43,4 +43,4 @@ describe('CToken', function () { // await expect(send(cToken, 'transfer', [accounts[0], 50])).rejects.toRevert("revert transferVerify rejected transfer"); }); }); -}); \ No newline at end of file +}); diff --git a/yarn.lock b/yarn.lock index 775fbde69..47964191c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,14 +2,15 @@ # yarn lockfile v1 -"@0x/assert@^3.0.7": - version "3.0.7" - resolved "https://registry.yarnpkg.com/@0x/assert/-/assert-3.0.7.tgz#fb616533ed00480bd642f8419d28e88b547c30df" - integrity sha512-HYdVvIgj/wVb20MVveazLQwICxZGelNuyu/U09ZSMzRy1NrDgrBiMjrU4WrcpW2GTPZjl+7R4U4/7h/C8I/egQ== - dependencies: - "@0x/json-schemas" "^5.0.7" - "@0x/typescript-typings" "^5.0.2" - "@0x/utils" "^5.4.1" +"@0x/assert@^3.0.0", "@0x/assert@^3.0.28": + version "3.0.28" + resolved "https://registry.yarnpkg.com/@0x/assert/-/assert-3.0.28.tgz#04ae55391f90eb433a86e8356cdf6799c63c5a0b" + integrity sha512-hBiBhoThQTEbzHSv/VEuiOAqzP7LWzVs9XXtdb2O8757ocWEcewJsp4cwgqdA4it4IwlWdwG5ASRn7BMSNcyXg== + dependencies: + "@0x/json-schemas" "^6.2.0" + "@0x/typescript-typings" "^5.2.0" + "@0x/utils" "^6.4.3" + "@types/node" "12.12.54" lodash "^4.17.11" valid-url "^1.0.9" @@ -43,16 +44,6 @@ lodash "^4.17.11" web3-provider-engine "14.0.6" -"@0x/json-schemas@^5.0.7": - version "5.0.7" - resolved "https://registry.yarnpkg.com/@0x/json-schemas/-/json-schemas-5.0.7.tgz#4e68074b7ab06984f680df742de825b678a253d3" - integrity sha512-/7gbLno+qQRNjLWRkulbPVOnRoP7uN5CnNP+VKydpKArBgU/E38rUVzSl/Y6FaPbhwC/Rs0d0BmP2Y5DMozjyA== - dependencies: - "@0x/typescript-typings" "^5.0.2" - "@types/node" "*" - jsonschema "^1.2.0" - lodash.values "^4.3.0" - "@0x/json-schemas@^5.1.0": version "5.1.0" resolved "https://registry.yarnpkg.com/@0x/json-schemas/-/json-schemas-5.1.0.tgz#3f30529049ea5aa4cfc4aed2c2124c7482d632f1" @@ -63,6 +54,16 @@ jsonschema "^1.2.0" lodash.values "^4.3.0" +"@0x/json-schemas@^6.2.0": + version "6.2.0" + resolved "https://registry.yarnpkg.com/@0x/json-schemas/-/json-schemas-6.2.0.tgz#d91bfd67b87e9ccb5c259642dd9b231bc56dbb69" + integrity sha512-k3Oe4V5ZwHeCLvMeElMJ6n8Aa3OAip8zcnMrZbtr1jR10ZMvcuZHtSyzXVSFjAw/X0PcAsTvWscmZoZaFcoThg== + dependencies: + "@0x/typescript-typings" "^5.2.0" + "@types/node" "12.12.54" + ajv "^6.12.5" + lodash.values "^4.3.0" + "@0x/sol-compiler@^4.1.1": version "4.1.1" resolved "https://registry.yarnpkg.com/@0x/sol-compiler/-/sol-compiler-4.1.1.tgz#dfab22e2370c03ef8dcfd910d66ced0d46ef5579" @@ -99,26 +100,26 @@ "@0x/typescript-typings" "^5.1.1" lodash "^4.17.11" -"@0x/subproviders@^6.0.0": - version "6.0.8" - resolved "https://registry.yarnpkg.com/@0x/subproviders/-/subproviders-6.0.8.tgz#5fd7461201d434785f231e9d5f2b1b1015e8cc1b" - integrity sha512-OEFZ6qdkHfAvkkcvXSLiCJd2V87NGiZvNcZZkNeupCK77mlDnO0k/IpCe3hr9bUu8PV8vOBvrQaE973vjyCfgQ== +"@0x/subproviders@=6.0.0": + version "6.0.0" + resolved "https://registry.yarnpkg.com/@0x/subproviders/-/subproviders-6.0.0.tgz#9d4b32e22c9e71f450b0f6d00978ca6b1129c0b3" + integrity sha512-5u0JpSGz6RtU0YKckV9FQeJAWkuESG6oR94GQujvkdxg1i1b/QGe9Njq+9VdPq6jhFwl7Hzr8K0JJYTXPlIo5A== dependencies: - "@0x/assert" "^3.0.7" - "@0x/types" "^3.1.2" - "@0x/typescript-typings" "^5.0.2" - "@0x/utils" "^5.4.1" - "@0x/web3-wrapper" "^7.0.7" + "@0x/assert" "^3.0.0" + "@0x/types" "^3.0.0" + "@0x/typescript-typings" "^5.0.0" + "@0x/utils" "^5.0.0" + "@0x/web3-wrapper" "^7.0.0" "@ledgerhq/hw-app-eth" "^4.3.0" "@ledgerhq/hw-transport-u2f" "4.24.0" "@types/hdkey" "^0.7.0" "@types/web3-provider-engine" "^14.0.0" bip39 "^2.5.0" bn.js "^4.11.8" - ethereum-types "^3.1.0" + ethereum-types "^3.0.0" ethereumjs-tx "^1.3.5" ethereumjs-util "^5.1.1" - ganache-core "^2.9.0-istanbul.0" + ganache-core "^2.6.0" hdkey "^0.7.1" json-rpc-error "2.0.0" lodash "^4.17.11" @@ -155,14 +156,14 @@ optionalDependencies: "@ledgerhq/hw-transport-node-hid" "^4.3.0" -"@0x/types@^3.1.2": - version "3.1.2" - resolved "https://registry.yarnpkg.com/@0x/types/-/types-3.1.2.tgz#85fb2e6de4b459bcb162a6065dcd7dc8bdb233ce" - integrity sha512-jweDayth9SSmvhx2Z5cARqQAdB9luzDm+GCzmpqQXYpdPPUzUMXQWjepGouLUgLEoBEq7Xm7DkY+qcTq3ekrSQ== +"@0x/types@^3.0.0", "@0x/types@^3.3.0", "@0x/types@^3.3.3": + version "3.3.3" + resolved "https://registry.yarnpkg.com/@0x/types/-/types-3.3.3.tgz#5df4ec381bba9f62441474b0e54309ddb2fccd17" + integrity sha512-pImq1ukZl+YN64ZKQqNPTOK8noNw4rHMksEEPzFGM26x7Utovf8Py+VFqbZrn1TMw/9WWGeZg8lPxs+LUYxayw== dependencies: - "@types/node" "*" + "@types/node" "12.12.54" bignumber.js "~9.0.0" - ethereum-types "^3.1.0" + ethereum-types "^3.5.0" "@0x/types@^3.2.0": version "3.2.0" @@ -173,15 +174,16 @@ bignumber.js "~9.0.0" ethereum-types "^3.2.0" -"@0x/typescript-typings@^5.0.2": - version "5.0.2" - resolved "https://registry.yarnpkg.com/@0x/typescript-typings/-/typescript-typings-5.0.2.tgz#5589ee8721165d0aa2e5290e28372c560970ab9d" - integrity sha512-syOJE/cN8lg4Homh/TGZPiS493NBmKBFjlaeOpnrjjzGcCG2SqY4nbj+VjGrvhJdw9/KM/J1nWqsCV+KSDORhg== +"@0x/typescript-typings@^5.0.0", "@0x/typescript-typings@^5.1.5", "@0x/typescript-typings@^5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@0x/typescript-typings/-/typescript-typings-5.2.0.tgz#3eba353a27a83697f6f4f6d65ce14506687f52b7" + integrity sha512-8Gk0riQ37HTv3bNe/iWsb9mcJuRCMk/16PZTzA3IUauNQajcJgTD601pHbmBF57SJDpFhJIRg2Crcf6hePlzBA== dependencies: "@types/bn.js" "^4.11.0" + "@types/node" "12.12.54" "@types/react" "*" bignumber.js "~9.0.0" - ethereum-types "^3.1.0" + ethereum-types "^3.5.0" popper.js "1.14.3" "@0x/typescript-typings@^5.1.1": @@ -195,19 +197,19 @@ ethereum-types "^3.2.0" popper.js "1.14.3" -"@0x/utils@^5.4.1": - version "5.4.1" - resolved "https://registry.yarnpkg.com/@0x/utils/-/utils-5.4.1.tgz#5ec5f0d08dad38543b6ff8199bdf8f3d0e63488e" - integrity sha512-zmolzXYt1FZlF3nGI9I1FaMdPp3kQAO/ZmtObFjN2KHG35dl+BBk/lSlWtmaqlVLaSLBQzLREKgjswKEcyT+xA== +"@0x/utils@^5.0.0": + version "5.6.4" + resolved "https://registry.yarnpkg.com/@0x/utils/-/utils-5.6.4.tgz#0158ec3243bbee444d90afbd79981321d19ccdfd" + integrity sha512-VBstWULWGxRbTIMN0QdOthdmZ109LPzPTR3GwbI4svZBizkype/lhRlyCd/B3+qpbpyREAfC8Jn1lUUbk4cwpQ== dependencies: - "@0x/types" "^3.1.2" - "@0x/typescript-typings" "^5.0.2" - "@types/node" "*" + "@0x/types" "^3.3.0" + "@0x/typescript-typings" "^5.1.5" + "@types/node" "12.12.54" abortcontroller-polyfill "^1.1.9" bignumber.js "~9.0.0" chalk "^2.3.0" detect-node "2.0.3" - ethereum-types "^3.1.0" + ethereum-types "^3.3.3" ethereumjs-util "^5.1.1" ethers "~4.0.4" isomorphic-fetch "2.2.1" @@ -233,17 +235,38 @@ js-sha3 "^0.7.0" lodash "^4.17.11" -"@0x/web3-wrapper@^7.0.7": - version "7.0.7" - resolved "https://registry.yarnpkg.com/@0x/web3-wrapper/-/web3-wrapper-7.0.7.tgz#c88b46b1b79e1775e3581d3cbd3e8f26ce220bd1" - integrity sha512-4dqtJW14W2E/hFBL0mTBd6w7QYp3l+OxAsJwhbmB9xnhZj8DfLrQA2RC+cFZnUarhjUeXlUh2B1Zr6YXLv3lEQ== +"@0x/utils@^6.4.3": + version "6.4.3" + resolved "https://registry.yarnpkg.com/@0x/utils/-/utils-6.4.3.tgz#d7c710a8d8b8f2ee3a4e324dc71423078d93ff37" + integrity sha512-HxZ22/fGGL56BhKAtPWe9mAurhzwH775uL6uEpHWt0TuOgNAdDZHz5GhiCh6mTz+5Bf6jmk0/VroMcWUB8qFnw== dependencies: - "@0x/assert" "^3.0.7" - "@0x/json-schemas" "^5.0.7" - "@0x/typescript-typings" "^5.0.2" - "@0x/utils" "^5.4.1" - ethereum-types "^3.1.0" - ethereumjs-util "^5.1.1" + "@0x/types" "^3.3.3" + "@0x/typescript-typings" "^5.2.0" + "@types/mocha" "^5.2.7" + "@types/node" "12.12.54" + abortcontroller-polyfill "^1.1.9" + bignumber.js "~9.0.0" + chalk "^2.3.0" + detect-node "2.0.3" + ethereum-types "^3.5.0" + ethereumjs-util "^7.0.10" + ethers "~4.0.4" + isomorphic-fetch "2.2.1" + js-sha3 "^0.7.0" + lodash "^4.17.11" + +"@0x/web3-wrapper@^7.0.0": + version "7.5.4" + resolved "https://registry.yarnpkg.com/@0x/web3-wrapper/-/web3-wrapper-7.5.4.tgz#451fe3b98f311cfa5343d16beb4174a465424426" + integrity sha512-oMPo9TmAIdzW9Pgn1EwehUywGhRjmxJdIGXPf/gMir1Mnkydv9MY6ICJV5yrd0vkVG+SCWzsYEAkYNqbip/XCQ== + dependencies: + "@0x/assert" "^3.0.28" + "@0x/json-schemas" "^6.2.0" + "@0x/typescript-typings" "^5.2.0" + "@0x/utils" "^6.4.3" + "@types/node" "12.12.54" + ethereum-types "^3.5.0" + ethereumjs-util "^7.0.10" ethers "~4.0.4" lodash "^4.17.11" @@ -268,6 +291,18 @@ dependencies: "@babel/highlight" "^7.8.3" +"@babel/code-frame@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.14.5.tgz#23b08d740e83f49c5e59945fbf1b43e80bbf4edb" + integrity sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw== + dependencies: + "@babel/highlight" "^7.14.5" + +"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.14.5": + version "7.14.7" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.14.7.tgz#7b047d7a3a89a67d2258dc61f604f098f1bc7e08" + integrity sha512-nS6dZaISCXJ3+518CWiBfEr//gHyMO02uDxBkXTKZDN5POruCnOZ1N4YBRZDCabwF8nZMWBpRxIicmXtBs+fvw== + "@babel/core@^7.1.0": version "7.8.6" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.8.6.tgz#27d7df9258a45c2e686b6f18b6c659e563aa4636" @@ -289,7 +324,16 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/generator@^7.4.0", "@babel/generator@^7.8.6": +"@babel/generator@^7.14.8", "@babel/generator@^7.4.0": + version "7.14.8" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.14.8.tgz#bf86fd6af96cf3b74395a8ca409515f89423e070" + integrity sha512-cYDUpvIzhBVnMzRoY1fkSEhK/HmwEVwlyULYgn/tMQYd6Obag3ylCjONle3gdErfXBW61SVTlR9QR7uWlgeIkg== + dependencies: + "@babel/types" "^7.14.8" + jsesc "^2.5.1" + source-map "^0.5.0" + +"@babel/generator@^7.8.6": version "7.8.6" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.8.6.tgz#57adf96d370c9a63c241cd719f9111468578537a" integrity sha512-4bpOR5ZBz+wWcMeVtcf7FbjcFzCp+817z2/gHNncIRcM9MmKzUhtWCYAq27RAfUrAFwb+OCG1s9WEaVxfi6cjg== @@ -299,6 +343,39 @@ lodash "^4.17.13" source-map "^0.5.0" +"@babel/helper-compilation-targets@^7.13.0": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.14.5.tgz#7a99c5d0967911e972fe2c3411f7d5b498498ecf" + integrity sha512-v+QtZqXEiOnpO6EYvlImB6zCD2Lel06RzOPzmkz/D/XgQiUu3C/Jb1LOqSt/AIA34TYi/Q+KlT8vTQrgdxkbLw== + dependencies: + "@babel/compat-data" "^7.14.5" + "@babel/helper-validator-option" "^7.14.5" + browserslist "^4.16.6" + semver "^6.3.0" + +"@babel/helper-define-polyfill-provider@^0.2.2": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.2.3.tgz#0525edec5094653a282688d34d846e4c75e9c0b6" + integrity sha512-RH3QDAfRMzj7+0Nqu5oqgO5q9mFtQEVvCRsi8qCEfzLR9p2BHfn5FzhSB2oj1fF7I2+DcTORkYaQ6aTR9Cofew== + dependencies: + "@babel/helper-compilation-targets" "^7.13.0" + "@babel/helper-module-imports" "^7.12.13" + "@babel/helper-plugin-utils" "^7.13.0" + "@babel/traverse" "^7.13.0" + debug "^4.1.1" + lodash.debounce "^4.0.8" + resolve "^1.14.2" + semver "^6.1.2" + +"@babel/helper-function-name@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.14.5.tgz#89e2c474972f15d8e233b52ee8c480e2cfcd50c4" + integrity sha512-Gjna0AsXWfFvrAuX+VKcN/aNNWonizBj39yGwUzVDVTlMYJMK2Wp6xdpy72mfArFq5uK+NOuexfzZlzI1z9+AQ== + dependencies: + "@babel/helper-get-function-arity" "^7.14.5" + "@babel/template" "^7.14.5" + "@babel/types" "^7.14.5" + "@babel/helper-function-name@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz#eeeb665a01b1f11068e9fb86ad56a1cb1a824cca" @@ -308,6 +385,13 @@ "@babel/template" "^7.8.3" "@babel/types" "^7.8.3" +"@babel/helper-get-function-arity@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.14.5.tgz#25fbfa579b0937eee1f3b805ece4ce398c431815" + integrity sha512-I1Db4Shst5lewOM4V+ZKJzQ0JGGaZ6VY1jYvMghRjqs6DWgxLCIyFt30GlnKkfUeFLpJt2vzbMVEXVSXlIFYUg== + dependencies: + "@babel/types" "^7.14.5" + "@babel/helper-get-function-arity@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz#b894b947bd004381ce63ea1db9f08547e920abd5" @@ -315,18 +399,37 @@ dependencies: "@babel/types" "^7.8.3" -"@babel/helper-module-imports@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.8.3.tgz#7fe39589b39c016331b6b8c3f441e8f0b1419498" - integrity sha512-R0Bx3jippsbAEtzkpZ/6FIiuzOURPcMjHp+Z6xPe6DtApDJx+w7UYyOLanZqO8+wKR9G10s/FmHXvxaMd9s6Kg== +"@babel/helper-hoist-variables@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.14.5.tgz#e0dd27c33a78e577d7c8884916a3e7ef1f7c7f8d" + integrity sha512-R1PXiz31Uc0Vxy4OEOm07x0oSjKAdPPCh3tPivn/Eo8cvz6gveAeuyUUPB21Hoiif0uoPQSSdhIPS3352nvdyQ== dependencies: - "@babel/types" "^7.8.3" + "@babel/types" "^7.14.5" + +"@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.14.5.tgz#6d1a44df6a38c957aa7c312da076429f11b422f3" + integrity sha512-SwrNHu5QWS84XlHwGYPDtCxcA0hrSlL2yhWYLgeOc0w7ccOl2qv4s/nARI0aYZW+bSwAL5CukeXA47B/1NKcnQ== + dependencies: + "@babel/types" "^7.14.5" -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.8.0": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz#9ea293be19babc0f52ff8ca88b34c3611b208670" integrity sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ== +"@babel/helper-plugin-utils@^7.13.0", "@babel/helper-plugin-utils@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz#5ac822ce97eec46741ab70a517971e443a70c5a9" + integrity sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ== + +"@babel/helper-split-export-declaration@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.14.5.tgz#22b23a54ef51c2b7605d851930c1976dd0bc693a" + integrity sha512-hprxVPu6e5Kdp2puZUmvOGjaLv9TCe58E/Fl6hRq4YiVQxIcNvuq6uTM2r1mT/oPskuS9CgR+I94sqAYv0NGKA== + dependencies: + "@babel/types" "^7.14.5" + "@babel/helper-split-export-declaration@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz#31a9f30070f91368a7182cf05f831781065fc7a9" @@ -334,6 +437,16 @@ dependencies: "@babel/types" "^7.8.3" +"@babel/helper-validator-identifier@^7.14.5", "@babel/helper-validator-identifier@^7.14.8": + version "7.14.8" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.8.tgz#32be33a756f29e278a0d644fa08a2c9e0f88a34c" + integrity sha512-ZGy6/XQjllhYQrNw/3zfWRwZCTVSiBLZ9DHVZxn9n2gip/7ab8mv2TWlKPIBk26RwedCBoWdjLmn+t9na2Gcow== + +"@babel/helper-validator-option@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz#6e72a1fff18d5dfcb878e1e62f1a021c4b72d5a3" + integrity sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow== + "@babel/helpers@^7.8.4": version "7.8.4" resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.8.4.tgz#754eb3ee727c165e0a240d6c207de7c455f36f73" @@ -343,6 +456,15 @@ "@babel/traverse" "^7.8.4" "@babel/types" "^7.8.3" +"@babel/highlight@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.14.5.tgz#6861a52f03966405001f6aa534a01a24d99e8cd9" + integrity sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg== + dependencies: + "@babel/helper-validator-identifier" "^7.14.5" + chalk "^2.0.0" + js-tokens "^4.0.0" + "@babel/highlight@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.8.3.tgz#28f173d04223eaaa59bc1d439a3836e6d1265797" @@ -352,11 +474,16 @@ esutils "^2.0.2" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.4.3", "@babel/parser@^7.8.6": +"@babel/parser@^7.1.0", "@babel/parser@^7.8.6": version "7.8.6" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.8.6.tgz#ba5c9910cddb77685a008e3c587af8d27b67962c" integrity sha512-trGNYSfwq5s0SgM1BMEB8hX3NDmO7EP2wsDGDexiaKMB92BaRpS+qZfpkMqUBhcsOTBwNy9B/jieo4ad/t/z2g== +"@babel/parser@^7.14.5", "@babel/parser@^7.14.8", "@babel/parser@^7.4.3": + version "7.14.8" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.14.8.tgz#66fd41666b2d7b840bd5ace7f7416d5ac60208d4" + integrity sha512-syoCQFOoo/fzkWDeM0dLEZi5xqurb5vuyzwIMNZRNun+N/9A4cUZeQaE7dTrB8jGaKuJRBtEOajtnmw0I5hvvA== + "@babel/plugin-syntax-object-rest-spread@^7.0.0": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" @@ -365,23 +492,34 @@ "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-transform-runtime@^7.5.5": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.8.3.tgz#c0153bc0a5375ebc1f1591cb7eea223adea9f169" - integrity sha512-/vqUt5Yh+cgPZXXjmaG9NT8aVfThKk7G4OqkVhrXqwsC5soMn/qTCxs36rZ2QFhpfTJcjw4SNDIZ4RUb8OL4jQ== - dependencies: - "@babel/helper-module-imports" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - resolve "^1.8.1" - semver "^5.5.1" + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.14.5.tgz#30491dad49c6059f8f8fa5ee8896a0089e987523" + integrity sha512-fPMBhh1AV8ZyneiCIA+wYYUH1arzlXR1UMcApjvchDhfKxhy2r2lReJv8uHEyihi4IFIGlr1Pdx7S5fkESDQsg== + dependencies: + "@babel/helper-module-imports" "^7.14.5" + "@babel/helper-plugin-utils" "^7.14.5" + babel-plugin-polyfill-corejs2 "^0.2.2" + babel-plugin-polyfill-corejs3 "^0.2.2" + babel-plugin-polyfill-regenerator "^0.2.2" + semver "^6.3.0" "@babel/runtime@^7.5.5": - version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.8.4.tgz#d79f5a2040f7caa24d53e563aad49cbc05581308" - integrity sha512-neAp3zt80trRVBI1x0azq6c57aNBqYZH8KhMm3TaB7wEI5Q4A2SHfBHE8w9gOhI/lrqxtEbXZgQIrHP+wvSGwQ== + version "7.14.8" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.8.tgz#7119a56f421018852694290b9f9148097391b446" + integrity sha512-twj3L8Og5SaCRCErB4x4ajbvBIVV77CGeFglHpeg5WC5FF8TZzBWXtTJ4MqaD9QszLYTtr+IsaAL2rEUevb+eg== dependencies: - regenerator-runtime "^0.13.2" + regenerator-runtime "^0.13.4" -"@babel/template@^7.4.0", "@babel/template@^7.8.3", "@babel/template@^7.8.6": +"@babel/template@^7.14.5", "@babel/template@^7.4.0": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.14.5.tgz#a9bc9d8b33354ff6e55a9c60d1109200a68974f4" + integrity sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g== + dependencies: + "@babel/code-frame" "^7.14.5" + "@babel/parser" "^7.14.5" + "@babel/types" "^7.14.5" + +"@babel/template@^7.8.3", "@babel/template@^7.8.6": version "7.8.6" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.6.tgz#86b22af15f828dfb086474f964dcc3e39c43ce2b" integrity sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg== @@ -390,7 +528,7 @@ "@babel/parser" "^7.8.6" "@babel/types" "^7.8.6" -"@babel/traverse@^7.1.0", "@babel/traverse@^7.4.3", "@babel/traverse@^7.8.4", "@babel/traverse@^7.8.6": +"@babel/traverse@^7.1.0", "@babel/traverse@^7.8.4", "@babel/traverse@^7.8.6": version "7.8.6" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.8.6.tgz#acfe0c64e1cd991b3e32eae813a6eb564954b5ff" integrity sha512-2B8l0db/DPi8iinITKuo7cbPznLCEk0kCxDoB9/N6gGNg/gxOXiR/IcymAFPiBwk5w6TtQ27w4wpElgp9btR9A== @@ -405,7 +543,22 @@ globals "^11.1.0" lodash "^4.17.13" -"@babel/types@^7.0.0", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.8.3", "@babel/types@^7.8.6": +"@babel/traverse@^7.13.0", "@babel/traverse@^7.4.3": + version "7.14.8" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.14.8.tgz#c0253f02677c5de1a8ff9df6b0aacbec7da1a8ce" + integrity sha512-kexHhzCljJcFNn1KYAQ6A5wxMRzq9ebYpEDV4+WdNyr3i7O44tanbDOR/xjiG2F3sllan+LgwK+7OMk0EmydHg== + dependencies: + "@babel/code-frame" "^7.14.5" + "@babel/generator" "^7.14.8" + "@babel/helper-function-name" "^7.14.5" + "@babel/helper-hoist-variables" "^7.14.5" + "@babel/helper-split-export-declaration" "^7.14.5" + "@babel/parser" "^7.14.8" + "@babel/types" "^7.14.8" + debug "^4.1.0" + globals "^11.1.0" + +"@babel/types@^7.0.0", "@babel/types@^7.3.0", "@babel/types@^7.8.3", "@babel/types@^7.8.6": version "7.8.6" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.8.6.tgz#629ecc33c2557fcde7126e58053127afdb3e6d01" integrity sha512-wqz7pgWMIrht3gquyEFPVXeXCti72Rm8ep9b5tQKz9Yg9LzJA3HxosF1SB3Kc81KD1A3XBkkVYtJvCKS2Z/QrA== @@ -414,6 +567,14 @@ lodash "^4.17.13" to-fast-properties "^2.0.0" +"@babel/types@^7.14.5", "@babel/types@^7.14.8", "@babel/types@^7.4.0": + version "7.14.8" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.14.8.tgz#38109de8fcadc06415fbd9b74df0065d4d41c728" + integrity sha512-iob4soQa7dZw8nodR/KlOQkPh9S4I8RwCxwRIFuiMRYjOzH/KJzdUfDgz6cGi5dDaclXF4P2PAhCdrBJNIg68Q== + dependencies: + "@babel/helper-validator-identifier" "^7.14.8" + to-fast-properties "^2.0.0" + "@cnakazawa/watch@^1.0.3": version "1.0.4" resolved "https://registry.yarnpkg.com/@cnakazawa/watch/-/watch-1.0.4.tgz#f864ae85004d0fcab6f50be9141c4da368d1656a" @@ -422,7 +583,7 @@ exec-sh "^0.3.2" minimist "^1.2.0" -"@compound-finance/sol-coverage@^4.0.10-alpha.7": +"@compound-finance/sol-coverage@=4.0.10-alpha.7": version "4.0.10-alpha.7" resolved "https://registry.yarnpkg.com/@compound-finance/sol-coverage/-/sol-coverage-4.0.10-alpha.7.tgz#7459f23a9934f987e865bc1717a33da137dae696" integrity sha512-UtBAc50sdv2KEnG3y5d2Vm/WvN5UvnhhZZ73BSYut67DNu4l22kOvlgivgO+Gd4cfTHRNhoy7cy0mZuUBomDfQ== @@ -436,7 +597,7 @@ minimatch "^3.0.4" web3-provider-engine "14.0.6" -"@compound-finance/sol-tracing-utils@7.1.0-alpha.7", "@compound-finance/sol-tracing-utils@^7.1.0-alpha.7": +"@compound-finance/sol-tracing-utils@=7.1.0-alpha.7", "@compound-finance/sol-tracing-utils@^7.1.0-alpha.7": version "7.1.0-alpha.7" resolved "https://registry.yarnpkg.com/@compound-finance/sol-tracing-utils/-/sol-tracing-utils-7.1.0-alpha.7.tgz#ad4b06320fb2db115d3266ca8fdfdd68e6d57080" integrity sha512-7yrJsjg7U6zwrDu09FTRN2ziQAv140dBZnQEasiXGy2UPhv17hToKow/bXtrR233ULQ3xHNR9hlpm2jatE5xVQ== @@ -463,22 +624,62 @@ solc "^0.5.5" solidity-parser-antlr "https://github.com/solidity-parser/parser" -"@ethersproject/abi@5.0.0-beta.153": - version "5.0.0-beta.153" - resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.0.0-beta.153.tgz#43a37172b33794e4562999f6e2d555b7599a8eee" - integrity sha512-aXweZ1Z7vMNzJdLpR1CZUAIgnwjrZeUSvN9syCwlBaEBUFJmFY+HHnfuTI5vIhVs/mRkfJVrbEyl51JZQqyjAg== - dependencies: - "@ethersproject/address" ">=5.0.0-beta.128" - "@ethersproject/bignumber" ">=5.0.0-beta.130" - "@ethersproject/bytes" ">=5.0.0-beta.129" - "@ethersproject/constants" ">=5.0.0-beta.128" - "@ethersproject/hash" ">=5.0.0-beta.128" - "@ethersproject/keccak256" ">=5.0.0-beta.127" - "@ethersproject/logger" ">=5.0.0-beta.129" - "@ethersproject/properties" ">=5.0.0-beta.131" - "@ethersproject/strings" ">=5.0.0-beta.130" - -"@ethersproject/address@>=5.0.0-beta.128", "@ethersproject/address@^5.0.0": +"@ethereumjs/common@^2.3.0", "@ethereumjs/common@^2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-2.4.0.tgz#2d67f6e6ba22246c5c89104e6b9a119fb3039766" + integrity sha512-UdkhFWzWcJCZVsj1O/H8/oqj/0RVYjLc1OhPjBrQdALAkQHpCp8xXI4WLnuGTADqTdJZww0NtgwG+TRPkXt27w== + dependencies: + crc-32 "^1.2.0" + ethereumjs-util "^7.1.0" + +"@ethereumjs/tx@^3.2.1": + version "3.3.0" + resolved "https://registry.yarnpkg.com/@ethereumjs/tx/-/tx-3.3.0.tgz#14ed1b7fa0f28e1cd61e3ecbdab824205f6a4378" + integrity sha512-yTwEj2lVzSMgE6Hjw9Oa1DZks/nKTWM8Wn4ykDNapBPua2f4nXO3qKnni86O6lgDj5fVNRqbDsD0yy7/XNGDEA== + dependencies: + "@ethereumjs/common" "^2.4.0" + ethereumjs-util "^7.1.0" + +"@ethersproject/abi@5.0.7": + version "5.0.7" + resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.0.7.tgz#79e52452bd3ca2956d0e1c964207a58ad1a0ee7b" + integrity sha512-Cqktk+hSIckwP/W8O47Eef60VwmoSC/L3lY0+dIBhQPCNn9E4V7rwmm2aFrNRRDJfFlGuZ1khkQUOc3oBX+niw== + dependencies: + "@ethersproject/address" "^5.0.4" + "@ethersproject/bignumber" "^5.0.7" + "@ethersproject/bytes" "^5.0.4" + "@ethersproject/constants" "^5.0.4" + "@ethersproject/hash" "^5.0.4" + "@ethersproject/keccak256" "^5.0.3" + "@ethersproject/logger" "^5.0.5" + "@ethersproject/properties" "^5.0.3" + "@ethersproject/strings" "^5.0.4" + +"@ethersproject/abstract-provider@^5.4.0": + version "5.4.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.4.0.tgz#415331031b0f678388971e1987305244edc04e1d" + integrity sha512-vPBR7HKUBY0lpdllIn7tLIzNN7DrVnhCLKSzY0l8WAwxz686m/aL7ASDzrVxV93GJtIub6N2t4dfZ29CkPOxgA== + dependencies: + "@ethersproject/bignumber" "^5.4.0" + "@ethersproject/bytes" "^5.4.0" + "@ethersproject/logger" "^5.4.0" + "@ethersproject/networks" "^5.4.0" + "@ethersproject/properties" "^5.4.0" + "@ethersproject/transactions" "^5.4.0" + "@ethersproject/web" "^5.4.0" + +"@ethersproject/abstract-signer@^5.4.0": + version "5.4.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.4.0.tgz#cd5f50b93141ee9f9f49feb4075a0b3eafb57d65" + integrity sha512-AieQAzt05HJZS2bMofpuxMEp81AHufA5D6M4ScKwtolj041nrfIbIi8ciNW7+F59VYxXq+V4c3d568Q6l2m8ew== + dependencies: + "@ethersproject/abstract-provider" "^5.4.0" + "@ethersproject/bignumber" "^5.4.0" + "@ethersproject/bytes" "^5.4.0" + "@ethersproject/logger" "^5.4.0" + "@ethersproject/properties" "^5.4.0" + +"@ethersproject/address@^5.0.0": version "5.0.2" resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.0.2.tgz#80d0ddfb7d4bd0d32657747fa4bdd2defef2e00a" integrity sha512-+rz26RKj7ujGfQynys4V9VJRbR+wpC6eL8F22q3raWMH3152Ha31GwJPWzxE/bEA+43M/zTNVwY0R53gn53L2Q== @@ -490,7 +691,25 @@ "@ethersproject/rlp" "^5.0.0" bn.js "^4.4.0" -"@ethersproject/bignumber@>=5.0.0-beta.130", "@ethersproject/bignumber@^5.0.0": +"@ethersproject/address@^5.0.4", "@ethersproject/address@^5.4.0": + version "5.4.0" + resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.4.0.tgz#ba2d00a0f8c4c0854933b963b9a3a9f6eb4a37a3" + integrity sha512-SD0VgOEkcACEG/C6xavlU1Hy3m5DGSXW3CUHkaaEHbAPPsgi0coP5oNPsxau8eTlZOk/bpa/hKeCNoK5IzVI2Q== + dependencies: + "@ethersproject/bignumber" "^5.4.0" + "@ethersproject/bytes" "^5.4.0" + "@ethersproject/keccak256" "^5.4.0" + "@ethersproject/logger" "^5.4.0" + "@ethersproject/rlp" "^5.4.0" + +"@ethersproject/base64@^5.4.0": + version "5.4.0" + resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.4.0.tgz#7252bf65295954c9048c7ca5f43e5c86441b2a9a" + integrity sha512-CjQw6E17QDSSC5jiM9YpF7N1aSCHmYGMt9bWD8PWv6YPMxjsys2/Q8xLrROKI3IWJ7sFfZ8B3flKDTM5wlWuZQ== + dependencies: + "@ethersproject/bytes" "^5.4.0" + +"@ethersproject/bignumber@^5.0.0": version "5.0.5" resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.0.5.tgz#31bd7e75aad46ace345fae69b1f5bb120906af1b" integrity sha512-24ln7PV0g8ZzjcVZiLW9Wod0i+XCmK6zKkAaxw5enraTIT1p7gVOcSXFSzNQ9WYAwtiFQPvvA+TIO2oEITZNJA== @@ -499,31 +718,58 @@ "@ethersproject/logger" "^5.0.0" bn.js "^4.4.0" -"@ethersproject/bytes@>=5.0.0-beta.129", "@ethersproject/bytes@^5.0.0": +"@ethersproject/bignumber@^5.0.7", "@ethersproject/bignumber@^5.4.0": + version "5.4.1" + resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.4.1.tgz#64399d3b9ae80aa83d483e550ba57ea062c1042d" + integrity sha512-fJhdxqoQNuDOk6epfM7yD6J8Pol4NUCy1vkaGAkuujZm0+lNow//MKu1hLhRiYV4BsOHyBv5/lsTjF+7hWwhJg== + dependencies: + "@ethersproject/bytes" "^5.4.0" + "@ethersproject/logger" "^5.4.0" + bn.js "^4.11.9" + +"@ethersproject/bytes@^5.0.0": version "5.0.3" resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.0.3.tgz#b3769963ae0188a35713d343890a903bda20af9c" integrity sha512-AyPMAlY+Amaw4Zfp8OAivm1xYPI8mqiUYmEnSUk1CnS2NrQGHEMmFJFiOJdS3gDDpgSOFhWIjZwxKq2VZpqNTA== dependencies: "@ethersproject/logger" "^5.0.0" -"@ethersproject/constants@>=5.0.0-beta.128", "@ethersproject/constants@^5.0.0": +"@ethersproject/bytes@^5.0.4", "@ethersproject/bytes@^5.4.0": + version "5.4.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.4.0.tgz#56fa32ce3bf67153756dbaefda921d1d4774404e" + integrity sha512-H60ceqgTHbhzOj4uRc/83SCN9d+BSUnOkrr2intevqdtEMO1JFVZ1XL84OEZV+QjV36OaZYxtnt4lGmxcGsPfA== + dependencies: + "@ethersproject/logger" "^5.4.0" + +"@ethersproject/constants@^5.0.0": version "5.0.2" resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.0.2.tgz#f7ac0b320e2bbec1a5950da075015f8bc4e8fed1" integrity sha512-nNoVlNP6bgpog7pQ2EyD1xjlaXcy1Cl4kK5v1KoskHj58EtB6TK8M8AFGi3GgHTdMldfT4eN3OsoQ/CdOTVNFA== dependencies: "@ethersproject/bignumber" "^5.0.0" -"@ethersproject/hash@>=5.0.0-beta.128": - version "5.0.2" - resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.0.2.tgz#6d69558786961836d530b8b4a8714eac5388aec7" - integrity sha512-dWGvNwmVRX2bxoQQ3ciMw46Vzl1nqfL+5R8+2ZxsRXD3Cjgw1dL2mdjJF7xMMWPvPdrlhKXWSK0gb8VLwHZ8Cw== +"@ethersproject/constants@^5.0.4", "@ethersproject/constants@^5.4.0": + version "5.4.0" + resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.4.0.tgz#ee0bdcb30bf1b532d2353c977bf2ef1ee117958a" + integrity sha512-tzjn6S7sj9+DIIeKTJLjK9WGN2Tj0P++Z8ONEIlZjyoTkBuODN+0VfhAyYksKi43l1Sx9tX2VlFfzjfmr5Wl3Q== dependencies: - "@ethersproject/bytes" "^5.0.0" - "@ethersproject/keccak256" "^5.0.0" - "@ethersproject/logger" "^5.0.0" - "@ethersproject/strings" "^5.0.0" + "@ethersproject/bignumber" "^5.4.0" + +"@ethersproject/hash@^5.0.4": + version "5.4.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.4.0.tgz#d18a8e927e828e22860a011f39e429d388344ae0" + integrity sha512-xymAM9tmikKgbktOCjW60Z5sdouiIIurkZUr9oW5NOex5uwxrbsYG09kb5bMcNjlVeJD3yPivTNzViIs1GCbqA== + dependencies: + "@ethersproject/abstract-signer" "^5.4.0" + "@ethersproject/address" "^5.4.0" + "@ethersproject/bignumber" "^5.4.0" + "@ethersproject/bytes" "^5.4.0" + "@ethersproject/keccak256" "^5.4.0" + "@ethersproject/logger" "^5.4.0" + "@ethersproject/properties" "^5.4.0" + "@ethersproject/strings" "^5.4.0" -"@ethersproject/keccak256@>=5.0.0-beta.127", "@ethersproject/keccak256@^5.0.0": +"@ethersproject/keccak256@^5.0.0": version "5.0.2" resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.0.2.tgz#7ed4a95bb45ee502cf4532223833740a83602797" integrity sha512-MbroXutc0gPNYIrUjS4Aw0lDuXabdzI7+l7elRWr1G6G+W0v00e/3gbikWkCReGtt2Jnt4lQSgnflhDwQGcIhA== @@ -531,18 +777,45 @@ "@ethersproject/bytes" "^5.0.0" js-sha3 "0.5.7" -"@ethersproject/logger@>=5.0.0-beta.129", "@ethersproject/logger@^5.0.0": +"@ethersproject/keccak256@^5.0.3", "@ethersproject/keccak256@^5.4.0": + version "5.4.0" + resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.4.0.tgz#7143b8eea4976080241d2bd92e3b1f1bf7025318" + integrity sha512-FBI1plWet+dPUvAzPAeHzRKiPpETQzqSUWR1wXJGHVWi4i8bOSrpC3NwpkPjgeXG7MnugVc1B42VbfnQikyC/A== + dependencies: + "@ethersproject/bytes" "^5.4.0" + js-sha3 "0.5.7" + +"@ethersproject/logger@^5.0.0": version "5.0.4" resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.0.4.tgz#09fa4765b5691233e3afb6617cb38a700f9dd2e4" integrity sha512-alA2LiAy1LdQ/L1SA9ajUC7MvGAEQLsICEfKK4erX5qhkXE1LwLSPIzobtOWFsMHf2yrXGKBLnnpuVHprI3sAw== -"@ethersproject/properties@>=5.0.0-beta.131", "@ethersproject/properties@^5.0.0": +"@ethersproject/logger@^5.0.5", "@ethersproject/logger@^5.4.0": + version "5.4.0" + resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.4.0.tgz#f39adadf62ad610c420bcd156fd41270e91b3ca9" + integrity sha512-xYdWGGQ9P2cxBayt64d8LC8aPFJk6yWCawQi/4eJ4+oJdMMjEBMrIcIMZ9AxhwpPVmnBPrsB10PcXGmGAqgUEQ== + +"@ethersproject/networks@^5.4.0": + version "5.4.1" + resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.4.1.tgz#2ce83b8e42aa85216e5d277a7952d97b6ce8d852" + integrity sha512-8SvowCKz9Uf4xC5DTKI8+il8lWqOr78kmiqAVLYT9lzB8aSmJHQMD1GSuJI0CW4hMAnzocpGpZLgiMdzsNSPig== + dependencies: + "@ethersproject/logger" "^5.4.0" + +"@ethersproject/properties@^5.0.0": version "5.0.2" resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.0.2.tgz#2facb62d2f2d968c7b3d0befa5bcc884cc565d3b" integrity sha512-FxAisPGAOACQjMJzewl9OJG6lsGCPTm5vpUMtfeoxzAlAb2lv+kHzQPUh9h4jfAILzE8AR1jgXMzRmlhwyra1Q== dependencies: "@ethersproject/logger" "^5.0.0" +"@ethersproject/properties@^5.0.3", "@ethersproject/properties@^5.4.0": + version "5.4.0" + resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.4.0.tgz#38ba20539b44dcc5d5f80c45ad902017dcdbefe7" + integrity sha512-7jczalGVRAJ+XSRvNA6D5sAwT4gavLq3OXPuV/74o3Rd2wuzSL035IMpIMgei4CYyBdialJMrTqkOnzccLHn4A== + dependencies: + "@ethersproject/logger" "^5.4.0" + "@ethersproject/rlp@^5.0.0": version "5.0.2" resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.0.2.tgz#d6b550a2ac5e484f15f0f63337e522004d2e78cd" @@ -551,6 +824,14 @@ "@ethersproject/bytes" "^5.0.0" "@ethersproject/logger" "^5.0.0" +"@ethersproject/rlp@^5.4.0": + version "5.4.0" + resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.4.0.tgz#de61afda5ff979454e76d3b3310a6c32ad060931" + integrity sha512-0I7MZKfi+T5+G8atId9QaQKHRvvasM/kqLyAH4XxBCBchAooH2EX5rL9kYZWwcm3awYV+XC7VF6nLhfeQFKVPg== + dependencies: + "@ethersproject/bytes" "^5.4.0" + "@ethersproject/logger" "^5.4.0" + "@ethersproject/signing-key@^5.0.0": version "5.0.3" resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.0.3.tgz#adb84360e147bfd336cb2fe114100120732dc10a" @@ -561,14 +842,26 @@ "@ethersproject/properties" "^5.0.0" elliptic "6.5.3" -"@ethersproject/strings@>=5.0.0-beta.130", "@ethersproject/strings@^5.0.0": - version "5.0.2" - resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.0.2.tgz#1753408c3c889813fd0992abd76393e3e47a2619" - integrity sha512-oNa+xvSqsFU96ndzog0IBTtsRFGOqGpzrXJ7shXLBT7juVeSEyZA/sYs0DMZB5mJ9FEjHdZKxR/rTyBY91vuXg== +"@ethersproject/signing-key@^5.4.0": + version "5.4.0" + resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.4.0.tgz#2f05120984e81cf89a3d5f6dec5c68ee0894fbec" + integrity sha512-q8POUeywx6AKg2/jX9qBYZIAmKSB4ubGXdQ88l40hmATj29JnG5pp331nAWwwxPn2Qao4JpWHNZsQN+bPiSW9A== dependencies: - "@ethersproject/bytes" "^5.0.0" - "@ethersproject/constants" "^5.0.0" - "@ethersproject/logger" "^5.0.0" + "@ethersproject/bytes" "^5.4.0" + "@ethersproject/logger" "^5.4.0" + "@ethersproject/properties" "^5.4.0" + bn.js "^4.11.9" + elliptic "6.5.4" + hash.js "1.1.7" + +"@ethersproject/strings@^5.0.4", "@ethersproject/strings@^5.4.0": + version "5.4.0" + resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.4.0.tgz#fb12270132dd84b02906a8d895ae7e7fa3d07d9a" + integrity sha512-k/9DkH5UGDhv7aReXLluFG5ExurwtIpUfnDNhQA29w896Dw3i4uDTz01Quaptbks1Uj9kI8wo9tmW73wcIEaWA== + dependencies: + "@ethersproject/bytes" "^5.4.0" + "@ethersproject/constants" "^5.4.0" + "@ethersproject/logger" "^5.4.0" "@ethersproject/transactions@^5.0.0-beta.135": version "5.0.2" @@ -585,6 +878,32 @@ "@ethersproject/rlp" "^5.0.0" "@ethersproject/signing-key" "^5.0.0" +"@ethersproject/transactions@^5.4.0": + version "5.4.0" + resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.4.0.tgz#a159d035179334bd92f340ce0f77e83e9e1522e0" + integrity sha512-s3EjZZt7xa4BkLknJZ98QGoIza94rVjaEed0rzZ/jB9WrIuu/1+tjvYCWzVrystXtDswy7TPBeIepyXwSYa4WQ== + dependencies: + "@ethersproject/address" "^5.4.0" + "@ethersproject/bignumber" "^5.4.0" + "@ethersproject/bytes" "^5.4.0" + "@ethersproject/constants" "^5.4.0" + "@ethersproject/keccak256" "^5.4.0" + "@ethersproject/logger" "^5.4.0" + "@ethersproject/properties" "^5.4.0" + "@ethersproject/rlp" "^5.4.0" + "@ethersproject/signing-key" "^5.4.0" + +"@ethersproject/web@^5.4.0": + version "5.4.0" + resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.4.0.tgz#49fac173b96992334ed36a175538ba07a7413d1f" + integrity sha512-1bUusGmcoRLYgMn6c1BLk1tOKUIFuTg8j+6N8lYlbMpDesnle+i3pGSagGNvwjaiLo4Y5gBibwctpPRmjrh4Og== + dependencies: + "@ethersproject/base64" "^5.4.0" + "@ethersproject/bytes" "^5.4.0" + "@ethersproject/logger" "^5.4.0" + "@ethersproject/properties" "^5.4.0" + "@ethersproject/strings" "^5.4.0" + "@jest/console@^24.7.1", "@jest/console@^24.9.0": version "24.9.0" resolved "https://registry.yarnpkg.com/@jest/console/-/console-24.9.0.tgz#79b1bc06fb74a8cfb01cbdedf945584b1b9707f0" @@ -733,10 +1052,10 @@ "@types/istanbul-reports" "^1.1.1" "@types/yargs" "^13.0.0" -"@jest/types@^25.3.0": - version "25.3.0" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-25.3.0.tgz#88f94b277a1d028fd7117bc1f74451e0fc2131e7" - integrity sha512-UkaDNewdqXAmCDbN2GlUM6amDKS78eCqiw/UmF5nE0mmLTd6moJkiZJML/X52Ke3LH7Swhw883IRXq8o9nWjVw== +"@jest/types@^25.5.0": + version "25.5.0" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-25.5.0.tgz#4d6a4793f7b9599fc3680877b856a97dbccf2a9d" + integrity sha512-OXD0RgQ86Tu3MazKo8bnrkDRaDXXMGUqd+kTtLtK1Zb7CRzQcaSRPPPV37SvYTdevXEBVxe0HXylEjs8ibkmCw== dependencies: "@types/istanbul-lib-coverage" "^2.0.0" "@types/istanbul-reports" "^1.1.1" @@ -823,6 +1142,11 @@ resolved "https://registry.yarnpkg.com/@ledgerhq/logs/-/logs-4.72.0.tgz#43df23af013ad1135407e5cf33ca6e4c4c7708d5" integrity sha512-o+TYF8vBcyySRsb2kqBDv/KMeme8a2nwWoG+lAWzbDmWfb2/MrVWYCVYDYvjXdSoI/Cujqy1i0gIDrkdxa9chA== +"@metamask/safe-event-emitter@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@metamask/safe-event-emitter/-/safe-event-emitter-2.0.0.tgz#af577b477c683fad17c619a78208cede06f9605c" + integrity sha512-/kSXhY692qiV1MXu6EeOZvg5nECLclxNXcKCxJ3cXQgYuRymRHpdx/t7JXfsK+JLjwA1e1c1/SBrlQYpusC29Q== + "@nodelib/fs.scandir@2.1.3": version "2.1.3" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz#3a582bdb53804c6ba6d146579c46e52130cf4a3b" @@ -849,6 +1173,20 @@ resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== +"@solidity-parser/parser@^0.13.2": + version "0.13.2" + resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.13.2.tgz#b6c71d8ca0b382d90a7bbed241f9bc110af65cbe" + integrity sha512-RwHnpRnfrnD2MSPveYoPh8nhofEvX7fgjHk1Oq+NNvCcLx4r1js91CO9o+F/F3fBzOCyvm8kKRTriFICX/odWw== + dependencies: + antlr4ts "^0.5.0-alpha.4" + +"@solidity-parser/parser@^0.14.1": + version "0.14.1" + resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.14.1.tgz#179afb29f4e295a77cc141151f26b3848abc3c46" + integrity sha512-eLjj2L6AuQjBB6s/ibwCAc0DwrR5Ge+ys+wgWo+bviU7fV2nTMQhU63CGaDKXg9iTmMxwhkyoggdIR7ZGRfMgw== + dependencies: + antlr4ts "^0.5.0-alpha.4" + "@szmarczak/http-timer@^1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" @@ -857,9 +1195,9 @@ defer-to-connect "^1.0.1" "@types/babel__core@^7.1.0": - version "7.1.6" - resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.6.tgz#16ff42a5ae203c9af1c6e190ed1f30f83207b610" - integrity sha512-tTnhWszAqvXnhW7m5jQU9PomXSiKXk2sFxpahXvI20SZKu9ylPi8WtIxueZ6ehDWikPT0jeFujMj3X4ZHuf3Tg== + version "7.1.15" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.15.tgz#2ccfb1ad55a02c83f8e0ad327cbc332f55eb1024" + integrity sha512-bxlMKPDbY8x5h6HBwVzEOk2C8fb6SLfYQ5Jw3uBYuYF1lfWk/kbLd81la82vrIkBb0l+JdmrZaDikPrNxpS/Ew== dependencies: "@babel/parser" "^7.1.0" "@babel/types" "^7.0.0" @@ -903,6 +1241,13 @@ dependencies: "@types/node" "*" +"@types/bn.js@^5.1.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.0.tgz#32c5d271503a12653c62cf4d2b45e6eab8cebc68" + integrity sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA== + dependencies: + "@types/node" "*" + "@types/color-name@^1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" @@ -935,9 +1280,9 @@ "@types/istanbul-lib-coverage" "*" "@types/istanbul-reports@^1.1.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-1.1.1.tgz#7a8cbf6a406f36c8add871625b278eaf0b0d255a" - integrity sha512-UpYjBi8xefVChsCoBpKShdxTllC9pwISirfoZsUa2AAdQg/Jd2KQGtSbw+ya7GPo7x/wAPlH6JBhKhAsXUEZNA== + version "1.1.2" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-1.1.2.tgz#e875cc689e47bce549ec81f3df5e6f6f11cfaeb2" + integrity sha512-P/W9yOX/3oPZSpaYOCQzGqgCQRXn0FFO/V8bWrCQs+wLmvVVxk6CRBXALEvNs9OHIatlnlFokfhuDo2ug01ciw== dependencies: "@types/istanbul-lib-coverage" "*" "@types/istanbul-lib-report" "*" @@ -961,26 +1306,38 @@ resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== +"@types/mocha@^5.2.7": + version "5.2.7" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-5.2.7.tgz#315d570ccb56c53452ff8638738df60726d5b6ea" + integrity sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ== + "@types/node@*": version "13.7.6" resolved "https://registry.yarnpkg.com/@types/node/-/node-13.7.6.tgz#cb734a7c191472ae6a2b3a502b4dfffcea974113" integrity sha512-eyK7MWD0R1HqVTp+PtwRgFeIsemzuj4gBFSQxfPHY5iMjS7474e5wq+VFgTcdpyHeNxyKSaetYAjdMLJlKoWqA== +"@types/node@12.12.54", "@types/node@^12.12.6": + version "12.12.54" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.54.tgz#a4b58d8df3a4677b6c08bfbc94b7ad7a7a5f82d1" + integrity sha512-ge4xZ3vSBornVYlDnk7yZ0gK6ChHf/CHB7Gl1I0Jhah8DDnEQqBzgohYG4FX4p81TNirSETOiSyn+y1r9/IR6w== + "@types/node@^10.12.18", "@types/node@^10.3.2": version "10.17.16" resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.16.tgz#ee96ddac1a38d98d2c8a71c7df0cdad5758e8993" integrity sha512-A4283YSA1OmnIivcpy/4nN86YlnKRiQp8PYwI2KdPCONEBN093QTb0gCtERtkLyVNGKKIGazTZ2nAmVzQU51zA== -"@types/node@^12.12.6": - version "12.12.54" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.54.tgz#a4b58d8df3a4677b6c08bfbc94b7ad7a7a5f82d1" - integrity sha512-ge4xZ3vSBornVYlDnk7yZ0gK6ChHf/CHB7Gl1I0Jhah8DDnEQqBzgohYG4FX4p81TNirSETOiSyn+y1r9/IR6w== - "@types/node@^12.6.1": version "12.12.28" resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.28.tgz#3a2b5f8d21f96ace690a8832ae9779114612575f" integrity sha512-g73GJYJDXgf0jqg+P9S8h2acWbDXNkoCX8DLtJVu7Fkn788pzQ/oJsrdJz/2JejRf/SjfZaAhsw+3nd1D5EWGg== +"@types/pbkdf2@^3.0.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@types/pbkdf2/-/pbkdf2-3.1.0.tgz#039a0e9b67da0cdc4ee5dab865caa6b267bb66b1" + integrity sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ== + dependencies: + "@types/node" "*" + "@types/prop-types@*": version "15.7.3" resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7" @@ -994,6 +1351,13 @@ "@types/prop-types" "*" csstype "^2.2.0" +"@types/secp256k1@^4.0.1": + version "4.0.3" + resolved "https://registry.yarnpkg.com/@types/secp256k1/-/secp256k1-4.0.3.tgz#1b8e55d8e00f08ee7220b4d59a6abe89c37a901c" + integrity sha512-Da66lEIFeIz9ltsdMZcpQvmrmmoqrfju8pm1BH8WbYjZSwUgCwXLb9C+9XYogwBITnbsSaMdVPb2ekf7TV+03w== + dependencies: + "@types/node" "*" + "@types/solidity-parser-antlr@^0.2.3": version "0.2.3" resolved "https://registry.yarnpkg.com/@types/solidity-parser-antlr/-/solidity-parser-antlr-0.2.3.tgz#bb2d9c6511bf483afe4fc3e2714da8a924e59e3f" @@ -1022,9 +1386,9 @@ integrity sha512-1jmXgoIyzxQSm33lYgEXvegtkhloHbed2I0QGlTN66U2F9/ExqJWSCSmaWC0IB/g1tW+IYSp+tDhcZBYB1ZGog== "@types/yargs@^13.0.0": - version "13.0.8" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-13.0.8.tgz#a38c22def2f1c2068f8971acb3ea734eb3c64a99" - integrity sha512-XAvHLwG7UQ+8M4caKIH0ZozIOYay5fQkAgyIXegXT9jPtdIGdhga+sUEdAr1CiG46aB+c64xQEYyEzlwWVTNzA== + version "13.0.12" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-13.0.12.tgz#d895a88c703b78af0465a9de88aa92c61430b092" + integrity sha512-qCxJE1qgz2y0hA4pIxjBR+PelCH0U5CK1XJXFwCNqfmliatKp47UCXXE9Dyk1OXBDLvsCF57TqQEJaeLfDYEOQ== dependencies: "@types/yargs-parser" "*" @@ -1055,9 +1419,9 @@ yaeti "^0.0.6" abab@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.3.tgz#623e2075e02eb2d3f2475e49f99c91846467907a" - integrity sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg== + version "2.0.5" + resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a" + integrity sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q== abbrev@1: version "1.1.1" @@ -1118,20 +1482,25 @@ acorn-globals@^4.1.0: acorn "^6.0.1" acorn-walk "^6.0.1" +acorn-jsx@^5.0.0: + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + acorn-walk@^6.0.1: version "6.2.0" resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.2.0.tgz#123cb8f3b84c2171f1f7fb252615b1c78a6b1a8c" integrity sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA== acorn@^5.5.3: - version "5.7.3" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" - integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw== + version "5.7.4" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.4.tgz#3e8d8a9947d0599a1796d10225d7432f4a4acf5e" + integrity sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg== -acorn@^6.0.1: - version "6.4.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.0.tgz#b659d2ffbafa24baf5db1cdbb2c94a983ecd2784" - integrity sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw== +acorn@^6.0.1, acorn@^6.0.7: + version "6.4.2" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6" + integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ== aes-js@3.0.0: version "3.0.0" @@ -1143,15 +1512,15 @@ aes-js@^3.1.1: resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.1.2.tgz#db9aabde85d5caabbfc0d4f2a4446960f627146a" integrity sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ== -ajv@^5.2.2: - version "5.5.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" - integrity sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU= +ajv@^6.10.2, ajv@^6.12.5, ajv@^6.6.1, ajv@^6.9.1: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== dependencies: - co "^4.6.0" - fast-deep-equal "^1.0.0" + fast-deep-equal "^3.1.1" fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.3.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" ajv@^6.5.5: version "6.12.0" @@ -1175,7 +1544,7 @@ ansi-colors@^1.0.1: dependencies: ansi-wrap "^0.1.0" -ansi-escapes@^3.0.0: +ansi-escapes@^3.0.0, ansi-escapes@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== @@ -1232,19 +1601,21 @@ ansi-wrap@0.1.0, ansi-wrap@^0.1.0: resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf" integrity sha1-qCJQ3bABXponyoLoLqYDu/pF768= +antlr4@4.7.1: + version "4.7.1" + resolved "https://registry.yarnpkg.com/antlr4/-/antlr4-4.7.1.tgz#69984014f096e9e775f53dd9744bf994d8959773" + integrity sha512-haHyTW7Y9joE5MVs37P2lNYfU2RWBLfcRDD8OWldcdZm5TiCE91B5Xl1oWSwiDUSd4rlExpt2pu1fksYQjRBYQ== + +antlr4ts@^0.5.0-alpha.4: + version "0.5.0-alpha.4" + resolved "https://registry.yarnpkg.com/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz#71702865a87478ed0b40c0709f422cf14d51652a" + integrity sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ== + any-promise@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" integrity sha1-q8av7tzqUugJzcA3au0845Y10X8= -anymatch@^1.3.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.2.tgz#553dcb8f91e3c889845dfdba34c77721b90b9d7a" - integrity sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA== - dependencies: - micromatch "^2.1.5" - normalize-path "^2.0.0" - anymatch@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" @@ -1293,13 +1664,6 @@ argparse@^1.0.7: dependencies: sprintf-js "~1.0.2" -arr-diff@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" - integrity sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8= - dependencies: - arr-flatten "^1.0.1" - arr-diff@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" @@ -1373,11 +1737,6 @@ array-sort@^1.0.0: get-value "^2.0.6" kind-of "^5.0.2" -array-unique@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" - integrity sha1-odl8yvy8JiXMcPrc6zalDFiwGlM= - array-unique@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" @@ -1414,6 +1773,11 @@ assign-symbols@^1.0.0: resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= +ast-parents@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/ast-parents/-/ast-parents-0.0.1.tgz#508fd0f05d0c48775d9eccda2e174423261e8dd3" + integrity sha512-XHusKxKz3zoYk1ic8Un640joHbFMhbqneyoZfoKnEGtf2ey9Uh/IdpcQplODdO/kENaMIWsD0nJm4+wX3UNLHA== + astral-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" @@ -1429,7 +1793,7 @@ async-done@^1.2.0, async-done@^1.2.2: process-nextick-args "^2.0.0" stream-exhaust "^1.0.1" -async-each@^1.0.0, async-each@^1.0.1: +async-each@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== @@ -1446,6 +1810,13 @@ async-limiter@~1.0.0: resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== +async-mutex@^0.2.6: + version "0.2.6" + resolved "https://registry.yarnpkg.com/async-mutex/-/async-mutex-0.2.6.tgz#0d7a3deb978bc2b984d5908a2038e1ae2e54ff40" + integrity sha512-Hs4R+4SPgamu6rSGW8C7cV9gaWUKEHykfzCCvIRuaVv636Ju10ZdeUbvb4TBEW0INuq2DHZqXbK4Nd3yG4RaRw== + dependencies: + tslib "^2.0.0" + async-settle@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/async-settle/-/async-settle-1.0.0.tgz#1d0a914bb02575bec8a8f3a74e5080f72b2c0c6b" @@ -1482,10 +1853,10 @@ atob@^2.1.2: resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== -await-semaphore@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/await-semaphore/-/await-semaphore-0.1.3.tgz#2b88018cc8c28e06167ae1cdff02504f1f9688d3" - integrity sha512-d1W2aNSYcz/sxYO4pMGX9vq65qOTu0P800epMud+6cYYX0QcT7zyqcxec3VWzpgvdXo57UWmVbZpLMjX2m1I7Q== +available-typed-arrays@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.4.tgz#9e0ae84ecff20caae6a94a1c3bc39b955649b7a9" + integrity sha512-SA5mXJWrId1TaQjfxUYghbqQ/hYioKmLJvPJyDuYRtXXenFNMjj4hSSt1Cf1xsuXSXrtxrVC5Ot4eU6cOtBDdA== aws-sign2@~0.7.0: version "0.7.0" @@ -1702,6 +2073,30 @@ babel-plugin-jest-hoist@^24.9.0: dependencies: "@types/babel__traverse" "^7.0.6" +babel-plugin-polyfill-corejs2@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.2.2.tgz#e9124785e6fd94f94b618a7954e5693053bf5327" + integrity sha512-kISrENsJ0z5dNPq5eRvcctITNHYXWOA4DUZRFYCz3jYCcvTb/A546LIddmoGNMVYg2U38OyFeNosQwI9ENTqIQ== + dependencies: + "@babel/compat-data" "^7.13.11" + "@babel/helper-define-polyfill-provider" "^0.2.2" + semver "^6.1.1" + +babel-plugin-polyfill-corejs3@^0.2.2: + version "0.2.3" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.2.3.tgz#72add68cf08a8bf139ba6e6dfc0b1d504098e57b" + integrity sha512-rCOFzEIJpJEAU14XCcV/erIf/wZQMmMT5l5vXOpL5uoznyOGfDIjPj6FVytMvtzaKSTSVKouOCTPJ5OMUZH30g== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.2.2" + core-js-compat "^3.14.0" + +babel-plugin-polyfill-regenerator@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.2.2.tgz#b310c8d642acada348c1fa3b3e6ce0e851bee077" + integrity sha512-Goy5ghsc21HgPDFtzRkSirpZVW35meGoTmTOb2bxqdl60ghub4xOidgNTHaZfQ2FaxQsKmwvXtOAkcIS4SMBWg== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.2.2" + babel-plugin-syntax-async-functions@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" @@ -2184,6 +2579,11 @@ bl@^3.0.0: dependencies: readable-stream "^3.0.1" +blakejs@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.1.1.tgz#bf313053978b2cd4c444a48795710be05c785702" + integrity sha512-bLG6PHOCZJKNshTjGRBvET0vTciwQE6zFKOKKXPDJfwFBd4Ac0yBfPZqcGvGJap50l7ktvlpFqc2jGVaUgbJgg== + bluebird@^3.5.0: version "3.7.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" @@ -2204,6 +2604,11 @@ bn.js@^4.11.9: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.9.tgz#26d556829458f9d1e81fc48952493d0ba3507828" integrity sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw== +bn.js@^5.1.2: + version "5.2.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.0.tgz#358860674396c6997771a9d051fcc1b57d4ae002" + integrity sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw== + body-parser@1.19.0, body-parser@^1.16.0: version "1.19.0" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" @@ -2228,15 +2633,6 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -braces@^1.8.2: - version "1.8.5" - resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" - integrity sha1-uneWLhLf+WnWt2cR6RS3N4V79qc= - dependencies: - expand-range "^1.8.1" - preserve "^0.2.0" - repeat-element "^1.1.2" - braces@^2.3.1, braces@^2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" @@ -2260,15 +2656,15 @@ braces@^3.0.1, braces@~3.0.2: dependencies: fill-range "^7.0.1" -brorand@^1.0.1: +brorand@^1.0.1, brorand@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= -browser-process-hrtime@^0.1.2: - version "0.1.3" - resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz#616f00faef1df7ec1b5bf9cfe2bdc3170f26c7b4" - integrity sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw== +browser-process-hrtime@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" + integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow== browser-resolve@^1.11.3: version "1.11.3" @@ -2282,7 +2678,7 @@ browser-stdout@1.3.0: resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" integrity sha1-81HTKWnTL6XXpVZxVCY9korjvR8= -browserify-aes@^1.0.0, browserify-aes@^1.0.4, browserify-aes@^1.0.6: +browserify-aes@^1.0.0, browserify-aes@^1.0.4, browserify-aes@^1.0.6, browserify-aes@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== @@ -2350,6 +2746,17 @@ browserslist@^3.2.6: caniuse-lite "^1.0.30000844" electron-to-chromium "^1.3.47" +browserslist@^4.16.6: + version "4.16.6" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.6.tgz#d7901277a5a88e554ed305b183ec9b0c08f66fa2" + integrity sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ== + dependencies: + caniuse-lite "^1.0.30001219" + colorette "^1.2.2" + electron-to-chromium "^1.3.723" + escalade "^3.1.1" + node-releases "^1.1.71" + bs-logger@0.x: version "0.2.6" resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" @@ -2449,6 +2856,13 @@ buffer@^5.5.0, buffer@^5.6.0: base64-js "^1.0.2" ieee754 "^1.1.4" +bufferutil@^4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.3.tgz#66724b756bed23cd7c28c4d306d7994f9943cc6b" + integrity sha512-yEYTwGndELGvfXsImMBLop58eaGW+YdONi1fNjTINSY98tmMmFijBG6WXgdkfuLNt4imzQNtIE+eBp1PVpMCSw== + dependencies: + node-gyp-build "^4.2.0" + bytes@3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" @@ -2505,6 +2919,33 @@ cachedown@1.0.0: abstract-leveldown "^2.4.1" lru-cache "^3.2.0" +call-bind@^1.0.0, call-bind@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + +caller-callsite@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" + integrity sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ== + dependencies: + callsites "^2.0.0" + +caller-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" + integrity sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A== + dependencies: + caller-callsite "^2.0.0" + +callsites@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" + integrity sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ== + callsites@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" @@ -2530,6 +2971,11 @@ caniuse-lite@^1.0.30000844: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001030.tgz#78076c4c6d67d3e41d6eb9399853fb27fe6e44ee" integrity sha512-QGK0W4Ft/Ac+zTjEiRJfwDNATvS3fodDczBXrH42784kcfqcDKpEPfN08N0HQjrAp8He/Jw8QiSS9QRn7XAbUw== +caniuse-lite@^1.0.30001219: + version "1.0.30001247" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001247.tgz#105be7a8fb30cdd303275e769a9dfb87d4b3577a" + integrity sha512-4rS7co+7+AoOSPRPOPUt5/GdaqZc0EsUpWk66ofE3HJTAajUK2Ss2VwoNzVN69ghg8lYYlh0an0Iy4LIHHo9UQ== + capture-exit@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4" @@ -2577,7 +3023,7 @@ chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.0, chalk@^2.4.2: +chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -2602,6 +3048,11 @@ chalk@^4.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" +chardet@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" + integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== + check-error@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" @@ -2614,22 +3065,6 @@ checkpoint-store@^1.1.0: dependencies: functional-red-black-tree "^1.0.1" -chokidar@^1.6.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468" - integrity sha1-eY5ol3gVHIB2tLNg5e3SjNortGg= - dependencies: - anymatch "^1.3.0" - async-each "^1.0.0" - glob-parent "^2.0.0" - inherits "^2.0.1" - is-binary-path "^1.0.0" - is-glob "^2.0.0" - path-is-absolute "^1.0.0" - readdirp "^2.0.0" - optionalDependencies: - fsevents "^1.0.0" - chokidar@^2.0.0: version "2.1.8" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" @@ -2708,6 +3143,18 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" +cli-cursor@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" + integrity sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw== + dependencies: + restore-cursor "^2.0.0" + +cli-width@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48" + integrity sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw== + cliui@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" @@ -2830,10 +3277,10 @@ color-support@^1.1.3: resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== -colors@^1.1.2: - version "1.4.0" - resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" - integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== +colorette@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.2.tgz#cbcc79d5e99caea2dbf10eb3a26fd8b3e6acfa94" + integrity sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w== combined-stream@^1.0.6, combined-stream@~1.0.6: version "1.0.8" @@ -2852,12 +3299,17 @@ commander@2.11.0: resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" integrity sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ== +commander@2.18.0: + version "2.18.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.18.0.tgz#2bf063ddee7c7891176981a2cc798e5754bc6970" + integrity sha512-6CYPa+JP2ftfRU2qkDK+UTVeQYosOg/2GbcjIcKPHfinyOLPVGXu/ovN86RP49Re5ndJK1N0kuiidFFuepc4ZQ== + commander@3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/commander/-/commander-3.0.2.tgz#6837c3fb677ad9933d1cfba42dd14d5117d6b39e" integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow== -commander@^2.9.0, commander@~2.20.3: +commander@~2.20.3: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== @@ -2950,6 +3402,14 @@ copy-props@^2.0.1: each-props "^1.3.0" is-plain-object "^2.0.1" +core-js-compat@^3.14.0: + version "3.15.2" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.15.2.tgz#47272fbb479880de14b4e6081f71f3492f5bd3cb" + integrity sha512-Wp+BJVvwopjI+A1EFqm2dwUmWYXrvucmtIB2LgXn/Rb+gWPKYxtmb4GKHGKG/KGF1eK9jfjzT38DITbTOCX/SQ== + dependencies: + browserslist "^4.16.6" + semver "7.0.0" + core-js-pure@^3.0.1: version "3.6.4" resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.6.4.tgz#4bf1ba866e25814f149d4e9aaa08c36173506e3a" @@ -2973,6 +3433,24 @@ cors@^2.8.1: object-assign "^4" vary "^1" +cosmiconfig@^5.0.7: + version "5.2.1" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" + integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== + dependencies: + import-fresh "^2.0.0" + is-directory "^0.3.1" + js-yaml "^3.13.1" + parse-json "^4.0.0" + +crc-32@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.0.tgz#cb2db6e29b88508e32d9dd0ec1693e7b41a18208" + integrity sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA== + dependencies: + exit-on-epipe "~1.0.1" + printj "~1.1.0" + create-ecdh@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff" @@ -2992,7 +3470,7 @@ create-hash@^1.1.0, create-hash@^1.1.1, create-hash@^1.1.2, create-hash@^1.2.0: ripemd160 "^2.0.1" sha.js "^2.4.0" -create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: +create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4, create-hmac@^1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== @@ -3021,7 +3499,7 @@ cross-spawn@^5.0.1: shebang-command "^1.2.0" which "^1.2.9" -cross-spawn@^6.0.0: +cross-spawn@^6.0.0, cross-spawn@^6.0.5: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== @@ -3111,6 +3589,13 @@ debug@3.2.6: dependencies: ms "^2.1.1" +debug@^4.0.1: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + debug@^4.1.0, debug@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" @@ -3365,11 +3850,6 @@ diff@3.3.1: resolved "https://registry.yarnpkg.com/diff/-/diff-3.3.1.tgz#aa8567a6eed03c531fc89d3f711cd0e5259dec75" integrity sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww== -diff@^3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" - integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== - diffie-hellman@^5.0.0: version "5.0.3" resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" @@ -3384,6 +3864,13 @@ dirty-chai@^2.0.1: resolved "https://registry.yarnpkg.com/dirty-chai/-/dirty-chai-2.0.1.tgz#6b2162ef17f7943589da840abc96e75bda01aff3" integrity sha512-ys79pWKvDMowIDEPC6Fig8d5THiC0DJ2gmTeGzVAoEH18J8OzLud0Jh7I9IWg3NSk8x2UocznUuFmfHCXYZx9w== +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + dom-walk@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.1.tgz#672226dc74c8f799ad35307df936aba11acd6018" @@ -3453,6 +3940,11 @@ electron-to-chromium@^1.3.47: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.362.tgz#9ed33f9d0673888d6a2614347b4b63b490009408" integrity sha512-xdU5VCoZyMPMOWtCaMgbr48OwWZHrMLbGnAOlEqibXiIGsb4kiCGWEHK5NOghcVLdBVIbr/BW+yuKxVuGTtzEg== +electron-to-chromium@^1.3.723: + version "1.3.786" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.786.tgz#1fc572abc77e2f474725f8a61acf7e25ced9fbe2" + integrity sha512-AmvbLBj3hepRk8v/DHrFF8gINxOFfDbrn6Ts3PcK46/FBdQb5OMmpamSpZQXSkfi77FfBzYtQtAk+00LCLYMVw== + elliptic@6.3.3: version "6.3.3" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.3.3.tgz#5482d9646d54bcb89fd7d994fc9e2e9568876e3f" @@ -3489,6 +3981,19 @@ elliptic@6.5.3: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.0" +elliptic@6.5.4: + version "6.5.4" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" + integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + hash.js "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" + emoji-regex@^7.0.1: version "7.0.3" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" @@ -3524,11 +4029,6 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.1: dependencies: once "^1.4.0" -eol@^0.9.1: - version "0.9.1" - resolved "https://registry.yarnpkg.com/eol/-/eol-0.9.1.tgz#f701912f504074be35c6117a5c4ade49cd547acd" - integrity sha512-Ds/TEoZjwggRoz/Q2O7SE3i4Jm66mqTDfmdHdq/7DKVk3bro9Q8h6WdXKdPqFLMoqxrDK5SVRzHVPOS6uuGtrg== - errno@~0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" @@ -3560,6 +4060,28 @@ es-abstract@^1.17.0-next.1, es-abstract@^1.17.2: string.prototype.trimleft "^2.1.1" string.prototype.trimright "^2.1.1" +es-abstract@^1.18.0-next.1, es-abstract@^1.18.0-next.2: + version "1.18.3" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.3.tgz#25c4c3380a27aa203c44b2b685bba94da31b63e0" + integrity sha512-nQIr12dxV7SSxE6r6f1l3DtAeEYdsGpps13dR0TwJg1S8gyp4ZPgy3FZcHBgbiQqnoqSTb+oC+kO4UQ0C/J8vw== + dependencies: + call-bind "^1.0.2" + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + get-intrinsic "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.2" + is-callable "^1.2.3" + is-negative-zero "^2.0.1" + is-regex "^1.1.3" + is-string "^1.0.6" + object-inspect "^1.10.3" + object-keys "^1.1.1" + object.assign "^4.1.2" + string.prototype.trimend "^1.0.4" + string.prototype.trimstart "^1.0.4" + unbox-primitive "^1.0.1" + es-to-primitive@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" @@ -3605,6 +4127,11 @@ es6-weak-map@^2.0.1: es6-iterator "^2.0.3" es6-symbol "^3.1.1" +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" @@ -3615,6 +4142,11 @@ escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1 resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= +escape-string-regexp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== + escodegen@1.8.x: version "1.8.1" resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.8.1.tgz#5a5b53af4693110bebb0867aa3430dd3b70a1018" @@ -3628,9 +4160,9 @@ escodegen@1.8.x: source-map "~0.2.0" escodegen@^1.9.1: - version "1.14.1" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.1.tgz#ba01d0c8278b5e95a9a45350142026659027a457" - integrity sha512-Bmt7NcRySdIfNPfU2ZoXDrrXsG9ZjvDxcAlMfDUgRBjLOWTuIACXPBFJH7Z+cLb40JeQco5toikyc9t9P8E9SQ== + version "1.14.3" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.3.tgz#4e7b81fba61581dc97582ed78cab7f0e8d63f503" + integrity sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw== dependencies: esprima "^4.0.1" estraverse "^4.2.0" @@ -3639,6 +4171,77 @@ escodegen@^1.9.1: optionalDependencies: source-map "~0.6.1" +eslint-scope@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" + integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + +eslint-utils@^1.3.1: + version "1.4.3" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f" + integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q== + dependencies: + eslint-visitor-keys "^1.1.0" + +eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" + integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== + +eslint@^5.6.0: + version "5.16.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.16.0.tgz#a1e3ac1aae4a3fbd8296fcf8f7ab7314cbb6abea" + integrity sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg== + dependencies: + "@babel/code-frame" "^7.0.0" + ajv "^6.9.1" + chalk "^2.1.0" + cross-spawn "^6.0.5" + debug "^4.0.1" + doctrine "^3.0.0" + eslint-scope "^4.0.3" + eslint-utils "^1.3.1" + eslint-visitor-keys "^1.0.0" + espree "^5.0.1" + esquery "^1.0.1" + esutils "^2.0.2" + file-entry-cache "^5.0.1" + functional-red-black-tree "^1.0.1" + glob "^7.1.2" + globals "^11.7.0" + ignore "^4.0.6" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + inquirer "^6.2.2" + js-yaml "^3.13.0" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.3.0" + lodash "^4.17.11" + minimatch "^3.0.4" + mkdirp "^0.5.1" + natural-compare "^1.4.0" + optionator "^0.8.2" + path-is-inside "^1.0.2" + progress "^2.0.0" + regexpp "^2.0.1" + semver "^5.5.1" + strip-ansi "^4.0.0" + strip-json-comments "^2.0.1" + table "^5.2.3" + text-table "^0.2.0" + +espree@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-5.0.1.tgz#5d6526fa4fc7f0788a5cf75b15f30323e2f81f7a" + integrity sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A== + dependencies: + acorn "^6.0.7" + acorn-jsx "^5.0.0" + eslint-visitor-keys "^1.0.0" + esprima@2.7.x, esprima@^2.7.1: version "2.7.3" resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" @@ -3649,16 +4252,35 @@ esprima@^4.0.0, esprima@^4.0.1: resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== +esquery@^1.0.1: + version "1.4.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" + integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + estraverse@^1.9.1: version "1.9.3" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44" integrity sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q= -estraverse@^4.2.0: +estraverse@^4.1.1, estraverse@^4.2.0: version "4.3.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== +estraverse@^5.1.0, estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + esutils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" @@ -3709,7 +4331,7 @@ eth-json-rpc-errors@^1.0.1: dependencies: fast-safe-stringify "^2.0.6" -eth-json-rpc-errors@^2.0.1, eth-json-rpc-errors@^2.0.2: +eth-json-rpc-errors@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/eth-json-rpc-errors/-/eth-json-rpc-errors-2.0.2.tgz#c1965de0301fe941c058e928bebaba2e1285e3c4" integrity sha512-uBCRM2w2ewusRHGxN8JhcuOb2RN3ueAOYH/0BhqdFmQkZx5lj5+fLKTz0mIVOzd4FG5/kUksCzCD7eTEim6gaA== @@ -3717,16 +4339,16 @@ eth-json-rpc-errors@^2.0.1, eth-json-rpc-errors@^2.0.2: fast-safe-stringify "^2.0.6" eth-json-rpc-filters@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/eth-json-rpc-filters/-/eth-json-rpc-filters-4.1.1.tgz#15277c66790236d85f798f4d7dc6bab99a798cd2" - integrity sha512-GkXb2h6STznD+AmMzblwXgm1JMvjdK9PTIXG7BvIkTlXQ9g0QOxuU1iQRYHoslF9S30BYBSoLSisAYPdLggW+A== + version "4.2.2" + resolved "https://registry.yarnpkg.com/eth-json-rpc-filters/-/eth-json-rpc-filters-4.2.2.tgz#eb35e1dfe9357ace8a8908e7daee80b2cd60a10d" + integrity sha512-DGtqpLU7bBg63wPMWg1sCpkKCf57dJ+hj/k3zF26anXMzkmtSBDExL8IhUu7LUd34f0Zsce3PYNO2vV2GaTzaw== dependencies: - await-semaphore "^0.1.3" - eth-json-rpc-middleware "^4.1.4" + "@metamask/safe-event-emitter" "^2.0.0" + async-mutex "^0.2.6" + eth-json-rpc-middleware "^6.0.0" eth-query "^2.1.2" - json-rpc-engine "^5.1.3" - lodash.flatmap "^4.5.0" - safe-event-emitter "^1.0.1" + json-rpc-engine "^6.1.0" + pify "^5.0.0" eth-json-rpc-infura@^3.1.0: version "3.2.1" @@ -3739,14 +4361,14 @@ eth-json-rpc-infura@^3.1.0: json-rpc-error "^2.0.0" eth-json-rpc-infura@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/eth-json-rpc-infura/-/eth-json-rpc-infura-4.0.2.tgz#8af1a1a2e9a0a82aaa302bbc96fb1a4c15d69b83" - integrity sha512-dvgOrci9lZqpjpp0hoC3Zfedhg3aIpLFVDH0TdlKxRlkhR75hTrKTwxghDrQwE0bn3eKrC8RsN1m/JdnIWltpw== + version "4.1.0" + resolved "https://registry.yarnpkg.com/eth-json-rpc-infura/-/eth-json-rpc-infura-4.1.0.tgz#623478375ba65e4304dea529ed69e8bd7938270d" + integrity sha512-DFYitKovzVlCdUulEccdm4g6k/vnvyByuw7rd5OoWDBSIiaeinI8Z/SntLjSIs2c+YvE20DGwk/GLwZGCWDN1Q== dependencies: - cross-fetch "^2.1.1" - eth-json-rpc-errors "^1.0.1" - eth-json-rpc-middleware "^4.1.4" + eth-json-rpc-middleware "^4.4.0" + eth-rpc-errors "^3.0.0" json-rpc-engine "^5.1.3" + node-fetch "^2.6.0" eth-json-rpc-middleware@^1.5.0: version "1.6.0" @@ -3767,7 +4389,7 @@ eth-json-rpc-middleware@^1.5.0: promise-to-callback "^1.0.0" tape "^4.6.3" -eth-json-rpc-middleware@^4.1.4, eth-json-rpc-middleware@^4.1.5: +eth-json-rpc-middleware@^4.1.5, eth-json-rpc-middleware@^4.4.0: version "4.4.1" resolved "https://registry.yarnpkg.com/eth-json-rpc-middleware/-/eth-json-rpc-middleware-4.4.1.tgz#07d3dd0724c24a8d31e4a172ee96271da71b4228" integrity sha512-yoSuRgEYYGFdVeZg3poWOwAlRI+MoBIltmOB86MtpoZjvLbou9EB/qWMOWSmH2ryCWLW97VYY6NWsmWm3OAA7A== @@ -3787,6 +4409,23 @@ eth-json-rpc-middleware@^4.1.4, eth-json-rpc-middleware@^4.1.5: pify "^3.0.0" safe-event-emitter "^1.0.1" +eth-json-rpc-middleware@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/eth-json-rpc-middleware/-/eth-json-rpc-middleware-6.0.0.tgz#4fe16928b34231a2537856f08a5ebbc3d0c31175" + integrity sha512-qqBfLU2Uq1Ou15Wox1s+NX05S9OcAEL4JZ04VZox2NS0U+RtCMjSxzXhLFWekdShUPZ+P8ax3zCO2xcPrp6XJQ== + dependencies: + btoa "^1.2.1" + clone "^2.1.1" + eth-query "^2.1.2" + eth-rpc-errors "^3.0.0" + eth-sig-util "^1.4.2" + ethereumjs-util "^5.1.2" + json-rpc-engine "^5.3.0" + json-stable-stringify "^1.0.1" + node-fetch "^2.6.1" + pify "^3.0.0" + safe-event-emitter "^1.0.1" + eth-lib@0.2.7: version "0.2.7" resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.2.7.tgz#2f93f17b1e23aec3759cd4a3fe20c1286a3fc1ca" @@ -3825,19 +4464,33 @@ eth-query@^2.0.2, eth-query@^2.1.0, eth-query@^2.1.2: json-rpc-random-id "^1.0.0" xtend "^4.0.1" -eth-saddle@^0.1.21: - version "0.1.21" - resolved "https://registry.yarnpkg.com/eth-saddle/-/eth-saddle-0.1.21.tgz#692ac403f6f68c71f3e81336869e2259ab77d97e" - integrity sha512-XsswjrWJaQnixrQk7ycL8fOUoqqyRbkSo9TkGJrgxNNcYjtF6/wFOjxgfwxxd3FIQWLCuAF4jcO6RpFRiEAh4Q== +eth-rpc-errors@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/eth-rpc-errors/-/eth-rpc-errors-3.0.0.tgz#d7b22653c70dbf9defd4ef490fd08fe70608ca10" + integrity sha512-iPPNHPrLwUlR9xCSYm7HHQjWBasor3+KZfRvwEWxMz3ca0yqnlBeJrnyphkGIXZ4J7AMAaOLmwy4AWhnxOiLxg== + dependencies: + fast-safe-stringify "^2.0.6" + +eth-rpc-errors@^4.0.2: + version "4.0.3" + resolved "https://registry.yarnpkg.com/eth-rpc-errors/-/eth-rpc-errors-4.0.3.tgz#6ddb6190a4bf360afda82790bb7d9d5e724f423a" + integrity sha512-Z3ymjopaoft7JDoxZcEb3pwdGh7yiYMhOwm2doUt6ASXlMavpNlK6Cre0+IMl2VSGyEU9rkiperQhp5iRxn5Pg== + dependencies: + fast-safe-stringify "^2.0.6" + +eth-saddle@^0.1.25: + version "0.1.25" + resolved "https://registry.yarnpkg.com/eth-saddle/-/eth-saddle-0.1.25.tgz#8bbfefa6eabcdaca0c88e838fa60213e9fff9d8b" + integrity sha512-BUames0/ap3Cm7bJVjp0sFfTxKUv+xK+zbwZLYQghky9KrfowlURqBZgJHPxF3w9HyCh95UQBY5QsIeed1Ppqw== dependencies: - "@0x/subproviders" "^6.0.0" - "@compound-finance/sol-coverage" "^4.0.10-alpha.7" - "@compound-finance/sol-tracing-utils" "7.1.0-alpha.7" + "@0x/subproviders" "=6.0.0" + "@compound-finance/sol-coverage" "=4.0.10-alpha.7" + "@compound-finance/sol-tracing-utils" "=7.1.0-alpha.7" "@types/jest" "^24.0.15" ethereumjs-tx "2.1.2" ethereumjs-util "5.2.0" fast-glob "^3.2.2" - ganache-core "^2.10.2" + ganache-core "^2.13.2" jest "^24.9.0" jest-cli "^24.9.0" jest-diff "^25.3.0" @@ -3911,12 +4564,33 @@ ethereum-common@^0.0.18: resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.0.18.tgz#2fdc3576f232903358976eb39da783213ff9523f" integrity sha1-L9w1dvIykDNYl26znaeDIT/5Uj8= -ethereum-types@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/ethereum-types/-/ethereum-types-3.1.0.tgz#76de33b398b5b5375e08e647c92ac00e87a647d9" - integrity sha512-E4lBfxzRSFjd2OM+BATc0b3nN+xWVpAQhBCwSNS9kbsXVPV2LNhIduwCR8Poc8seQukFfuXp0QoVXOlQbUS2pQ== +ethereum-cryptography@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz#8d6143cfc3d74bf79bbd8edecdf29e4ae20dd191" + integrity sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ== dependencies: - "@types/node" "*" + "@types/pbkdf2" "^3.0.0" + "@types/secp256k1" "^4.0.1" + blakejs "^1.1.0" + browserify-aes "^1.2.0" + bs58check "^2.1.2" + create-hash "^1.2.0" + create-hmac "^1.1.7" + hash.js "^1.1.7" + keccak "^3.0.0" + pbkdf2 "^3.0.17" + randombytes "^2.1.0" + safe-buffer "^5.1.2" + scrypt-js "^3.0.0" + secp256k1 "^4.0.1" + setimmediate "^1.0.5" + +ethereum-types@^3.0.0, ethereum-types@^3.3.3, ethereum-types@^3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/ethereum-types/-/ethereum-types-3.5.0.tgz#27393f0d86f55bb1dcbff8a6af55a39c1f751c0d" + integrity sha512-vTGJl45DxOK21w3rzlqV8KrfcdIJC+4ZqxFkjNf1aw2GBMXZy2MxiibUqBth2M823d98WgOuFpVHobOfa7ejDw== + dependencies: + "@types/node" "12.12.54" bignumber.js "~9.0.0" ethereum-types@^3.2.0: @@ -4064,6 +4738,18 @@ ethereumjs-util@^4.0.1, ethereumjs-util@^4.3.0: rlp "^2.0.0" secp256k1 "^3.0.1" +ethereumjs-util@^7.0.10, ethereumjs-util@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.0.tgz#e2b43a30bfcdbcb432a4eb42bd5f2393209b3fd5" + integrity sha512-kR+vhu++mUDARrsMMhsjjzPduRVAeundLGXucGRHF3B4oEltOUspfgCVco4kckucj3FMlLaZHUl9n7/kdmr6Tw== + dependencies: + "@types/bn.js" "^5.1.0" + bn.js "^5.1.2" + create-hash "^1.1.2" + ethereum-cryptography "^0.1.3" + ethjs-util "0.1.6" + rlp "^2.2.4" + ethereumjs-util@~6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-6.1.0.tgz#e9c51e5549e8ebd757a339cc00f5380507e799c8" @@ -4231,18 +4917,16 @@ execa@^1.0.0: signal-exit "^3.0.0" strip-eof "^1.0.0" +exit-on-epipe@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz#0bdd92e87d5285d267daa8171d0eb06159689692" + integrity sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw== + exit@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw= -expand-brackets@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" - integrity sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s= - dependencies: - is-posix-bracket "^0.1.0" - expand-brackets@^2.1.4: version "2.1.4" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" @@ -4256,13 +4940,6 @@ expand-brackets@^2.1.4: snapdragon "^0.8.1" to-regex "^3.0.1" -expand-range@^1.8.1: - version "1.8.2" - resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" - integrity sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc= - dependencies: - fill-range "^2.1.0" - expand-template@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c" @@ -4350,12 +5027,14 @@ extend@^3.0.0, extend@~3.0.2: resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== -extglob@^0.3.1: - version "0.3.2" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" - integrity sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE= +external-editor@^3.0.3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" + integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== dependencies: - is-extglob "^1.0.0" + chardet "^0.7.0" + iconv-lite "^0.4.24" + tmp "^0.0.33" extglob@^2.0.4: version "2.0.4" @@ -4398,27 +5077,26 @@ fancy-log@^1.3.2: parse-node-version "^1.0.0" time-stamp "^1.0.0" -fast-deep-equal@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" - integrity sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ= - fast-deep-equal@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz#545145077c501491e33b15ec408c294376e94ae4" integrity sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA== +fast-diff@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" + integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== + fast-glob@^3.2.2: - version "3.2.2" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.2.tgz#ade1a9d91148965d4bf7c51f72e1ca662d32e63d" - integrity sha512-UDV82o4uQyljznxwMxyVRJgZZt3O5wENYojjzbaGEGZgeOxkLFf+V4cnUD+krzb2F72E18RhamkMZ7AdeggF7A== + version "3.2.7" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.7.tgz#fd6cb7a2d7e9aa7a7846111e85a196d6b2f766a1" + integrity sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q== dependencies: "@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.walk" "^1.2.3" - glob-parent "^5.1.0" + glob-parent "^5.1.2" merge2 "^1.3.0" - micromatch "^4.0.2" - picomatch "^2.2.1" + micromatch "^4.0.4" fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0: version "2.1.0" @@ -4431,9 +5109,9 @@ fast-levenshtein@~2.0.6: integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= fast-safe-stringify@^2.0.6: - version "2.0.7" - resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz#124aa885899261f68aedb42a7c080de9da608743" - integrity sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA== + version "2.0.8" + resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.0.8.tgz#dc2af48c46cf712b683e849b2bbd446b32de936f" + integrity sha512-lXatBjf3WPjmWD6DpIZxkeSsCOwqI0maYMpgDlx8g4U2qi4lbjA9oH/HD2a87G+KfsUmo5WbJFmqBZlPxtptag== fastq@^1.6.0: version "1.7.0" @@ -4463,6 +5141,20 @@ fetch-ponyfill@^4.0.0: dependencies: node-fetch "~1.7.1" +figures@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" + integrity sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA== + dependencies: + escape-string-regexp "^1.0.5" + +file-entry-cache@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" + integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== + dependencies: + flat-cache "^2.0.1" + file-type@^3.8.0: version "3.9.0" resolved "https://registry.yarnpkg.com/file-type/-/file-type-3.9.0.tgz#257a078384d1db8087bc449d107d52a52672b9e9" @@ -4483,22 +5175,6 @@ file-uri-to-path@1.0.0: resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== -filename-regex@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" - integrity sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY= - -fill-range@^2.1.0: - version "2.2.4" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.4.tgz#eb1e773abb056dcd8df2bfdf6af59b8b3a936565" - integrity sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q== - dependencies: - is-number "^2.1.0" - isobject "^2.0.0" - randomatic "^3.0.0" - repeat-element "^1.1.2" - repeat-string "^1.5.2" - fill-range@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" @@ -4587,6 +5263,20 @@ flagged-respawn@^1.0.0: resolved "https://registry.yarnpkg.com/flagged-respawn/-/flagged-respawn-1.0.1.tgz#e7de6f1279ddd9ca9aac8a5971d618606b3aab41" integrity sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q== +flat-cache@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" + integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== + dependencies: + flatted "^2.0.0" + rimraf "2.6.3" + write "1.0.3" + +flatted@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" + integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== + flow-stoplight@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/flow-stoplight/-/flow-stoplight-1.0.0.tgz#4a292c5bcff8b39fa6cc0cb1a853d86f27eeff7b" @@ -4612,13 +5302,6 @@ for-in@^1.0.1, for-in@^1.0.2: resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= -for-own@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" - integrity sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4= - dependencies: - for-in "^1.0.1" - for-own@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/for-own/-/for-own-1.0.0.tgz#c63332f415cedc4b04dbfe70cf836494c53cb44b" @@ -4626,6 +5309,11 @@ for-own@^1.0.0: dependencies: for-in "^1.0.1" +foreach@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" + integrity sha1-C+4AUBiusmDQo6865ljdATbsG5k= + forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" @@ -4702,7 +5390,7 @@ fs.realpath@^1.0.0: resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= -fsevents@^1.0.0, fsevents@^1.2.7: +fsevents@^1.2.7: version "1.2.11" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.11.tgz#67bf57f4758f02ede88fb2a1712fef4d15358be3" integrity sha512-+ux3lx6peh0BpvY0JebGyZoiR4D+oYzdPZMKJwkZ+sFkNJzpL7tXc/wehS49gUAxg3tmMHPHZkA8JU2rhhgDHw== @@ -4725,7 +5413,7 @@ functional-red-black-tree@^1.0.1, functional-red-black-tree@~1.0.1: resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= -ganache-core@^2.10.2, ganache-core@^2.9.0-istanbul.0, "ganache-core@github:compound-finance/ganache-core.git#jflatow/unbreak-fork": +ganache-core@^2.10.2, ganache-core@^2.13.2, ganache-core@^2.6.0, "ganache-core@github:compound-finance/ganache-core.git#jflatow/unbreak-fork": version "2.10.2" resolved "https://codeload.github.com/compound-finance/ganache-core/tar.gz/4c7e063f6d423e1b3850f4cb328029e819670a64" dependencies: @@ -4792,6 +5480,15 @@ get-func-name@^2.0.0: resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE= +get-intrinsic@^1.0.2, get-intrinsic@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" + integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + get-stream@^2.2.0: version "2.3.1" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-2.3.1.tgz#5f38f93f346009666ee0150a054167f91bdd95de" @@ -4836,21 +5533,6 @@ github-from-package@0.0.0: resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce" integrity sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4= -glob-base@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" - integrity sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q= - dependencies: - glob-parent "^2.0.0" - is-glob "^2.0.0" - -glob-parent@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" - integrity sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg= - dependencies: - is-glob "^2.0.0" - glob-parent@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" @@ -4859,10 +5541,10 @@ glob-parent@^3.1.0: is-glob "^3.1.0" path-dirname "^1.0.0" -glob-parent@^5.1.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" - integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== +glob-parent@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== dependencies: is-glob "^4.0.1" @@ -4964,7 +5646,7 @@ global@~4.3.0: min-document "^2.19.0" process "~0.5.1" -globals@^11.1.0: +globals@^11.1.0, globals@^11.7.0: version "11.12.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== @@ -5018,11 +5700,16 @@ got@^7.1.0: url-parse-lax "^1.0.0" url-to-options "^1.0.1" -graceful-fs@^4.0.0, graceful-fs@^4.1.10, graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9: +graceful-fs@^4.0.0, graceful-fs@^4.1.10, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9: version "4.2.3" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== +graceful-fs@^4.1.15: + version "4.2.6" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee" + integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ== + "graceful-readlink@>= 1.0.0": version "1.0.1" resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" @@ -5110,6 +5797,11 @@ has-ansi@^2.0.0: dependencies: ansi-regex "^2.0.0" +has-bigints@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113" + integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA== + has-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" @@ -5140,6 +5832,11 @@ has-symbols@^1.0.0, has-symbols@^1.0.1: resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== +has-symbols@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423" + integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== + has-to-string-tag-x@^1.2.0: version "1.4.1" resolved "https://registry.yarnpkg.com/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz#a045ab383d7b4b2012a00148ab0aa5f290044d4d" @@ -5206,7 +5903,7 @@ hash.js@1.1.3: inherits "^2.0.3" minimalistic-assert "^1.0.0" -hash.js@^1.0.0, hash.js@^1.0.3: +hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3, hash.js@^1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== @@ -5241,7 +5938,7 @@ heap@0.2.6: resolved "https://registry.yarnpkg.com/heap/-/heap-0.2.6.tgz#087e1f10b046932fc8594dd9e6d378afc9d1e5ac" integrity sha1-CH4fELBGky/IWU3Z5tN4r8nR5aw= -hmac-drbg@^1.0.0: +hmac-drbg@^1.0.0, hmac-drbg@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= @@ -5323,7 +6020,7 @@ http-signature@~1.2.0: jsprim "^1.2.2" sshpk "^1.7.0" -iconv-lite@0.4.24, iconv-lite@~0.4.13: +iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@~0.4.13: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -5342,11 +6039,32 @@ ieee754@^1.1.4: resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg== +ignore@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" + integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== + immediate@^3.2.3, immediate@~3.2.3: version "3.2.3" resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.2.3.tgz#d140fa8f614659bd6541233097ddaac25cdd991c" integrity sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw= +import-fresh@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" + integrity sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg== + dependencies: + caller-path "^2.0.0" + resolve-from "^3.0.0" + +import-fresh@^3.0.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + import-local@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d" @@ -5383,6 +6101,25 @@ ini@^1.3.4, ini@~1.3.0: resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== +inquirer@^6.2.2: + version "6.5.2" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.2.tgz#ad50942375d036d327ff528c08bd5fab089928ca" + integrity sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ== + dependencies: + ansi-escapes "^3.2.0" + chalk "^2.4.2" + cli-cursor "^2.1.0" + cli-width "^2.0.0" + external-editor "^3.0.3" + figures "^2.0.0" + lodash "^4.17.12" + mute-stream "0.0.7" + run-async "^2.2.0" + rxjs "^6.4.0" + string-width "^2.1.0" + strip-ansi "^5.1.0" + through "^2.3.6" + interpret@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296" @@ -5437,6 +6174,11 @@ is-arrayish@^0.2.1: resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= +is-bigint@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.2.tgz#ffb381442503235ad245ea89e45b3dbff040ee5a" + integrity sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA== + is-binary-path@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" @@ -5451,6 +6193,13 @@ is-binary-path@~2.1.0: dependencies: binary-extensions "^2.0.0" +is-boolean-object@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.1.tgz#3c0878f035cb821228d350d2e1e36719716a3de8" + integrity sha512-bXdQWkECBUIAcCkeH1unwJLIpZYaa5VvuygSyS/c2lf719mTKZDU5UdDRlpd01UjADgmW8RfqaP+mRaVPdr/Ng== + dependencies: + call-bind "^1.0.2" + is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" @@ -5461,6 +6210,11 @@ is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.1.5: resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab" integrity sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q== +is-callable@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.3.tgz#8b1e0500b73a1d76c70487636f368e519de8db8e" + integrity sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ== + is-ci@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" @@ -5468,6 +6222,13 @@ is-ci@^2.0.0: dependencies: ci-info "^2.0.0" +is-core-module@^2.2.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.5.0.tgz#f754843617c70bfd29b7bd87327400cda5c18491" + integrity sha512-TXCMSDsEHMEEZ6eCA8rwRDbLu55MRGmrctljsBX/2v1d9/GzqHOxW5c5oPSgrUt2vBFXebu9rGqckXGPWOlYpg== + dependencies: + has "^1.0.3" + is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" @@ -5505,17 +6266,10 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2: is-data-descriptor "^1.0.0" kind-of "^6.0.2" -is-dotfile@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" - integrity sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE= - -is-equal-shallow@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" - integrity sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ= - dependencies: - is-primitive "^2.0.0" +is-directory@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" + integrity sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw== is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" @@ -5529,11 +6283,6 @@ is-extendable@^1.0.1: dependencies: is-plain-object "^2.0.4" -is-extglob@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" - integrity sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA= - is-extglob@^2.1.0, is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" @@ -5571,12 +6320,10 @@ is-generator-fn@^2.0.0: resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== -is-glob@^2.0.0, is-glob@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" - integrity sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM= - dependencies: - is-extglob "^1.0.0" +is-generator-function@^1.0.7: + version "1.0.9" + resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.9.tgz#e5f82c2323673e7fcad3d12858c83c4039f6399c" + integrity sha512-ZJ34p1uvIfptHCN7sFTjGibB9/oBg17sHqzDLfuwhvmN/qLVvIQXRQ8licZQ35WJ8KuEQt/etnnzQFI9C9Ue/A== is-glob@^3.1.0: version "3.1.0" @@ -5607,12 +6354,15 @@ is-negated-glob@^1.0.0: resolved "https://registry.yarnpkg.com/is-negated-glob/-/is-negated-glob-1.0.0.tgz#6910bca5da8c95e784b5751b976cf5a10fee36d2" integrity sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI= -is-number@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" - integrity sha1-Afy7s5NGOlSPL0ZszhbezknbkI8= - dependencies: - kind-of "^3.0.2" +is-negative-zero@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24" + integrity sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w== + +is-number-object@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.5.tgz#6edfaeed7950cff19afedce9fbfca9ee6dd289eb" + integrity sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw== is-number@^3.0.0: version "3.0.0" @@ -5648,16 +6398,6 @@ is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: dependencies: isobject "^3.0.1" -is-posix-bracket@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" - integrity sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q= - -is-primitive@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" - integrity sha1-IHurkWOEmcB7Kt8kCkGochADRXU= - is-regex@^1.0.4, is-regex@^1.0.5, is-regex@~1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.5.tgz#39d589a358bf18967f726967120b8fc1aed74eae" @@ -5665,6 +6405,14 @@ is-regex@^1.0.4, is-regex@^1.0.5, is-regex@~1.0.5: dependencies: has "^1.0.3" +is-regex@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.3.tgz#d029f9aff6448b93ebbe3f33dac71511fdcbef9f" + integrity sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ== + dependencies: + call-bind "^1.0.2" + has-symbols "^1.0.2" + is-relative@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-1.0.0.tgz#a1bb6935ce8c5dba1e8b9754b9b2dcc020e2260d" @@ -5682,6 +6430,11 @@ is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0: resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= +is-string@^1.0.5, is-string@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.6.tgz#3fe5d5992fb0d93404f32584d4b0179a71b54a5f" + integrity sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w== + is-symbol@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937" @@ -5689,6 +6442,24 @@ is-symbol@^1.0.2: dependencies: has-symbols "^1.0.1" +is-symbol@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" + integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== + dependencies: + has-symbols "^1.0.2" + +is-typed-array@^1.1.3: + version "1.1.5" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.5.tgz#f32e6e096455e329eb7b423862456aa213f0eb4e" + integrity sha512-S+GRDgJlR3PyEbsX/Fobd9cqpZBuvUS+8asRqYDMLCb2qMzt1oz5m5oxQCxOgUDxiWsOVNi4yaF+/uvdlHlYug== + dependencies: + available-typed-arrays "^1.0.2" + call-bind "^1.0.2" + es-abstract "^1.18.0-next.2" + foreach "^2.0.5" + has-symbols "^1.0.1" + is-typedarray@^1.0.0, is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" @@ -5896,14 +6667,14 @@ jest-diff@^24.3.0, jest-diff@^24.9.0: pretty-format "^24.9.0" jest-diff@^25.3.0: - version "25.3.0" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-25.3.0.tgz#0d7d6f5d6171e5dacde9e05be47b3615e147c26f" - integrity sha512-vyvs6RPoVdiwARwY4kqFWd4PirPLm2dmmkNzKqo38uZOzJvLee87yzDjIZLmY1SjM3XR5DwsUH+cdQ12vgqi1w== + version "25.5.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-25.5.0.tgz#1dd26ed64f96667c068cef026b677dfa01afcfa9" + integrity sha512-z1kygetuPiREYdNIumRpAHY6RXiGmp70YHptjdaxTWGmA085W3iCnXNx0DhflK3vwrKmrRWyY1wUpkPMVxMK7A== dependencies: chalk "^3.0.0" diff-sequences "^25.2.6" jest-get-type "^25.2.6" - pretty-format "^25.3.0" + pretty-format "^25.5.0" jest-diff@^26.4.2: version "26.4.2" @@ -6072,9 +6843,9 @@ jest-mock@^24.9.0: "@jest/types" "^24.9.0" jest-pnp-resolver@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.1.tgz#ecdae604c077a7fbc70defb6d517c3c1c898923a" - integrity sha512-pgFw2tm54fzgYvc/OHrnysABEObZCUNFnhjoRjaVOCN8NYc032/gVjPaHD4Aq6ApkSieWtfKAFQtmDKAmhupnQ== + version "1.2.2" + resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz#b704ac0ae028a89108a4d040b3f919dfddc8e33c" + integrity sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w== jest-regex-util@^24.3.0, jest-regex-util@^24.9.0: version "24.9.0" @@ -6258,11 +7029,6 @@ js-sha3@^0.7.0: resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.7.0.tgz#0a5c57b36f79882573b2d84051f8bb85dd1bd63a" integrity sha512-Wpks3yBDm0UcL5qlVhwW9Jr9n9i4FfeWBFOOXP5puDS/SiudJGhw7DPyBqn3487qD4F0lsC0q3zxink37f7zeA== -js-string-escape@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef" - integrity sha1-4mJbrbwNZ8dTPp7cEGjFh65BN+8= - "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -6281,6 +7047,14 @@ js-yaml@3.x: argparse "^1.0.7" esprima "^4.0.0" +js-yaml@^3.12.0, js-yaml@^3.13.0, js-yaml@^3.13.1: + version "3.14.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" @@ -6355,16 +7129,22 @@ json-rpc-engine@^3.4.0, json-rpc-engine@^3.6.0: promise-to-callback "^1.0.0" safe-event-emitter "^1.0.1" -json-rpc-engine@^5.1.3: - version "5.1.8" - resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-5.1.8.tgz#5ba0147ce571899bbaa7133ffbc05317c34a3c7f" - integrity sha512-vTBSDEPJV1fPAsbm2g5sEuPjsgLdiab2f1CTn2PyRr8nxggUpA996PDlNQDsM0gnrA99F8KIBLq2nIKrOFl1Mg== +json-rpc-engine@^5.1.3, json-rpc-engine@^5.3.0: + version "5.4.0" + resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-5.4.0.tgz#75758609d849e1dba1e09021ae473f3ab63161e5" + integrity sha512-rAffKbPoNDjuRnXkecTjnsE3xLLrb00rEkdgalINhaYVYIxDwWtvYBr9UFbhTvPB1B2qUOLoFd/cV6f4Q7mh7g== dependencies: - async "^2.0.1" - eth-json-rpc-errors "^2.0.1" - promise-to-callback "^1.0.0" + eth-rpc-errors "^3.0.0" safe-event-emitter "^1.0.1" +json-rpc-engine@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-6.1.0.tgz#bf5ff7d029e1c1bf20cb6c0e9f348dcd8be5a393" + integrity sha512-NEdLrtrq1jUZyfjkr9OCz9EzCNhnRyWtt1PAnvnhwy6e8XETS0Dtc+ZNCO2gvuAoKsIn2+vCSowXTYE4CkgnAQ== + dependencies: + "@metamask/safe-event-emitter" "^2.0.0" + eth-rpc-errors "^4.0.2" + json-rpc-error@2.0.0, json-rpc-error@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/json-rpc-error/-/json-rpc-error-2.0.0.tgz#a7af9c202838b5e905c7250e547f1aff77258a02" @@ -6377,11 +7157,6 @@ json-rpc-random-id@^1.0.0, json-rpc-random-id@^1.0.1: resolved "https://registry.yarnpkg.com/json-rpc-random-id/-/json-rpc-random-id-1.0.1.tgz#ba49d96aded1444dbb8da3d203748acbbcdec8c8" integrity sha1-uknZat7RRE27jaPSA3SKy7zeyMg= -json-schema-traverse@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" - integrity sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A= - json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" @@ -6480,6 +7255,14 @@ keccak@^2.0.0: nan "^2.14.0" safe-buffer "^5.2.0" +keccak@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.1.tgz#ae30a0e94dbe43414f741375cff6d64c8bea0bff" + integrity sha512-epq90L9jlFWCW7+pQa6JOnKn2Xgl2mtI664seYR6MHskvI9agt7AnDqmAlp9TqU4/caMYbA08Hi5DMZAl5zdkA== + dependencies: + node-addon-api "^2.0.0" + node-gyp-build "^4.2.0" + keccakjs@^0.2.0: version "0.2.3" resolved "https://registry.yarnpkg.com/keccakjs/-/keccakjs-0.2.3.tgz#5e4e969ce39689a3861f445d7752ee3477f9fe72" @@ -6699,7 +7482,7 @@ leven@^3.1.0: resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== -levn@~0.3.0: +levn@^0.3.0, levn@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= @@ -6758,10 +7541,10 @@ locate-path@^3.0.0: p-locate "^3.0.0" path-exists "^3.0.0" -lodash.flatmap@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.flatmap/-/lodash.flatmap-4.5.0.tgz#ef8cbf408f6e48268663345305c6acc0b778702e" - integrity sha1-74y/QI9uSCaGYzRTBcaswLd4cC4= +lodash.debounce@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" + integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= lodash.memoize@4.x: version "4.1.2" @@ -6783,11 +7566,16 @@ lodash@4.17.14: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.14.tgz#9ce487ae66c96254fe20b599f21b6816028078ba" integrity sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw== -lodash@^4.14.2, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.4: +lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.4: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== +lodash@^4.17.12, lodash@^4.17.19: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + loglevel@^1.6.1: version "1.6.7" resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.7.tgz#b3e034233188c68b889f5b862415306f565e2c56" @@ -6908,11 +7696,6 @@ matchdep@^2.0.0: resolve "^1.4.0" stack-trace "0.0.10" -math-random@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.4.tgz#5dd6943c938548267016d4e34f057583080c514c" - integrity sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A== - md5.js@^1.3.4: version "1.3.5" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" @@ -6997,25 +7780,6 @@ methods@~1.1.2: resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= -micromatch@^2.1.5: - version "2.3.11" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" - integrity sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU= - dependencies: - arr-diff "^2.0.0" - array-unique "^0.2.1" - braces "^1.8.2" - expand-brackets "^0.1.4" - extglob "^0.3.1" - filename-regex "^2.0.0" - is-extglob "^1.0.0" - is-glob "^2.0.1" - kind-of "^3.0.2" - normalize-path "^2.0.1" - object.omit "^2.0.0" - parse-glob "^3.0.4" - regex-cache "^0.4.2" - micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" @@ -7035,13 +7799,13 @@ micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4: snapdragon "^0.8.1" to-regex "^3.0.2" -micromatch@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259" - integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q== +micromatch@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" + integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== dependencies: braces "^3.0.1" - picomatch "^2.0.5" + picomatch "^2.2.3" miller-rabin@^4.0.0: version "4.0.1" @@ -7117,6 +7881,11 @@ minimist@^1.1.1, minimist@^1.2.0, minimist@~1.2.0: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= +minimist@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" + integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + minimist@~0.0.1: version "0.0.10" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" @@ -7157,13 +7926,20 @@ mkdirp@*: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.3.tgz#4cf2e30ad45959dddea53ad97d518b6c8205e1ea" integrity sha512-6uCP4Qc0sWsgMLy1EOqqS/3rjDHOEnsStVr/4vtAIK2Y5i2kA7lFFejYrpIyiN9w0pYf4ckeCYT9f1r1P9KX5g== -mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@0.x, mkdirp@^0.5.0, mkdirp@^0.5.1: +mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@^0.5.0, mkdirp@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= dependencies: minimist "0.0.8" +mkdirp@0.x: + version "0.5.5" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" + integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== + dependencies: + minimist "^1.2.5" + mkdirp@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" @@ -7200,7 +7976,7 @@ ms@2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== -ms@^2.1.1: +ms@2.1.2, ms@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== @@ -7250,6 +8026,11 @@ mute-stdout@^1.0.0: resolved "https://registry.yarnpkg.com/mute-stdout/-/mute-stdout-1.0.1.tgz#acb0300eb4de23a7ddeec014e3e96044b3472331" integrity sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg== +mute-stream@0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" + integrity sha512-r65nCZhrbXXb6dXOACihYApHw2Q6pV0M3V0PSxd74N0+D8nzAdEAITq2oAjA1jVnKI+tGvEBUpqiMh0+rW6zDQ== + nan@2.13.2: version "2.13.2" resolved "https://registry.yarnpkg.com/nan/-/nan-2.13.2.tgz#f51dc7ae66ba7d5d55e1e6d4d8092e802c9aefe7" @@ -7319,6 +8100,11 @@ node-abi@^2.7.0: dependencies: semver "^5.4.1" +node-addon-api@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" + integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA== + node-fetch@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.1.2.tgz#ab884e8e7e57e38a944753cec706f788d1768bb5" @@ -7332,6 +8118,16 @@ node-fetch@^1.0.1, node-fetch@~1.7.1: encoding "^0.1.11" is-stream "^1.0.1" +node-fetch@^2.6.0, node-fetch@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" + integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== + +node-gyp-build@^4.2.0: + version "4.2.3" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.2.3.tgz#ce6277f853835f718829efb47db20f3e4d9c4739" + integrity sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg== + node-hid@^0.7.9: version "0.7.9" resolved "https://registry.yarnpkg.com/node-hid/-/node-hid-0.7.9.tgz#cc0cdf1418a286a7667f0b63642b5eeb544ccd05" @@ -7352,9 +8148,9 @@ node-modules-regexp@^1.0.0: integrity sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA= node-notifier@^5.4.2: - version "5.4.3" - resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-5.4.3.tgz#cb72daf94c93904098e28b9c590fd866e464bd50" - integrity sha512-M4UBGcs4jeOK9CjTsYwkvH6/MzuUmGCyTW+kCY7uO+1ZVr0+FHGdPdIf5CCLqAaxnRrWidyoQlNkMIIVwbKB8Q== + version "5.4.5" + resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-5.4.5.tgz#0cbc1a2b0f658493b4025775a13ad938e96091ef" + integrity sha512-tVbHs7DyTLtzOiN78izLA85zRqB9NvEXkAf014Vx3jtSvn/xBl6bR8ZYifj+dFcFrKI21huSQgJZ6ZtL3B4HfQ== dependencies: growly "^1.3.0" is-wsl "^1.1.0" @@ -7362,6 +8158,11 @@ node-notifier@^5.4.2: shellwords "^0.1.1" which "^1.3.0" +node-releases@^1.1.71: + version "1.1.73" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.73.tgz#dd4e81ddd5277ff846b80b52bb40c49edf7a7b20" + integrity sha512-uW7fodD6pyW2FZNZnp/Z3hvWKeEW1Y8R1+1CnErE8cXFXzl5blBOoVB41CvMer6P6Q0S5FXDwcHgFd1Wj0U9zg== + noop-logger@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/noop-logger/-/noop-logger-0.1.1.tgz#94a2b1633c4f1317553007d8966fd0e841b6a4c2" @@ -7384,7 +8185,7 @@ normalize-package-data@^2.3.2: semver "2 || 3 || 4 || 5" validate-npm-package-license "^3.0.1" -normalize-path@^2.0.0, normalize-path@^2.0.1, normalize-path@^2.1.1: +normalize-path@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= @@ -7462,6 +8263,11 @@ object-copy@^0.1.0: define-property "^0.2.5" kind-of "^3.0.3" +object-inspect@^1.10.3: + version "1.11.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.11.0.tgz#9dceb146cedd4148a0d9e51ab88d34cf509922b1" + integrity sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg== + object-inspect@^1.7.0, object-inspect@~1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67" @@ -7499,6 +8305,16 @@ object.assign@^4.0.4, object.assign@^4.1.0: has-symbols "^1.0.0" object-keys "^1.0.11" +object.assign@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" + integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + has-symbols "^1.0.1" + object-keys "^1.1.1" + object.defaults@^1.0.0, object.defaults@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/object.defaults/-/object.defaults-1.1.0.tgz#3a7f868334b407dea06da16d88d5cd29e435fecf" @@ -7525,14 +8341,6 @@ object.map@^1.0.0: for-own "^1.0.0" make-iterator "^1.0.0" -object.omit@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" - integrity sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo= - dependencies: - for-own "^0.1.4" - is-extendable "^0.1.1" - object.pick@^1.2.0, object.pick@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" @@ -7555,6 +8363,13 @@ oboe@2.1.4: dependencies: http-https "^1.0.0" +oboe@2.1.5: + version "2.1.5" + resolved "https://registry.yarnpkg.com/oboe/-/oboe-2.1.5.tgz#5554284c543a2266d7a38f17e073821fbde393cd" + integrity sha1-VVQoTFQ6ImbXo48X4HOCH73jk80= + dependencies: + http-https "^1.0.0" + on-finished@~2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" @@ -7569,6 +8384,13 @@ once@1.x, once@^1.3.0, once@^1.3.1, once@^1.3.2, once@^1.4.0: dependencies: wrappy "1" +onetime@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" + integrity sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ== + dependencies: + mimic-fn "^1.0.0" + optimist@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" @@ -7577,7 +8399,7 @@ optimist@^0.6.1: minimist "~0.0.1" wordwrap "~0.0.2" -optionator@^0.8.1: +optionator@^0.8.1, optionator@^0.8.2: version "0.8.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== @@ -7652,9 +8474,9 @@ p-limit@^1.1.0: p-try "^1.0.0" p-limit@^2.0.0: - version "2.2.2" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.2.tgz#61279b67721f5287aa1c13a9a7fbbc48c9291b1e" - integrity sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ== + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== dependencies: p-try "^2.0.0" @@ -7694,6 +8516,13 @@ p-try@^2.0.0: resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + parse-asn1@^5.0.0: version "5.1.5" resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.5.tgz#003271343da58dc94cace494faef3d2147ecea0e" @@ -7715,16 +8544,6 @@ parse-filepath@^1.0.1: map-cache "^0.2.0" path-root "^0.1.1" -parse-glob@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" - integrity sha1-ssN2z7EfNVE7rdFz7wu246OIORw= - dependencies: - glob-base "^0.3.0" - is-dotfile "^1.0.0" - is-extglob "^1.0.0" - is-glob "^2.0.0" - parse-headers@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.3.tgz#5e8e7512383d140ba02f0c7aa9f49b4399c92515" @@ -7792,6 +8611,11 @@ path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= +path-is-inside@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + integrity sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w== + path-key@^2.0.0, path-key@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" @@ -7840,6 +8664,17 @@ pathval@^1.1.0: resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0" integrity sha1-uULm1L3mUwBe9rcTYd74cn0GReA= +pbkdf2@^3.0.17: + version "3.1.2" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" + integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== + dependencies: + create-hash "^1.1.2" + create-hmac "^1.1.4" + ripemd160 "^2.0.1" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + pbkdf2@^3.0.3, pbkdf2@^3.0.9: version "3.0.17" resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.17.tgz#976c206530617b14ebb32114239f7b09336e93a6" @@ -7871,10 +8706,10 @@ picomatch@^2.0.4, picomatch@^2.0.7: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.1.tgz#21bac888b6ed8601f831ce7816e335bc779f0a4a" integrity sha512-ISBaA8xQNmwELC7eOjqFKMESB2VIqt4PPDD0nsS95b/9dZXvVKOlz9keMSnoGGKcOHXfTvDD6WMaRoSc9UuhRA== -picomatch@^2.0.5, picomatch@^2.2.1: - version "2.2.2" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" - integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== +picomatch@^2.2.3: + version "2.3.0" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" + integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw== pify@^2.0.0, pify@^2.3.0: version "2.3.0" @@ -7891,6 +8726,11 @@ pify@^4.0.1: resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== +pify@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-5.0.0.tgz#1f5eca3f5e87ebec28cc6d54a0e4aaf00acc127f" + integrity sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA== + pinkie-promise@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" @@ -7978,10 +8818,10 @@ prepend-http@^2.0.0: resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= -preserve@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" - integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks= +prettier@^1.14.3, prettier@^1.19.0: + version "1.19.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb" + integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew== pretty-format@^24.9.0: version "24.9.0" @@ -7993,12 +8833,12 @@ pretty-format@^24.9.0: ansi-styles "^3.2.0" react-is "^16.8.4" -pretty-format@^25.3.0: - version "25.3.0" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-25.3.0.tgz#d0a4f988ff4a6cd350342fdabbb809aeb4d49ad5" - integrity sha512-wToHwF8bkQknIcFkBqNfKu4+UZqnrLn/Vr+wwKQwwvPzkBfDDKp/qIabFqdgtoi5PEnM8LFByVsOrHoa3SpTVA== +pretty-format@^25.5.0: + version "25.5.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-25.5.0.tgz#7873c1d774f682c34b8d48b6743a2bf2ac55791a" + integrity sha512-kbo/kq2LQ/A/is0PQwsEHM7Ca6//bGPPvU6UnsdDRSKTWxT/ru/xb88v4BJf6a69H+uTytOEsTusT9ksd/1iWQ== dependencies: - "@jest/types" "^25.3.0" + "@jest/types" "^25.5.0" ansi-regex "^5.0.0" ansi-styles "^4.0.0" react-is "^16.12.0" @@ -8018,6 +8858,11 @@ pretty-hrtime@^1.0.0: resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1" integrity sha1-t+PqQkNaTJsnWdmeDyAesZWALuE= +printj@~1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/printj/-/printj-1.1.2.tgz#d90deb2975a8b9f600fb3a1c94e3f4c53c78a222" + integrity sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ== + private@^0.1.6, private@^0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" @@ -8033,6 +8878,11 @@ process@~0.5.1: resolved "https://registry.yarnpkg.com/process/-/process-0.5.2.tgz#1638d8a8e34c2f440a91db95ab9aeb677fc185cf" integrity sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8= +progress@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" + integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== + promise-to-callback@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/promise-to-callback/-/promise-to-callback-1.0.0.tgz#5d2a749010bfb67d963598fcd3960746a68feef7" @@ -8186,15 +9036,6 @@ query-string@^5.0.1: object-assign "^4.1.0" strict-uri-encode "^1.0.0" -randomatic@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.1.1.tgz#b776efc59375984e36c537b2f51a1f0aff0da1ed" - integrity sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw== - dependencies: - is-number "^4.0.0" - kind-of "^6.0.0" - math-random "^1.0.1" - randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.0.6, randombytes@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" @@ -8235,16 +9076,11 @@ rc@^1.2.7: minimist "^1.2.0" strip-json-comments "~2.0.1" -react-is@^16.12.0: +react-is@^16.12.0, react-is@^16.8.4: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== -react-is@^16.8.4: - version "16.13.0" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.0.tgz#0f37c3613c34fe6b37cd7f763a0d6293ab15c527" - integrity sha512-GFMtL0vHkiBv9HluwNZTggSn/sCyEt9n02aM0dSAjGGyqyNlAyftYm4phPxdvCigG15JreC5biwxCgTAJZ7yAA== - read-pkg-up@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" @@ -8321,7 +9157,7 @@ readable-stream@~1.0.15: isarray "0.0.1" string_decoder "~0.10.x" -readdirp@^2.0.0, readdirp@^2.2.1: +readdirp@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== @@ -8361,10 +9197,10 @@ regenerator-runtime@^0.11.0: resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== -regenerator-runtime@^0.13.2: - version "0.13.3" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz#7cf6a77d8f5c6f60eb73c5fc1955b2ceb01e6bf5" - integrity sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw== +regenerator-runtime@^0.13.4: + version "0.13.9" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" + integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== regenerator-transform@^0.10.0: version "0.10.1" @@ -8375,13 +9211,6 @@ regenerator-transform@^0.10.0: babel-types "^6.19.0" private "^0.1.6" -regex-cache@^0.4.2: - version "0.4.4" - resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" - integrity sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ== - dependencies: - is-equal-shallow "^0.1.3" - regex-not@^1.0.0, regex-not@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" @@ -8398,6 +9227,11 @@ regexp.prototype.flags@^1.2.0: define-properties "^1.1.3" es-abstract "^1.17.0-next.1" +regexpp@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" + integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== + regexpu-core@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" @@ -8446,7 +9280,7 @@ repeat-element@^1.1.2: resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== -repeat-string@^1.5.2, repeat-string@^1.6.1: +repeat-string@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= @@ -8472,19 +9306,19 @@ replace-homedir@^1.0.0: is-absolute "^1.0.0" remove-trailing-separator "^1.1.0" -request-promise-core@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.3.tgz#e9a3c081b51380dfea677336061fea879a829ee9" - integrity sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ== +request-promise-core@1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.4.tgz#3eedd4223208d419867b78ce815167d10593a22f" + integrity sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw== dependencies: - lodash "^4.17.15" + lodash "^4.17.19" request-promise-native@^1.0.5: - version "1.0.8" - resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.8.tgz#a455b960b826e44e2bf8999af64dff2bfe58cb36" - integrity sha512-dapwLGqkHtwL5AEbfenuzjTYg35Jd6KPytsC2/TLkVMz8rm+tNt72MGUWT1RP/aYawMpN6HqbNGBQaRcBtjQMQ== + version "1.0.9" + resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.9.tgz#e407120526a5efdc9a39b28a5679bf47b9d9dc28" + integrity sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g== dependencies: - request-promise-core "1.1.3" + request-promise-core "1.1.4" stealthy-require "^1.1.1" tough-cookie "^2.3.3" @@ -8554,6 +9388,11 @@ resolve-from@^3.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" integrity sha1-six699nWiBvItuZTM17rywoYh0g= +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + resolve-options@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/resolve-options/-/resolve-options-1.1.0.tgz#32bb9e39c06d67338dc9378c0d6d6074566ad131" @@ -8571,7 +9410,15 @@ resolve@1.1.7, resolve@1.1.x: resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= -resolve@1.x, resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.3.2, resolve@^1.4.0, resolve@^1.8.1: +resolve@1.x, resolve@^1.14.2: + version "1.20.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" + integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== + dependencies: + is-core-module "^2.2.0" + path-parse "^1.0.6" + +resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.3.2, resolve@^1.4.0: version "1.15.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.15.1.tgz#27bdcdeffeaf2d6244b95bb0f9f4b4653451f3e8" integrity sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w== @@ -8592,6 +9439,14 @@ responselike@^1.0.2: dependencies: lowercase-keys "^1.0.0" +restore-cursor@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" + integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368= + dependencies: + onetime "^2.0.0" + signal-exit "^3.0.2" + resumer@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/resumer/-/resumer-0.0.0.tgz#f1e8f461e4064ba39e82af3cdc2a8c893d076759" @@ -8609,6 +9464,13 @@ reusify@^1.0.4: resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== +rimraf@2.6.3: + version "2.6.3" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== + dependencies: + glob "^7.1.3" + rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.2, rimraf@^2.6.3: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" @@ -8631,11 +9493,23 @@ rlp@^2.0.0, rlp@^2.2.1, rlp@^2.2.2, rlp@^2.2.3: dependencies: bn.js "^4.11.1" +rlp@^2.2.4: + version "2.2.6" + resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.6.tgz#c80ba6266ac7a483ef1e69e8e2f056656de2fb2c" + integrity sha512-HAfAmL6SDYNWPUOJNrM500x4Thn4PZsEy5pijPh40U9WfNk0z15hUYzO9xVIMAdIHdFtD8CBDHd75Td1g36Mjg== + dependencies: + bn.js "^4.11.1" + rsvp@^4.8.4: version "4.8.5" resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" integrity sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA== +run-async@^2.2.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" + integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== + run-parallel@^1.1.9: version "1.1.9" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" @@ -8646,6 +9520,13 @@ rustbn.js@~0.2.0: resolved "https://registry.yarnpkg.com/rustbn.js/-/rustbn.js-0.2.0.tgz#8082cb886e707155fd1cb6f23bd591ab8d55d0ca" integrity sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA== +rxjs@^6.4.0: + version "6.6.7" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9" + integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ== + dependencies: + tslib "^1.9.0" + rxjs@^6.5.3: version "6.5.4" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.4.tgz#e0777fe0d184cec7872df147f303572d414e211c" @@ -8712,7 +9593,7 @@ scrypt-js@2.0.4: resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-2.0.4.tgz#32f8c5149f0797672e551c07e230f834b6af5f16" integrity sha512-4KsaGcPnuhtCZQCxFxN3GVYIhKFPTdLd8PLC552XwbMndtD0cjRFAhDuuydXQ0h08ZfPgzqe6EKHozpuH74iDw== -scrypt-js@^3.0.1: +scrypt-js@^3.0.0, scrypt-js@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== @@ -8749,6 +9630,15 @@ secp256k1@^3.0.1: nan "^2.14.0" safe-buffer "^5.1.2" +secp256k1@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-4.0.2.tgz#15dd57d0f0b9fdb54ac1fa1694f40e5e9a54f4a1" + integrity sha512-UDar4sKvWAksIlfX3xIaQReADn+WFnHvbVujpcbr+9Sf/69odMwy2MUsz5CKLQgX9nsIyrjuxL2imVyoNHa3fg== + dependencies: + elliptic "^6.5.2" + node-addon-api "^2.0.0" + node-gyp-build "^4.2.0" + seedrandom@3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/seedrandom/-/seedrandom-3.0.1.tgz#eb3dde015bcf55df05a233514e5df44ef9dce083" @@ -8788,7 +9678,12 @@ semver@5.5.0: resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" integrity sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA== -semver@^6.0.0, semver@^6.2.0, semver@^6.3.0: +semver@7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" + integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== + +semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== @@ -8948,6 +9843,15 @@ slash@^2.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== +slice-ansi@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" + integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== + dependencies: + ansi-styles "^3.2.0" + astral-regex "^1.0.0" + is-fullwidth-code-point "^2.0.0" + snapdragon-node@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" @@ -8978,16 +9882,6 @@ snapdragon@^0.8.1: source-map-resolve "^0.5.0" use "^3.1.0" -sol-digger@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/sol-digger/-/sol-digger-0.0.2.tgz#406c4a9d31e269e7f88eb1c2ea101318e5e09025" - integrity sha1-QGxKnTHiaef4jrHC6hATGOXgkCU= - -sol-explore@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/sol-explore/-/sol-explore-1.6.1.tgz#b59f073c69fe332560d5a10c32ba8ca7f2986cfb" - integrity sha1-tZ8HPGn+MyVg1aEMMrqMp/KYbPs= - solc@^0.5.5: version "0.5.16" resolved "https://registry.yarnpkg.com/solc/-/solc-0.5.16.tgz#6c8d710a3792ccc79db924606b558a1149b1c603" @@ -9002,35 +9896,33 @@ solc@^0.5.5: semver "^5.5.0" tmp "0.0.33" +solhint@^3.3.7: + version "3.3.7" + resolved "https://registry.yarnpkg.com/solhint/-/solhint-3.3.7.tgz#b5da4fedf7a0fee954cb613b6c55a5a2b0063aa7" + integrity sha512-NjjjVmXI3ehKkb3aNtRJWw55SUVJ8HMKKodwe0HnejA+k0d2kmhw7jvpa+MCTbcEgt8IWSwx0Hu6aCo/iYOZzQ== + dependencies: + "@solidity-parser/parser" "^0.14.1" + ajv "^6.6.1" + antlr4 "4.7.1" + ast-parents "0.0.1" + chalk "^2.4.2" + commander "2.18.0" + cosmiconfig "^5.0.7" + eslint "^5.6.0" + fast-diff "^1.1.2" + glob "^7.1.3" + ignore "^4.0.6" + js-yaml "^3.12.0" + lodash "^4.17.11" + semver "^6.3.0" + optionalDependencies: + prettier "^1.14.3" + "solidity-parser-antlr@https://github.com/solidity-parser/parser": version "0.7.0" resolved "https://github.com/solidity-parser/parser#013764c850294460d51c6f227cc150c152a01338" -solium-plugin-security@0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/solium-plugin-security/-/solium-plugin-security-0.1.1.tgz#2a87bcf8f8c3abf7d198e292e4ac080284e3f3f6" - integrity sha512-kpLirBwIq4mhxk0Y/nn5cQ6qdJTI+U1LO3gpoNIcqNaW+sI058moXBe2UiHs+9wvF9IzYD49jcKhFTxcR9u9SQ== - -solium@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/solium/-/solium-1.2.5.tgz#d036c30e2901e22137bbf342f106b17529ff22a8" - integrity sha512-NuNrm7fp8JcDN/P+SAdM5TVa4wYDtwVtLY/rG4eBOZrC5qItsUhmQKR/YhjszaEW4c8tNUYhkhQcwOsS25znpw== - dependencies: - ajv "^5.2.2" - chokidar "^1.6.0" - colors "^1.1.2" - commander "^2.9.0" - diff "^3.5.0" - eol "^0.9.1" - js-string-escape "^1.0.1" - lodash "^4.14.2" - sol-digger "0.0.2" - sol-explore "1.6.1" - solium-plugin-security "0.1.1" - solparse "2.2.8" - text-table "^0.2.0" - -solparse@2.2.8, solparse@^2.2.8: +solparse@^2.2.8: version "2.2.8" resolved "https://registry.yarnpkg.com/solparse/-/solparse-2.2.8.tgz#d13e42dbed95ce32f43894f5ec53f00d14cf9f11" integrity sha512-Tm6hdfG72DOxD40SD+T5ddbekWglNWjzDRSNq7ZDIOHVsyaJSeeunUuWNj4DE7uDrJK3tGQuX0ZTDZWNYsGPMA== @@ -9159,9 +10051,11 @@ stack-trace@0.0.10: integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA= stack-utils@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.2.tgz#33eba3897788558bebfc2db059dc158ec36cebb8" - integrity sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA== + version "1.0.5" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.5.tgz#a19b0b01947e0029c8e451d5d61a498f5bb1471b" + integrity sha512-KZiTzuV3CnSnSvgMRrARVCj+Ht7rMbauGDK0LdVFRGyenwdylpajAp4Q0i6SX8rEmbTpMMf6ryq2gb8pPq2WgQ== + dependencies: + escape-string-regexp "^2.0.0" static-extend@^0.1.1: version "0.1.2" @@ -9221,7 +10115,7 @@ string-width@^1.0.1, string-width@^1.0.2: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.1: +"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== @@ -9247,6 +10141,14 @@ string.prototype.trim@~1.2.1: es-abstract "^1.17.0-next.1" function-bind "^1.1.1" +string.prototype.trimend@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz#e75ae90c2942c63504686c18b287b4a0b1a45f80" + integrity sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + string.prototype.trimleft@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz#9bdb8ac6abd6d602b17a4ed321870d2f8dcefc74" @@ -9263,6 +10165,14 @@ string.prototype.trimright@^2.1.1: define-properties "^1.1.3" function-bind "^1.1.1" +string.prototype.trimstart@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz#b36399af4ab2999b4c9c648bd7a3fb2bb26feeed" + integrity sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" @@ -9334,7 +10244,7 @@ strip-hex-prefix@1.0.0: dependencies: is-hex-prefixed "1.0.0" -strip-json-comments@~2.0.1: +strip-json-comments@^2.0.1, strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= @@ -9427,6 +10337,16 @@ symbol-tree@^3.2.2: resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== +table@^5.2.3: + version "5.4.6" + resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" + integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== + dependencies: + ajv "^6.10.2" + lodash "^4.17.14" + slice-ansi "^2.1.0" + string-width "^3.0.0" + tape@^4.4.0, tape@^4.6.3: version "4.13.0" resolved "https://registry.yarnpkg.com/tape/-/tape-4.13.0.tgz#e2f581ff5f12a7cbd787e9f83c76c2851782fce2" @@ -9531,7 +10451,7 @@ through2@^2.0.0, through2@^2.0.3, through2@~2.0.0: readable-stream "~2.3.6" xtend "~4.0.1" -through@^2.3.8, through@~2.3.4, through@~2.3.8: +through@^2.3.6, through@^2.3.8, through@~2.3.4, through@~2.3.8: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= @@ -9546,7 +10466,7 @@ timed-out@^4.0.0, timed-out@^4.0.1: resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" integrity sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8= -tmp@0.0.33: +tmp@0.0.33, tmp@^0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== @@ -9678,6 +10598,11 @@ tslib@^1.9.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.1.tgz#eb15d128827fbee2841549e171f45ed338ac7e35" integrity sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA== +tslib@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.0.tgz#803b8cdab3e12ba581a4ca41c8839bbb0dacb09e" + integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg== + tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" @@ -9743,9 +10668,9 @@ typedarray@^0.0.6: integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= typescript@^3.5.1: - version "3.8.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.8.2.tgz#91d6868aaead7da74f493c553aeff76c0c0b1d5a" - integrity sha512-EgOVgL/4xfVrCMbhYKUQTdF37SQn4Iw73H5BgCrF1Abdun7Kwy/QZsE/ssAy0y4LxBbvua3PIbFsbRczWWnDdQ== + version "3.9.10" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.10.tgz#70f3910ac7a51ed6bef79da7800690b19bf778b8" + integrity sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q== typewise-core@^1.2, typewise-core@^1.2.0: version "1.2.0" @@ -9782,6 +10707,16 @@ ultron@~1.1.0: resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og== +unbox-primitive@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471" + integrity sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw== + dependencies: + function-bind "^1.1.1" + has-bigints "^1.0.1" + has-symbols "^1.0.2" + which-boxed-primitive "^1.0.2" + unbzip2-stream@^1.0.9: version "1.3.3" resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.3.3.tgz#d156d205e670d8d8c393e1c02ebd506422873f6a" @@ -9795,6 +10730,11 @@ unc-path-regex@^0.1.2: resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" integrity sha1-5z3T17DXxe2G+6xrCufYxqadUPo= +underscore@1.12.1: + version "1.12.1" + resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.12.1.tgz#7bb8cc9b3d397e201cf8553336d262544ead829e" + integrity sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw== + underscore@1.9.1: version "1.9.1" resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.1.tgz#06dce34a0e68a7babc29b365b8e74b8925203961" @@ -9916,6 +10856,13 @@ use@^3.1.0: resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== +utf-8-validate@^5.0.2: + version "5.0.5" + resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.5.tgz#dd32c2e82c72002dc9f02eb67ba6761f43456ca1" + integrity sha512-+pnxRYsS/axEpkrrEpzYfNZGXp0IjC/9RIxwM5gntY4Koi8SHmUGSfxfWqxZdRxrtaoVstuOzUp/rbs3JSPELQ== + dependencies: + node-gyp-build "^4.2.0" + utf8@3.0.0, utf8@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/utf8/-/utf8-3.0.0.tgz#f052eed1364d696e769ef058b183df88c87f69d1" @@ -9936,6 +10883,18 @@ util.promisify@^1.0.0: has-symbols "^1.0.1" object.getownpropertydescriptors "^2.1.0" +util@^0.12.0: + version "0.12.4" + resolved "https://registry.yarnpkg.com/util/-/util-0.12.4.tgz#66121a31420df8f01ca0c464be15dfa1d1850253" + integrity sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw== + dependencies: + inherits "^2.0.3" + is-arguments "^1.0.4" + is-generator-function "^1.0.7" + is-typed-array "^1.1.3" + safe-buffer "^5.1.2" + which-typed-array "^1.1.2" + utils-merge@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" @@ -10049,11 +11008,11 @@ vinyl@^2.0.0: replace-ext "^1.0.0" w3c-hr-time@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz#82ac2bff63d950ea9e3189a58a65625fedf19045" - integrity sha1-gqwr/2PZUOqeMYmlimViX+3xkEU= + version "1.0.2" + resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd" + integrity sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ== dependencies: - browser-process-hrtime "^0.1.2" + browser-process-hrtime "^1.0.0" walker@^1.0.7, walker@~1.0.5: version "1.0.7" @@ -10062,16 +11021,6 @@ walker@^1.0.7, walker@~1.0.5: dependencies: makeerror "1.0.x" -web3-bzz@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.2.11.tgz#41bc19a77444bd5365744596d778b811880f707f" - integrity sha512-XGpWUEElGypBjeFyUhTkiPXFbDVD6Nr/S5jznE3t8cWUA0FxRf1n3n/NuIZeb0H9RkN2Ctd/jNma/k8XGa3YKg== - dependencies: - "@types/node" "^12.12.6" - got "9.6.0" - swarm-js "^0.1.40" - underscore "1.9.1" - web3-bzz@1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.2.4.tgz#a4adb7a8cba3d260de649bdb1f14ed359bfb3821" @@ -10082,14 +11031,15 @@ web3-bzz@1.2.4: swarm-js "0.1.39" underscore "1.9.1" -web3-core-helpers@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.2.11.tgz#84c681ed0b942c0203f3b324a245a127e8c67a99" - integrity sha512-PEPoAoZd5ME7UfbnCZBdzIerpe74GEvlwT4AjOmHeCVZoIFk7EqvOZDejJHt+feJA6kMVTdd0xzRNN295UhC1A== +web3-bzz@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.4.0.tgz#78a5db3544624b6709b2554094d931639f6f85b8" + integrity sha512-KhXmz8hcfGsqhplB7NrekAeNkG2edHjXV4bL3vnXde8RGMWpabpSNxuwiGv+dv/3nWlrHatH0vGooONYCkP5TA== dependencies: - underscore "1.9.1" - web3-eth-iban "1.2.11" - web3-utils "1.2.11" + "@types/node" "^12.12.6" + got "9.6.0" + swarm-js "^0.1.40" + underscore "1.12.1" web3-core-helpers@1.2.4: version "1.2.4" @@ -10100,17 +11050,14 @@ web3-core-helpers@1.2.4: web3-eth-iban "1.2.4" web3-utils "1.2.4" -web3-core-method@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.2.11.tgz#f880137d1507a0124912bf052534f168b8d8fbb6" - integrity sha512-ff0q76Cde94HAxLDZ6DbdmKniYCQVtvuaYh+rtOUMB6kssa5FX0q3vPmixi7NPooFnbKmmZCM6NvXg4IreTPIw== +web3-core-helpers@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.4.0.tgz#5cbed46dd325b9498f6fafb15aed4a4295cce514" + integrity sha512-8Ebq0nmRfzw7iPoXbIRHEWOuPh+1cOV3OOEvKm5Od3McZOjja914vdk+DM3MgmbSpDzYJRFM6KoF0+Z/U/1bPw== dependencies: - "@ethersproject/transactions" "^5.0.0-beta.135" - underscore "1.9.1" - web3-core-helpers "1.2.11" - web3-core-promievent "1.2.11" - web3-core-subscriptions "1.2.11" - web3-utils "1.2.11" + underscore "1.12.1" + web3-eth-iban "1.4.0" + web3-utils "1.4.0" web3-core-method@1.2.4: version "1.2.4" @@ -10123,12 +11070,17 @@ web3-core-method@1.2.4: web3-core-subscriptions "1.2.4" web3-utils "1.2.4" -web3-core-promievent@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.2.11.tgz#51fe97ca0ddec2f99bf8c3306a7a8e4b094ea3cf" - integrity sha512-il4McoDa/Ox9Agh4kyfQ8Ak/9ABYpnF8poBLL33R/EnxLsJOGQG2nZhkJa3I067hocrPSjEdlPt/0bHXsln4qA== +web3-core-method@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.4.0.tgz#0e26001e4029d359731b25a82e0bed4d1bef8392" + integrity sha512-KW9922fEkgKu8zDcJR8Iikg/epsuWMArAUVTipKVwzAI5TVdvOMRgSe/b7IIDRUIeoeXMARmJ+PrAlx+IU2acQ== dependencies: - eventemitter3 "4.0.4" + "@ethersproject/transactions" "^5.0.0-beta.135" + underscore "1.12.1" + web3-core-helpers "1.4.0" + web3-core-promievent "1.4.0" + web3-core-subscriptions "1.4.0" + web3-utils "1.4.0" web3-core-promievent@1.2.4: version "1.2.4" @@ -10138,16 +11090,12 @@ web3-core-promievent@1.2.4: any-promise "1.3.0" eventemitter3 "3.1.2" -web3-core-requestmanager@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.2.11.tgz#fe6eb603fbaee18530293a91f8cf26d8ae28c45a" - integrity sha512-oFhBtLfOiIbmfl6T6gYjjj9igOvtyxJ+fjS+byRxiwFJyJ5BQOz4/9/17gWR1Cq74paTlI7vDGxYfuvfE/mKvA== +web3-core-promievent@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.4.0.tgz#531644dab287e83653d983aeb3d9daa0f894f775" + integrity sha512-YEwko22kcry7lHwbe0k80BrjXCZ+73jMdvZtptRH5k2B+XZ1XtmXwYL1PFIlZy9V0zgZijdg+3GabCnAHjVXAw== dependencies: - underscore "1.9.1" - web3-core-helpers "1.2.11" - web3-providers-http "1.2.11" - web3-providers-ipc "1.2.11" - web3-providers-ws "1.2.11" + eventemitter3 "4.0.4" web3-core-requestmanager@1.2.4: version "1.2.4" @@ -10160,14 +11108,17 @@ web3-core-requestmanager@1.2.4: web3-providers-ipc "1.2.4" web3-providers-ws "1.2.4" -web3-core-subscriptions@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.2.11.tgz#beca908fbfcb050c16f45f3f0f4c205e8505accd" - integrity sha512-qEF/OVqkCvQ7MPs1JylIZCZkin0aKK9lDxpAtQ1F8niEDGFqn7DT8E/vzbIa0GsOjL2fZjDhWJsaW+BSoAW1gg== +web3-core-requestmanager@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.4.0.tgz#39043da0e1a1b1474f85af531df786e6036ef4b3" + integrity sha512-qIwKJO5T0KkUAIL7y9JRSUkk3+LaCwghdUHK8FzbMvq6R1W9lgCBnccqFGEI76EJjHvsiw4kEKBEXowdB3xenQ== dependencies: - eventemitter3 "4.0.4" - underscore "1.9.1" - web3-core-helpers "1.2.11" + underscore "1.12.1" + util "^0.12.0" + web3-core-helpers "1.4.0" + web3-providers-http "1.4.0" + web3-providers-ipc "1.4.0" + web3-providers-ws "1.4.0" web3-core-subscriptions@1.2.4: version "1.2.4" @@ -10178,18 +11129,14 @@ web3-core-subscriptions@1.2.4: underscore "1.9.1" web3-core-helpers "1.2.4" -web3-core@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.2.11.tgz#1043cacc1becb80638453cc5b2a14be9050288a7" - integrity sha512-CN7MEYOY5ryo5iVleIWRE3a3cZqVaLlIbIzDPsvQRUfzYnvzZQRZBm9Mq+ttDi2STOOzc1MKylspz/o3yq/LjQ== +web3-core-subscriptions@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.4.0.tgz#ec44e5cfe7bffe0c2a9da330007f88e08e1b5837" + integrity sha512-/UMC9rSLEd0U+h6Qanx6CM29o/cfUyGWgl/HM6O/AIuth9G+34QBuKDa11Gr2Qg6F8Lr9tSFm8QIGVniOx9i5A== dependencies: - "@types/bn.js" "^4.11.5" - "@types/node" "^12.12.6" - bignumber.js "^9.0.0" - web3-core-helpers "1.2.11" - web3-core-method "1.2.11" - web3-core-requestmanager "1.2.11" - web3-utils "1.2.11" + eventemitter3 "4.0.4" + underscore "1.12.1" + web3-core-helpers "1.4.0" web3-core@1.2.4: version "1.2.4" @@ -10204,14 +11151,18 @@ web3-core@1.2.4: web3-core-requestmanager "1.2.4" web3-utils "1.2.4" -web3-eth-abi@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.2.11.tgz#a887494e5d447c2926d557a3834edd66e17af9b0" - integrity sha512-PkRYc0+MjuLSgg03QVWqWlQivJqRwKItKtEpRUaxUAeLE7i/uU39gmzm2keHGcQXo3POXAbOnMqkDvOep89Crg== +web3-core@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.4.0.tgz#db830ed9fa9cca37479c501f0e5bc4201493b46b" + integrity sha512-VRNMNqwzvPeKIet2l9BMApPHoUv0UqwaZH0lZJhG2RBko42w9Xls+pQwfVNSV16j04t/ehm1aLRV2Sx6lzVfRg== dependencies: - "@ethersproject/abi" "5.0.0-beta.153" - underscore "1.9.1" - web3-utils "1.2.11" + "@types/bn.js" "^4.11.5" + "@types/node" "^12.12.6" + bignumber.js "^9.0.0" + web3-core-helpers "1.4.0" + web3-core-method "1.4.0" + web3-core-requestmanager "1.4.0" + web3-utils "1.4.0" web3-eth-abi@1.2.4: version "1.2.4" @@ -10222,6 +11173,15 @@ web3-eth-abi@1.2.4: underscore "1.9.1" web3-utils "1.2.4" +web3-eth-abi@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.4.0.tgz#83f9f0ce48fd6d6b233a30a33bd674b3518e472b" + integrity sha512-FtmWipG/dSSkTGFb72JCwky7Jd0PIvd0kGTInWQwIEZlw5qMOYl61WZ9gwfojFHvHF6q1eKncerQr+MRXHO6zg== + dependencies: + "@ethersproject/abi" "5.0.7" + underscore "1.12.1" + web3-utils "1.4.0" + web3-eth-abi@^1.0.0-beta.24: version "1.2.6" resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.2.6.tgz#b495383cc5c0d8e2857b26e7fe25606685983b25" @@ -10231,23 +11191,6 @@ web3-eth-abi@^1.0.0-beta.24: underscore "1.9.1" web3-utils "1.2.6" -web3-eth-accounts@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.2.11.tgz#a9e3044da442d31903a7ce035a86d8fa33f90520" - integrity sha512-6FwPqEpCfKIh3nSSGeo3uBm2iFSnFJDfwL3oS9pyegRBXNsGRVpgiW63yhNzL0796StsvjHWwQnQHsZNxWAkGw== - dependencies: - crypto-browserify "3.12.0" - eth-lib "0.2.8" - ethereumjs-common "^1.3.2" - ethereumjs-tx "^2.1.1" - scrypt-js "^3.0.1" - underscore "1.9.1" - uuid "3.3.2" - web3-core "1.2.11" - web3-core-helpers "1.2.11" - web3-core-method "1.2.11" - web3-utils "1.2.11" - web3-eth-accounts@1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.2.4.tgz#ada6edc49542354328a85cafab067acd7f88c288" @@ -10266,20 +11209,23 @@ web3-eth-accounts@1.2.4: web3-core-method "1.2.4" web3-utils "1.2.4" -web3-eth-contract@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.2.11.tgz#917065902bc27ce89da9a1da26e62ef663663b90" - integrity sha512-MzYuI/Rq2o6gn7vCGcnQgco63isPNK5lMAan2E51AJLknjSLnOxwNY3gM8BcKoy4Z+v5Dv00a03Xuk78JowFow== +web3-eth-accounts@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.4.0.tgz#25fc4b2b582a16b77c1492f27f58c59481156068" + integrity sha512-tETHBvfO3Z7BXZ7HJIwuX7ol6lPefP55X7b4IiX82C1PujHwsxENY7c/3wyxzqKoDyH6zfyEQo17yhxkhsM1oA== dependencies: - "@types/bn.js" "^4.11.5" - underscore "1.9.1" - web3-core "1.2.11" - web3-core-helpers "1.2.11" - web3-core-method "1.2.11" - web3-core-promievent "1.2.11" - web3-core-subscriptions "1.2.11" - web3-eth-abi "1.2.11" - web3-utils "1.2.11" + "@ethereumjs/common" "^2.3.0" + "@ethereumjs/tx" "^3.2.1" + crypto-browserify "3.12.0" + eth-lib "0.2.8" + ethereumjs-util "^7.0.10" + scrypt-js "^3.0.1" + underscore "1.12.1" + uuid "3.3.2" + web3-core "1.4.0" + web3-core-helpers "1.4.0" + web3-core-method "1.4.0" + web3-utils "1.4.0" web3-eth-contract@1.2.4: version "1.2.4" @@ -10296,20 +11242,20 @@ web3-eth-contract@1.2.4: web3-eth-abi "1.2.4" web3-utils "1.2.4" -web3-eth-ens@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.2.11.tgz#26d4d7f16d6cbcfff918e39832b939edc3162532" - integrity sha512-dbW7dXP6HqT1EAPvnniZVnmw6TmQEKF6/1KgAxbo8iBBYrVTMDGFQUUnZ+C4VETGrwwaqtX4L9d/FrQhZ6SUiA== +web3-eth-contract@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.4.0.tgz#604187d1e44365fa0c0592e61ac5a1b5fd7c2eaa" + integrity sha512-GfIhOzfp/ZXKd+1tFEH3ePq0DEsvq9XO5tOsI0REDtEYUj2GNxO5e/x/Fhekk7iLZ7xAqSzDMweFruDQ1fxn0A== dependencies: - content-hash "^2.5.2" - eth-ens-namehash "2.0.8" - underscore "1.9.1" - web3-core "1.2.11" - web3-core-helpers "1.2.11" - web3-core-promievent "1.2.11" - web3-eth-abi "1.2.11" - web3-eth-contract "1.2.11" - web3-utils "1.2.11" + "@types/bn.js" "^4.11.5" + underscore "1.12.1" + web3-core "1.4.0" + web3-core-helpers "1.4.0" + web3-core-method "1.4.0" + web3-core-promievent "1.4.0" + web3-core-subscriptions "1.4.0" + web3-eth-abi "1.4.0" + web3-utils "1.4.0" web3-eth-ens@1.2.4: version "1.2.4" @@ -10325,13 +11271,20 @@ web3-eth-ens@1.2.4: web3-eth-contract "1.2.4" web3-utils "1.2.4" -web3-eth-iban@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.2.11.tgz#f5f73298305bc7392e2f188bf38a7362b42144ef" - integrity sha512-ozuVlZ5jwFC2hJY4+fH9pIcuH1xP0HEFhtWsR69u9uDIANHLPQQtWYmdj7xQ3p2YT4bQLq/axKhZi7EZVetmxQ== +web3-eth-ens@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.4.0.tgz#4e66dfc3bdc6439553482972ffb2a181f1c12cbc" + integrity sha512-jR1KorjU1erpYFpFzsMXAWZnHhqUqWPBq/4+BGVj7/pJ43+A3mrE1eB0zl91Dwc1RTNwOhB02iOj1c9OlpGr3g== dependencies: - bn.js "^4.11.9" - web3-utils "1.2.11" + content-hash "^2.5.2" + eth-ens-namehash "2.0.8" + underscore "1.12.1" + web3-core "1.4.0" + web3-core-helpers "1.4.0" + web3-core-promievent "1.4.0" + web3-eth-abi "1.4.0" + web3-eth-contract "1.4.0" + web3-utils "1.4.0" web3-eth-iban@1.2.4: version "1.2.4" @@ -10341,17 +11294,13 @@ web3-eth-iban@1.2.4: bn.js "4.11.8" web3-utils "1.2.4" -web3-eth-personal@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.2.11.tgz#a38b3942a1d87a62070ce0622a941553c3d5aa70" - integrity sha512-42IzUtKq9iHZ8K9VN0vAI50iSU9tOA1V7XU2BhF/tb7We2iKBVdkley2fg26TxlOcKNEHm7o6HRtiiFsVK4Ifw== +web3-eth-iban@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.4.0.tgz#b54902c019d677b6356d838b3e964f925017c143" + integrity sha512-YNx748VzwiBe0gvtZjvU9BQsooZ9s9sAlmiDWJOMcvMbUTDhC7SvxA7vV/vrnOxL6oGHRh0U/azsYNxxlKiTBw== dependencies: - "@types/node" "^12.12.6" - web3-core "1.2.11" - web3-core-helpers "1.2.11" - web3-core-method "1.2.11" - web3-net "1.2.11" - web3-utils "1.2.11" + bn.js "^4.11.9" + web3-utils "1.4.0" web3-eth-personal@1.2.4: version "1.2.4" @@ -10365,24 +11314,17 @@ web3-eth-personal@1.2.4: web3-net "1.2.4" web3-utils "1.2.4" -web3-eth@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.2.11.tgz#4c81fcb6285b8caf544058fba3ae802968fdc793" - integrity sha512-REvxW1wJ58AgHPcXPJOL49d1K/dPmuw4LjPLBPStOVkQjzDTVmJEIsiLwn2YeuNDd4pfakBwT8L3bz1G1/wVsQ== +web3-eth-personal@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.4.0.tgz#77420d1f49e36f8c461a61aeabac16045d8592c0" + integrity sha512-8Ip6xZ8plmWqAD4ESbKUIPVV9gfTAFFm0ff1FQIw9I9kYvFlBIPzukvm852w2SftGem+/iRH+2+2mK7HvuKXZQ== dependencies: - underscore "1.9.1" - web3-core "1.2.11" - web3-core-helpers "1.2.11" - web3-core-method "1.2.11" - web3-core-subscriptions "1.2.11" - web3-eth-abi "1.2.11" - web3-eth-accounts "1.2.11" - web3-eth-contract "1.2.11" - web3-eth-ens "1.2.11" - web3-eth-iban "1.2.11" - web3-eth-personal "1.2.11" - web3-net "1.2.11" - web3-utils "1.2.11" + "@types/node" "^12.12.6" + web3-core "1.4.0" + web3-core-helpers "1.4.0" + web3-core-method "1.4.0" + web3-net "1.4.0" + web3-utils "1.4.0" web3-eth@1.2.4: version "1.2.4" @@ -10403,14 +11345,24 @@ web3-eth@1.2.4: web3-net "1.2.4" web3-utils "1.2.4" -web3-net@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.2.11.tgz#eda68ef25e5cdb64c96c39085cdb74669aabbe1b" - integrity sha512-sjrSDj0pTfZouR5BSTItCuZ5K/oZPVdVciPQ6981PPPIwJJkCMeVjD7I4zO3qDPCnBjBSbWvVnLdwqUBPtHxyg== - dependencies: - web3-core "1.2.11" - web3-core-method "1.2.11" - web3-utils "1.2.11" +web3-eth@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.4.0.tgz#6ca2dcbd72d128a225ada1fec0d1e751f8df5200" + integrity sha512-L990eMJeWh4h/Z3M8MJb9HrKq8tqvzdGZ7igdzd6Ba3B/VKgGFAJ/4XIqtLwAJ1Wg5Cj8my60tYY+34c2cLefw== + dependencies: + underscore "1.12.1" + web3-core "1.4.0" + web3-core-helpers "1.4.0" + web3-core-method "1.4.0" + web3-core-subscriptions "1.4.0" + web3-eth-abi "1.4.0" + web3-eth-accounts "1.4.0" + web3-eth-contract "1.4.0" + web3-eth-ens "1.4.0" + web3-eth-iban "1.4.0" + web3-eth-personal "1.4.0" + web3-net "1.4.0" + web3-utils "1.4.0" web3-net@1.2.4: version "1.2.4" @@ -10421,6 +11373,15 @@ web3-net@1.2.4: web3-core-method "1.2.4" web3-utils "1.2.4" +web3-net@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.4.0.tgz#eaea1562dc96ddde6f14e823d2b94886091d2049" + integrity sha512-41WkKobL+KnKC0CY0RZ1KhMMyR/hMFGlbHZQac4KtB7ro1UdXeK+RiYX+GzSr1h7j9Dj+dQZqyBs70cxmL9cPQ== + dependencies: + web3-core "1.4.0" + web3-core-method "1.4.0" + web3-utils "1.4.0" + web3-provider-engine@14.0.6: version "14.0.6" resolved "https://registry.yarnpkg.com/web3-provider-engine/-/web3-provider-engine-14.0.6.tgz#cbdd66fe20c0136a3a495cbe40d18b6c4160d5f0" @@ -10475,9 +11436,9 @@ web3-provider-engine@14.2.1: xtend "^4.0.1" web3-provider-engine@^15.0.4: - version "15.0.6" - resolved "https://registry.yarnpkg.com/web3-provider-engine/-/web3-provider-engine-15.0.6.tgz#bb64d49d0718bb6a12f146bdd542d5f2f8fa4e48" - integrity sha512-KdIHmRmB7VG6HeSu4hlB+Iypsbv/dAbNV/UWBDxsTwLJuuTSobmtowOq5BEsegXtjWhSSzSi9O0Ci/DVG0kB1g== + version "15.0.12" + resolved "https://registry.yarnpkg.com/web3-provider-engine/-/web3-provider-engine-15.0.12.tgz#24d7f2f6fb6de856824c7306291018c4fc543ac3" + integrity sha512-/OfhQalKPND1iB5ggvGuYF0+SIb2Qj5OFTrT2VrZWP79UhMTdP7T+L2FtblmRdCeOetoAzZHdBaIwLOZsmIX+w== dependencies: async "^2.5.0" backoff "^2.5.0" @@ -10502,14 +11463,6 @@ web3-provider-engine@^15.0.4: xhr "^2.2.0" xtend "^4.0.1" -web3-providers-http@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.2.11.tgz#1cd03442c61670572d40e4dcdf1faff8bd91e7c6" - integrity sha512-psh4hYGb1+ijWywfwpB2cvvOIMISlR44F/rJtYkRmQ5jMvG4FOCPlQJPiHQZo+2cc3HbktvvSJzIhkWQJdmvrA== - dependencies: - web3-core-helpers "1.2.11" - xhr2-cookies "1.1.0" - web3-providers-http@1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.2.4.tgz#514fcad71ae77832c2c15574296282fbbc5f4a67" @@ -10518,14 +11471,13 @@ web3-providers-http@1.2.4: web3-core-helpers "1.2.4" xhr2-cookies "1.1.0" -web3-providers-ipc@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.2.11.tgz#d16d6c9be1be6e0b4f4536c4acc16b0f4f27ef21" - integrity sha512-yhc7Y/k8hBV/KlELxynWjJDzmgDEDjIjBzXK+e0rHBsYEhdCNdIH5Psa456c+l0qTEU2YzycF8VAjYpWfPnBpQ== +web3-providers-http@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.4.0.tgz#2d67f85fda00765c1402aede3d7e6cbacaa3091b" + integrity sha512-A9nLF4XGZfDb1KYYuKRwHY1H90Ee/0I0CqQQEELI0yuY9eca50qdCHEg3sJhvqBIG44JCm83amOGxR8wi+76tQ== dependencies: - oboe "2.1.4" - underscore "1.9.1" - web3-core-helpers "1.2.11" + web3-core-helpers "1.4.0" + xhr2-cookies "1.1.0" web3-providers-ipc@1.2.4: version "1.2.4" @@ -10536,15 +11488,14 @@ web3-providers-ipc@1.2.4: underscore "1.9.1" web3-core-helpers "1.2.4" -web3-providers-ws@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.2.11.tgz#a1dfd6d9778d840561d9ec13dd453046451a96bb" - integrity sha512-ZxnjIY1Er8Ty+cE4migzr43zA/+72AF1myzsLaU5eVgdsfV7Jqx7Dix1hbevNZDKFlSoEyq/3j/jYalh3So1Zg== +web3-providers-ipc@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.4.0.tgz#cd14e93e2d22689a26587dd2d2101e575d1e2924" + integrity sha512-ul/tSNUI5anhdBGBV+FWFH9EJgO73/G21haFDEXvTnSJQa9/byj401H/E2Xd8BXGk+2XB+CCGLZBiuAjhhhtTA== dependencies: - eventemitter3 "4.0.4" - underscore "1.9.1" - web3-core-helpers "1.2.11" - websocket "^1.0.31" + oboe "2.1.5" + underscore "1.12.1" + web3-core-helpers "1.4.0" web3-providers-ws@1.2.4: version "1.2.4" @@ -10555,15 +11506,15 @@ web3-providers-ws@1.2.4: underscore "1.9.1" web3-core-helpers "1.2.4" -web3-shh@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.2.11.tgz#f5d086f9621c9a47e98d438010385b5f059fd88f" - integrity sha512-B3OrO3oG1L+bv3E1sTwCx66injW1A8hhwpknDUbV+sw3fehFazA06z9SGXUefuFI1kVs4q2vRi0n4oCcI4dZDg== +web3-providers-ws@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.4.0.tgz#a4db03fc865a73db62bc15c5da37f930517cfe08" + integrity sha512-E5XfF58RLXuCtGiMSXxXEtjceCfPli+I4MDYCKx/J/bDJ6qvLUM2OnnGEmE7pq1Z03h0xh1ZezaB/qoweK3ZIQ== dependencies: - web3-core "1.2.11" - web3-core-method "1.2.11" - web3-core-subscriptions "1.2.11" - web3-net "1.2.11" + eventemitter3 "4.0.4" + underscore "1.12.1" + web3-core-helpers "1.4.0" + websocket "^1.0.32" web3-shh@1.2.4: version "1.2.4" @@ -10575,19 +11526,15 @@ web3-shh@1.2.4: web3-core-subscriptions "1.2.4" web3-net "1.2.4" -web3-utils@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.2.11.tgz#af1942aead3fb166ae851a985bed8ef2c2d95a82" - integrity sha512-3Tq09izhD+ThqHEaWYX4VOT7dNPdZiO+c/1QMA0s5X2lDFKK/xHJb7cyTRRVzN2LvlHbR7baS1tmQhSua51TcQ== +web3-shh@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.4.0.tgz#d22ff8dce16987bef73172191d9e95c3ccf0aa80" + integrity sha512-OZMkMgo+VZnu1ErhIFXW+5ExnPKQg9v8/2DHGVtNEwuC5OHYuAEF5U7MQgbxYJYwbRmxQCt/hA3VwKjnkbmSAA== dependencies: - bn.js "^4.11.9" - eth-lib "0.2.8" - ethereum-bloom-filters "^1.0.6" - ethjs-unit "0.1.6" - number-to-bn "1.7.0" - randombytes "^2.1.0" - underscore "1.9.1" - utf8 "3.0.0" + web3-core "1.4.0" + web3-core-method "1.4.0" + web3-core-subscriptions "1.4.0" + web3-net "1.4.0" web3-utils@1.2.4: version "1.2.4" @@ -10617,6 +11564,20 @@ web3-utils@1.2.6: underscore "1.9.1" utf8 "3.0.0" +web3-utils@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.4.0.tgz#e8cb381c81b242dc1d4ecb397200356d404410e6" + integrity sha512-b8mEhwh/J928Xk+SQFjtqrR2EGPhpknWLcIt9aCpVPVRXiqjUGo/kpOHKz0azu9c6/onEJ9tWXZt0cVjmH0N5Q== + dependencies: + bn.js "^4.11.9" + eth-lib "0.2.8" + ethereum-bloom-filters "^1.0.6" + ethjs-unit "0.1.6" + number-to-bn "1.7.0" + randombytes "^2.1.0" + underscore "1.12.1" + utf8 "3.0.0" + web3@1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/web3/-/web3-1.2.4.tgz#6e7ab799eefc9b4648c2dab63003f704a1d5e7d9" @@ -10632,17 +11593,17 @@ web3@1.2.4: web3-utils "1.2.4" web3@^1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3/-/web3-1.2.11.tgz#50f458b2e8b11aa37302071c170ed61cff332975" - integrity sha512-mjQ8HeU41G6hgOYm1pmeH0mRAeNKJGnJEUzDMoerkpw7QUQT4exVREgF1MYPvL/z6vAshOXei25LE/t/Bxl8yQ== + version "1.4.0" + resolved "https://registry.yarnpkg.com/web3/-/web3-1.4.0.tgz#717c01723226daebab9274be5cb56644de860688" + integrity sha512-faT3pIX+1tuo+wqmUFQPe10MUGaB1UvRYxw9dmVJFLxaRAIfXErSilOf3jFhSwKbbPNkwG0bTiudCLN9JgeS7A== dependencies: - web3-bzz "1.2.11" - web3-core "1.2.11" - web3-eth "1.2.11" - web3-eth-personal "1.2.11" - web3-net "1.2.11" - web3-shh "1.2.11" - web3-utils "1.2.11" + web3-bzz "1.4.0" + web3-core "1.4.0" + web3-eth "1.4.0" + web3-eth-personal "1.4.0" + web3-net "1.4.0" + web3-shh "1.4.0" + web3-utils "1.4.0" webidl-conversions@^4.0.2: version "4.0.2" @@ -10660,15 +11621,16 @@ websocket@1.0.29: typedarray-to-buffer "^3.1.5" yaeti "^0.0.6" -websocket@^1.0.31: - version "1.0.31" - resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.31.tgz#e5d0f16c3340ed87670e489ecae6144c79358730" - integrity sha512-VAouplvGKPiKFDTeCCO65vYHsyay8DqoBSlzIO3fayrfOgU94lQN5a1uWVnFrMLceTJw/+fQXR5PGbUVRaHshQ== +websocket@^1.0.32: + version "1.0.34" + resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.34.tgz#2bdc2602c08bf2c82253b730655c0ef7dcab3111" + integrity sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ== dependencies: + bufferutil "^4.0.1" debug "^2.2.0" es5-ext "^0.10.50" - nan "^2.14.0" typedarray-to-buffer "^3.1.5" + utf-8-validate "^5.0.2" yaeti "^0.0.6" whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3: @@ -10711,6 +11673,17 @@ whatwg-url@^7.0.0: tr46 "^1.0.1" webidl-conversions "^4.0.2" +which-boxed-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" + integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== + dependencies: + is-bigint "^1.0.1" + is-boolean-object "^1.1.0" + is-number-object "^1.0.4" + is-string "^1.0.5" + is-symbol "^1.0.3" + which-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" @@ -10726,6 +11699,19 @@ which-pm-runs@^1.0.0: resolved "https://registry.yarnpkg.com/which-pm-runs/-/which-pm-runs-1.0.0.tgz#670b3afbc552e0b55df6b7780ca74615f23ad1cb" integrity sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs= +which-typed-array@^1.1.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.4.tgz#8fcb7d3ee5adf2d771066fba7cf37e32fe8711ff" + integrity sha512-49E0SpUe90cjpoc7BOJwyPHRqSAd12c10Qm2amdEZrJPCY2NDxaW01zHITrem+rnETY3dwrbH3UUrUwagfCYDA== + dependencies: + available-typed-arrays "^1.0.2" + call-bind "^1.0.0" + es-abstract "^1.18.0-next.1" + foreach "^2.0.5" + function-bind "^1.1.1" + has-symbols "^1.0.1" + is-typed-array "^1.1.3" + which@^1.1.1, which@^1.2.14, which@^1.2.9, which@^1.3.0: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" @@ -10786,6 +11772,13 @@ write-file-atomic@2.4.1: imurmurhash "^0.1.4" signal-exit "^3.0.2" +write@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" + integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== + dependencies: + mkdirp "^0.5.1" + ws@^3.0.0: version "3.3.3" resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" @@ -10795,13 +11788,20 @@ ws@^3.0.0: safe-buffer "~5.1.0" ultron "~1.1.0" -ws@^5.1.1, ws@^5.2.0: +ws@^5.1.1: version "5.2.2" resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.2.tgz#dffef14866b8e8dc9133582514d1befaf96e980f" integrity sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA== dependencies: async-limiter "~1.0.0" +ws@^5.2.0: + version "5.2.3" + resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.3.tgz#05541053414921bc29c63bee14b8b0dd50b07b3d" + integrity sha512-jZArVERrMsKUatIdnLzqvcfydI85dvd/Fp1u/VOpfdDWQ4c9qWXe+VIeAbQ5FrDwciAkr+lzofXLz3Kuf26AOA== + dependencies: + async-limiter "~1.0.0" + xhr-request-promise@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/xhr-request-promise/-/xhr-request-promise-0.1.2.tgz#343c44d1ee7726b8648069682d0f840c83b4261d" @@ -10898,10 +11898,10 @@ yargs-parser@10.x: dependencies: camelcase "^4.1.0" -yargs-parser@^13.1.1: - version "13.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" - integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ== +yargs-parser@^13.1.2: + version "13.1.2" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" + integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== dependencies: camelcase "^5.0.0" decamelize "^1.2.0" @@ -10939,9 +11939,9 @@ yargs@^10.0.3: yargs-parser "^8.1.0" yargs@^13.2.4, yargs@^13.3.0: - version "13.3.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.0.tgz#4c657a55e07e5f2cf947f8a366567c04a0dedc83" - integrity sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA== + version "13.3.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" + integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== dependencies: cliui "^5.0.0" find-up "^3.0.0" @@ -10952,7 +11952,7 @@ yargs@^13.2.4, yargs@^13.3.0: string-width "^3.0.0" which-module "^2.0.0" y18n "^4.0.0" - yargs-parser "^13.1.1" + yargs-parser "^13.1.2" yargs@^7.1.0: version "7.1.0"