Contract Overview
Balance:
0 BTT
BTT Value:
$0.00
My Name Tag:
Not Available, login to update
Txn Hash | Method |
Block
|
From
|
To
|
Value | [Txn Fee] | |||
---|---|---|---|---|---|---|---|---|---|
0xbd6d56a8d8da17ee1bc372713498ee645a75dfb8c6a7275cb4abfd9ee3325338 | 0x60806040 | 14069910 | 389 days 23 hrs ago | Bitlend: Deployer | IN | Create: CompoundLens | 0 BTT | 980.3985 |
[ Download CSV Export ]
Contract Name:
CompoundLens
Compiler Version
v0.8.10+commit.fc410830
Contract Source Code (Solidity)
/** *Submitted for verification at bttcscan.com on 2022-11-14 */ // Sources flattened with hardhat v2.10.1 https://hardhat.org // File contracts/ComptrollerInterface.sol // SPDX-License-Identifier: BSD-3-Clause pragma solidity ^0.8.10; 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) virtual external returns (uint[] memory); function exitMarket(address cToken) virtual external returns (uint); /*** Policy Hooks ***/ 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) virtual external returns (uint); function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) virtual 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) virtual external returns (uint); function repayBorrowVerify( address cToken, address payer, address borrower, uint repayAmount, uint borrowerIndex) virtual external; function liquidateBorrowAllowed( address cTokenBorrowed, address cTokenCollateral, address liquidator, address borrower, uint repayAmount) virtual external returns (uint); function liquidateBorrowVerify( address cTokenBorrowed, address cTokenCollateral, address liquidator, address borrower, uint repayAmount, uint seizeTokens) virtual external; function seizeAllowed( address cTokenCollateral, address cTokenBorrowed, address liquidator, address borrower, uint seizeTokens) virtual external returns (uint); function seizeVerify( address cTokenCollateral, address cTokenBorrowed, address liquidator, address borrower, uint seizeTokens) virtual 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) virtual external view returns (uint, uint); } abstract contract InterestRateModel { /// @notice Indicator that this is an InterestRateModel contract (for inspection) bool public constant isInterestRateModel = true; /** * @notice Calculates the current borrow interest rate per block * @param cash The total amount of cash the market has * @param borrows The total amount of borrows the market has outstanding * @param reserves The total amount of reserves the market has * @return The borrow rate per block (as a percentage, and scaled by 1e18) */ function getBorrowRate(uint cash, uint borrows, uint reserves) virtual external view returns (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) virtual external view returns (uint); } interface EIP20NonStandardInterface { /** * @notice Get the total number of tokens in circulation * @return The supply of tokens */ function totalSupply() external view returns (uint256); /** * @notice Gets the balance of the specified address * @param owner The address from which the balance will be retrieved * @return balance The balance */ function balanceOf(address owner) external view returns (uint256 balance); /// /// !!!!!!!!!!!!!! /// !!! NOTICE !!! `transfer` does not return a value, in violation of the ERC-20 specification /// !!!!!!!!!!!!!! /// /** * @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 */ function transfer(address dst, uint256 amount) external; /// /// !!!!!!!!!!!!!! /// !!! NOTICE !!! `transferFrom` does not return a value, in violation of the ERC-20 specification /// !!!!!!!!!!!!!! /// /** * @notice Transfer `amount` tokens from `src` to `dst` * @param src The address of the source account * @param dst The address of the destination account * @param amount The number of tokens to transfer */ function transferFrom(address src, address dst, uint256 amount) external; /** * @notice Approve `spender` to transfer up to `amount` from `src` * @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 * @return success Whether or not the approval succeeded */ function approve(address spender, uint256 amount) external returns (bool success); /** * @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 remaining The number of tokens allowed to be spent */ function allowance(address owner, address spender) external view returns (uint256 remaining); event Transfer(address indexed from, address indexed to, uint256 amount); event Approval(address indexed owner, address indexed spender, uint256 amount); } contract ComptrollerErrorReporter { enum Error { NO_ERROR, UNAUTHORIZED, COMPTROLLER_MISMATCH, INSUFFICIENT_SHORTFALL, INSUFFICIENT_LIQUIDITY, INVALID_CLOSE_FACTOR, INVALID_COLLATERAL_FACTOR, INVALID_LIQUIDATION_INCENTIVE, MARKET_NOT_ENTERED, // no longer possible MARKET_NOT_LISTED, MARKET_ALREADY_LISTED, MATH_ERROR, NONZERO_BORROW_BALANCE, PRICE_ERROR, REJECTION, SNAPSHOT_ERROR, TOO_MANY_ASSETS, TOO_MUCH_REPAY } enum FailureInfo { ACCEPT_ADMIN_PENDING_ADMIN_CHECK, ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK, EXIT_MARKET_BALANCE_OWED, EXIT_MARKET_REJECTION, SET_CLOSE_FACTOR_OWNER_CHECK, SET_CLOSE_FACTOR_VALIDATION, SET_COLLATERAL_FACTOR_OWNER_CHECK, SET_COLLATERAL_FACTOR_NO_EXISTS, SET_COLLATERAL_FACTOR_VALIDATION, SET_COLLATERAL_FACTOR_WITHOUT_PRICE, SET_IMPLEMENTATION_OWNER_CHECK, SET_LIQUIDATION_INCENTIVE_OWNER_CHECK, SET_LIQUIDATION_INCENTIVE_VALIDATION, SET_MAX_ASSETS_OWNER_CHECK, SET_PENDING_ADMIN_OWNER_CHECK, SET_PENDING_IMPLEMENTATION_OWNER_CHECK, SET_PRICE_ORACLE_OWNER_CHECK, SUPPORT_MARKET_EXISTS, SUPPORT_MARKET_OWNER_CHECK, SET_PAUSE_GUARDIAN_OWNER_CHECK } /** * @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); /** * @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); return uint(err); } /** * @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); return uint(err); } } contract TokenErrorReporter { uint public constant NO_ERROR = 0; // support legacy return codes 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(); } contract CTokenStorage { /** * @dev Guard variable for re-entrancy checks */ bool internal _notEntered; /** * @notice EIP-20 token name for this token */ string public name; /** * @notice EIP-20 token symbol for this token */ string public symbol; /** * @notice EIP-20 token decimals for this token */ uint8 public decimals; // Maximum borrow rate that can ever be applied (.0005% / block) uint internal constant borrowRateMaxMantissa = 0.0005e16; // Maximum fraction of interest that can be set aside for reserves uint internal constant reserveFactorMaxMantissa = 1e18; /** * @notice Administrator for this contract */ address payable public admin; /** * @notice Pending administrator for this contract */ address payable public pendingAdmin; /** * @notice Contract which oversees inter-cToken operations */ ComptrollerInterface public comptroller; /** * @notice Model which tells what the current interest rate should be */ InterestRateModel public interestRateModel; // Initial exchange rate used when minting the first CTokens (used when totalSupply = 0) uint internal initialExchangeRateMantissa; /** * @notice Fraction of interest currently set aside for reserves */ uint public reserveFactorMantissa; /** * @notice Block number that interest was last accrued at */ uint public accrualBlockNumber; /** * @notice Accumulator of the total earned interest rate since the opening of the market */ uint public borrowIndex; /** * @notice Total amount of outstanding borrows of the underlying in this market */ uint public totalBorrows; /** * @notice Total amount of reserves of the underlying held in this market */ uint public totalReserves; /** * @notice Total number of tokens in circulation */ uint public totalSupply; // Official record of token balances for each account mapping (address => uint) internal accountTokens; // Approved token transfer amounts on behalf of others mapping (address => mapping (address => uint)) internal transferAllowances; /** * @notice Container for borrow balance information * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action * @member interestIndex Global borrowIndex as of the most recent balance-changing action */ struct BorrowSnapshot { uint principal; uint interestIndex; } // 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% } abstract contract CTokenInterface is CTokenStorage { /** * @notice Indicator that this is a CToken contract (for inspection) */ bool public constant isCToken = true; /*** Market Events ***/ /** * @notice Event emitted when interest is accrued */ event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows); /** * @notice Event emitted when tokens are minted */ event Mint(address minter, uint mintAmount, uint mintTokens); /** * @notice Event emitted when tokens are redeemed */ event Redeem(address redeemer, uint redeemAmount, uint redeemTokens); /** * @notice Event emitted when underlying is borrowed */ event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows); /** * @notice Event emitted when a borrow is repaid */ event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows); /** * @notice Event emitted when a borrow is liquidated */ event LiquidateBorrow(address liquidator, address borrower, uint repayAmount, address cTokenCollateral, uint seizeTokens); /*** Admin Events ***/ /** * @notice Event emitted when pendingAdmin is changed */ event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin); /** * @notice Event emitted when pendingAdmin is accepted, which means admin is updated */ event NewAdmin(address oldAdmin, address newAdmin); /** * @notice Event emitted when comptroller is changed */ event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller); /** * @notice Event emitted when interestRateModel is changed */ event NewMarketInterestRateModel(InterestRateModel oldInterestRateModel, InterestRateModel newInterestRateModel); /** * @notice Event emitted when the reserve factor is changed */ event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa); /** * @notice Event emitted when the reserves are added */ event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves); /** * @notice Event emitted when the reserves are reduced */ event ReservesReduced(address admin, uint reduceAmount, uint newTotalReserves); /** * @notice EIP20 Transfer event */ event Transfer(address indexed from, address indexed to, uint amount); /** * @notice EIP20 Approval event */ event Approval(address indexed owner, address indexed spender, uint amount); /*** User Interface ***/ 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) 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 { /** * @notice Underlying asset for this CToken */ address public underlying; } abstract contract CErc20Interface is CErc20Storage { /*** User Interface ***/ 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) virtual external returns (uint); } contract CDelegationStorage { /** * @notice Implementation address for this contract */ address public implementation; } abstract contract CDelegatorInterface is CDelegationStorage { /** * @notice Emitted when implementation is changed */ event NewImplementation(address oldImplementation, address newImplementation); /** * @notice Called by the admin to update the implementation of the delegator * @param implementation_ The address of the new implementation for delegation * @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) virtual external; } 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) virtual external; /** * @notice Called by the delegator on a delegate to forfeit its responsibility */ function _resignImplementation() virtual external; } interface EIP20Interface { function name() external view returns (string memory); function symbol() external view returns (string memory); function decimals() external view returns (uint8); /** * @notice Get the total number of tokens in circulation * @return The supply of tokens */ function totalSupply() external view returns (uint256); /** * @notice Gets the balance of the specified address * @param owner The address from which the balance will be retrieved * @return balance The balance */ function balanceOf(address owner) external view returns (uint256 balance); /** * @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 success Whether or not the transfer succeeded */ function transfer(address dst, uint256 amount) external returns (bool success); /** * @notice Transfer `amount` tokens from `src` to `dst` * @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 success Whether or not the transfer succeeded */ function transferFrom(address src, address dst, uint256 amount) external returns (bool success); /** * @notice Approve `spender` to transfer up to `amount` from `src` * @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) * @return success Whether or not the approval succeeded */ function approve(address spender, uint256 amount) external returns (bool success); /** * @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 remaining The number of tokens allowed to be spent (-1 means infinite) */ function allowance(address owner, address spender) external view returns (uint256 remaining); event Transfer(address indexed from, address indexed to, uint256 amount); event Approval(address indexed owner, address indexed spender, uint256 amount); } contract ExponentialNoError { uint constant expScale = 1e18; uint constant doubleScale = 1e36; uint constant halfExpScale = expScale/2; uint constant mantissaOne = expScale; struct Exp { uint mantissa; } struct Double { uint mantissa; } /** * @dev Truncates the given exp to a whole number value. * For example, truncate(Exp{mantissa: 15 * expScale}) = 15 */ function truncate(Exp memory exp) pure internal returns (uint) { // Note: We are not using careful math here as we're performing a division that cannot fail return exp.mantissa / expScale; } /** * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer. */ function mul_ScalarTruncate(Exp memory a, uint scalar) pure internal returns (uint) { Exp memory product = mul_(a, scalar); return truncate(product); } /** * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer. */ function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) pure internal returns (uint) { Exp memory product = mul_(a, scalar); return add_(truncate(product), addend); } /** * @dev Checks if first Exp is less than second Exp. */ function lessThanExp(Exp memory left, Exp memory right) pure internal returns (bool) { return left.mantissa < right.mantissa; } /** * @dev Checks if left Exp <= right Exp. */ function lessThanOrEqualExp(Exp memory left, Exp memory right) pure internal returns (bool) { return left.mantissa <= right.mantissa; } /** * @dev Checks if left Exp > right Exp. */ function greaterThanExp(Exp memory left, Exp memory right) pure internal returns (bool) { return left.mantissa > right.mantissa; } /** * @dev returns true if Exp is exactly zero */ function isZeroExp(Exp memory value) pure internal returns (bool) { return value.mantissa == 0; } function safe224(uint n, string memory errorMessage) pure internal returns (uint224) { require(n < 2**224, errorMessage); return uint224(n); } function safe32(uint n, string memory errorMessage) pure internal returns (uint32) { require(n < 2**32, errorMessage); return uint32(n); } function add_(Exp memory a, Exp memory b) pure internal returns (Exp memory) { return Exp({mantissa: add_(a.mantissa, b.mantissa)}); } function add_(Double memory a, Double memory b) pure internal returns (Double memory) { return Double({mantissa: add_(a.mantissa, b.mantissa)}); } function add_(uint a, uint b) pure internal returns (uint) { return a + b; } function sub_(Exp memory a, Exp memory b) pure internal returns (Exp memory) { return Exp({mantissa: sub_(a.mantissa, b.mantissa)}); } function sub_(Double memory a, Double memory b) pure internal returns (Double memory) { return Double({mantissa: sub_(a.mantissa, b.mantissa)}); } function sub_(uint a, uint b) pure internal returns (uint) { return a - b; } function mul_(Exp memory a, Exp memory b) pure internal returns (Exp memory) { return Exp({mantissa: mul_(a.mantissa, b.mantissa) / expScale}); } function mul_(Exp memory a, uint b) pure internal returns (Exp memory) { return Exp({mantissa: mul_(a.mantissa, b)}); } function mul_(uint a, Exp memory b) pure internal returns (uint) { return mul_(a, b.mantissa) / expScale; } function mul_(Double memory a, Double memory b) pure internal returns (Double memory) { return Double({mantissa: mul_(a.mantissa, b.mantissa) / doubleScale}); } function mul_(Double memory a, uint b) pure internal returns (Double memory) { return Double({mantissa: mul_(a.mantissa, b)}); } function mul_(uint a, Double memory b) pure internal returns (uint) { return mul_(a, b.mantissa) / doubleScale; } function mul_(uint a, uint b) pure internal returns (uint) { return a * b; } function div_(Exp memory a, Exp memory b) pure internal returns (Exp memory) { return Exp({mantissa: div_(mul_(a.mantissa, expScale), b.mantissa)}); } function div_(Exp memory a, uint b) pure internal returns (Exp memory) { return Exp({mantissa: div_(a.mantissa, b)}); } function div_(uint a, Exp memory b) pure internal returns (uint) { return div_(mul_(a, expScale), b.mantissa); } function div_(Double memory a, Double memory b) pure internal returns (Double memory) { return Double({mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa)}); } function div_(Double memory a, uint b) pure internal returns (Double memory) { return Double({mantissa: div_(a.mantissa, b)}); } function div_(uint a, Double memory b) pure internal returns (uint) { return div_(mul_(a, doubleScale), b.mantissa); } function div_(uint a, uint b) pure internal returns (uint) { return a / b; } function fraction(uint a, uint b) pure internal returns (Double memory) { return Double({mantissa: div_(mul_(a, doubleScale), b)}); } } abstract contract CToken is CTokenInterface, ExponentialNoError, TokenErrorReporter { /** * @notice Initialize the money market * @param comptroller_ The address of the Comptroller * @param interestRateModel_ The address of the interest rate model * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18 * @param name_ EIP-20 name of this token * @param symbol_ EIP-20 symbol of this token * @param decimals_ EIP-20 decimal precision of this token */ function initialize(ComptrollerInterface comptroller_, InterestRateModel interestRateModel_, uint initialExchangeRateMantissa_, string memory name_, string memory symbol_, uint8 decimals_) public { require(msg.sender == admin, "only admin may initialize the market"); require(accrualBlockNumber == 0 && borrowIndex == 0, "market may only be initialized once"); // Set initial exchange rate initialExchangeRateMantissa = initialExchangeRateMantissa_; require(initialExchangeRateMantissa > 0, "initial exchange rate must be greater than zero."); // Set the comptroller uint err = _setComptroller(comptroller_); require(err == NO_ERROR, "setting comptroller failed"); // Initialize block number and borrow index (block number mocks depend on comptroller being set) accrualBlockNumber = getBlockNumber(); borrowIndex = mantissaOne; // Set the interest rate model (depends on block number / borrow index) err = _setInterestRateModelFresh(interestRateModel_); require(err == NO_ERROR, "setting interest rate model failed"); name = name_; symbol = symbol_; decimals = decimals_; // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund) _notEntered = true; } /** * @notice Transfer `tokens` tokens from `src` to `dst` by `spender` * @dev Called by both `transfer` and `transferFrom` internally * @param spender The address of the account performing the transfer * @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 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) { revert TransferComptrollerRejection(allowed); } /* Do not allow self-transfers */ if (src == dst) { revert TransferNotAllowed(); } /* Get the allowance, infinite for the account owner */ uint startingAllowance = 0; if (spender == src) { startingAllowance = type(uint).max; } else { startingAllowance = transferAllowances[src][spender]; } /* Do the calculations, checking for {under,over}flow */ uint allowanceNew = startingAllowance - tokens; uint srcTokensNew = accountTokens[src] - tokens; uint dstTokensNew = accountTokens[dst] + tokens; ///////////////////////// // EFFECTS & INTERACTIONS // (No safe failures beyond this point) accountTokens[src] = srcTokensNew; accountTokens[dst] = dstTokensNew; /* Eat some of the allowance (if necessary) */ if (startingAllowance != type(uint).max) { transferAllowances[src][spender] = allowanceNew; } /* We emit a Transfer event */ emit Transfer(src, dst, tokens); // unused function // comptroller.transferVerify(address(this), src, dst, tokens); return NO_ERROR; } /** * @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 */ function transfer(address dst, uint256 amount) override external nonReentrant returns (bool) { return transferTokens(msg.sender, msg.sender, dst, amount) == NO_ERROR; } /** * @notice Transfer `amount` tokens from `src` to `dst` * @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 */ function transferFrom(address src, address dst, uint256 amount) override external nonReentrant returns (bool) { return transferTokens(msg.sender, src, dst, amount) == NO_ERROR; } /** * @notice Approve `spender` to transfer up to `amount` from `src` * @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 (uint256.max means infinite) * @return Whether or not the approval succeeded */ function approve(address spender, uint256 amount) override external returns (bool) { address src = msg.sender; transferAllowances[src][spender] = amount; emit Approval(src, spender, amount); return true; } /** * @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) */ function allowance(address owner, address spender) override external view returns (uint256) { return transferAllowances[owner][spender]; } /** * @notice Get the token balance of the `owner` * @param owner The address of the account to query * @return The number of tokens owned by `owner` */ function balanceOf(address owner) override external view returns (uint256) { return accountTokens[owner]; } /** * @notice Get the underlying balance of the `owner` * @dev This also accrues interest in a transaction * @param owner The address of the account to query * @return The amount of underlying owned by `owner` */ function balanceOfUnderlying(address owner) override external returns (uint) { Exp memory exchangeRate = Exp({mantissa: exchangeRateCurrent()}); return mul_ScalarTruncate(exchangeRate, accountTokens[owner]); } /** * @notice Get a snapshot of the account's balances, and the cached exchange rate * @dev This is used by comptroller to more efficiently perform liquidity checks. * @param account Address of the account to snapshot * @return (possible error, token balance, borrow balance, exchange rate mantissa) */ 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() virtual internal view returns (uint) { return block.number; } /** * @notice Returns the current per-block borrow interest rate for this cToken * @return The borrow interest rate per block, scaled by 1e18 */ function borrowRatePerBlock() override external view returns (uint) { return interestRateModel.getBorrowRate(getCashPrior(), totalBorrows, totalReserves); } /** * @notice Returns the current per-block supply interest rate for this cToken * @return The supply interest rate per block, scaled by 1e18 */ function supplyRatePerBlock() override external view returns (uint) { return interestRateModel.getSupplyRate(getCashPrior(), totalBorrows, totalReserves, reserveFactorMantissa); } /** * @notice Returns the current total borrows plus accrued interest * @return The total borrows with interest */ function totalBorrowsCurrent() override external nonReentrant returns (uint) { accrueInterest(); return totalBorrows; } /** * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex * @param account The address whose balance should be calculated after updating borrowIndex * @return The calculated balance */ function borrowBalanceCurrent(address account) override external nonReentrant returns (uint) { accrueInterest(); return borrowBalanceStored(account); } /** * @notice Return the borrow balance of account based on stored data * @param account The address whose balance should be calculated * @return The calculated balance */ function borrowBalanceStored(address account) override public view returns (uint) { return borrowBalanceStoredInternal(account); } /** * @notice Return the borrow balance of account based on stored data * @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 (uint) { /* Get borrowBalance and borrowIndex */ BorrowSnapshot storage borrowSnapshot = accountBorrows[account]; /* If borrowBalance = 0 then borrowIndex is likely also 0. * Rather than failing the calculation with a division by 0, we immediately return 0 in this case. */ if (borrowSnapshot.principal == 0) { return 0; } /* Calculate new borrow balance using the interest index: * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex */ 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() override public nonReentrant returns (uint) { accrueInterest(); return exchangeRateStored(); } /** * @notice Calculates the exchange rate from the underlying to the CToken * @dev This function does not accrue interest before calculating the exchange rate * @return Calculated exchange rate scaled by 1e18 */ 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 calculated exchange rate scaled by 1e18 */ function exchangeRateStoredInternal() virtual internal view returns (uint) { uint _totalSupply = totalSupply; if (_totalSupply == 0) { /* * If there are no tokens minted: * exchangeRate = initialExchangeRate */ return initialExchangeRateMantissa; } else { /* * Otherwise: * exchangeRate = (totalCash + totalBorrows - totalReserves) / totalSupply */ uint totalCash = getCashPrior(); uint cashPlusBorrowsMinusReserves = totalCash + totalBorrows - totalReserves; uint exchangeRate = cashPlusBorrowsMinusReserves * expScale / _totalSupply; return exchangeRate; } } /** * @notice Get cash balance of this cToken in the underlying asset * @return The quantity of underlying asset owned by this contract */ function getCash() override external view returns (uint) { return getCashPrior(); } /** * @notice Applies accrued interest to total borrows and reserves * @dev This calculates interest accrued from the last checkpointed block * up to the current block and writes new checkpoint to storage. */ 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 NO_ERROR; } /* Read the previous values out of storage */ uint cashPrior = getCashPrior(); uint borrowsPrior = totalBorrows; uint reservesPrior = totalReserves; uint borrowIndexPrior = borrowIndex; /* Calculate the current borrow interest rate */ uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior); require(borrowRateMantissa <= borrowRateMaxMantissa, "borrow rate is absurdly high"); /* Calculate the number of blocks elapsed since the last accrual */ uint blockDelta = currentBlockNumber - accrualBlockNumberPrior; /* * Calculate the interest accumulated into borrows and reserves and the new index: * simpleInterestFactor = borrowRate * blockDelta * interestAccumulated = simpleInterestFactor * totalBorrows * totalBorrowsNew = interestAccumulated + totalBorrows * totalReservesNew = interestAccumulated * reserveFactor + totalReserves * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex */ 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 // (No safe failures beyond this point) /* We write the previously calculated values into storage */ accrualBlockNumber = currentBlockNumber; borrowIndex = borrowIndexNew; totalBorrows = totalBorrowsNew; totalReserves = totalReservesNew; /* We emit an AccrueInterest event */ emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew); 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 */ 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 mintFresh(msg.sender, mintAmount); } /** * @notice User supplies assets into the market and receives cTokens in exchange * @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 */ function mintFresh(address minter, uint mintAmount) internal { /* Fail if mint not allowed */ uint allowed = comptroller.mintAllowed(address(this), minter, mintAmount); if (allowed != 0) { revert MintComptrollerRejection(allowed); } /* Verify market's block number equals current block number */ if (accrualBlockNumber != getBlockNumber()) { revert MintFreshnessCheck(); } Exp memory exchangeRate = Exp({mantissa: exchangeRateStoredInternal()}); ///////////////////////// // EFFECTS & INTERACTIONS // (No safe failures beyond this point) /* * We call `doTransferIn` for the minter and the mintAmount. * Note: The cToken must handle variations between ERC-20 and ETH underlying. * `doTransferIn` reverts if anything goes wrong, since we can't be sure if * side-effects occurred. The function returns the amount actually transferred, * in case of a fee. On success, the cToken holds an additional `actualMintAmount` * of cash. */ uint actualMintAmount = doTransferIn(minter, mintAmount); /* * We get the current exchange rate and calculate the number of cTokens to be minted: * mintTokens = actualMintAmount / exchangeRate */ 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 */ totalSupply = totalSupply + mintTokens; accountTokens[minter] = accountTokens[minter] + mintTokens; /* We emit a Mint event, and a Transfer event */ emit Mint(minter, actualMintAmount, mintTokens); emit Transfer(address(this), minter, mintTokens); /* We call the defense hook */ // unused function // 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 */ function redeemInternal(uint redeemTokens) internal nonReentrant { accrueInterest(); // redeemFresh emits redeem-specific logs on errors, so we don't need to 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 */ function redeemUnderlyingInternal(uint redeemAmount) internal nonReentrant { accrueInterest(); // redeemFresh emits redeem-specific logs on errors, so we don't need to redeemFresh(payable(msg.sender), 0, redeemAmount); } /** * @notice User redeems cTokens in exchange for the underlying asset * @dev Assumes interest has already been accrued up to the current block * @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) */ function redeemFresh(address payable redeemer, uint redeemTokensIn, uint redeemAmountIn) internal { require(redeemTokensIn == 0 || redeemAmountIn == 0, "one of redeemTokensIn or redeemAmountIn must be zero"); /* exchangeRate = invoke Exchange Rate Stored() */ Exp memory exchangeRate = Exp({mantissa: exchangeRateStoredInternal() }); uint redeemTokens; uint redeemAmount; /* If redeemTokensIn > 0: */ if (redeemTokensIn > 0) { /* * We calculate the exchange rate and the amount of underlying to be redeemed: * redeemTokens = redeemTokensIn * redeemAmount = redeemTokensIn x exchangeRateCurrent */ 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 */ redeemTokens = div_(redeemAmountIn, exchangeRate); redeemAmount = redeemAmountIn; } /* Fail if redeem not allowed */ uint allowed = comptroller.redeemAllowed(address(this), redeemer, redeemTokens); if (allowed != 0) { revert RedeemComptrollerRejection(allowed); } /* Verify market's block number equals current block number */ if (accrualBlockNumber != getBlockNumber()) { revert RedeemFreshnessCheck(); } /* Fail gracefully if protocol has insufficient cash */ 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, redeemAmount); /* We emit a Transfer event, and a Redeem event */ emit Transfer(redeemer, address(this), redeemTokens); emit Redeem(redeemer, redeemAmount, redeemTokens); /* We call the defense hook */ 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 */ function borrowInternal(uint borrowAmount) internal nonReentrant { accrueInterest(); // borrowFresh emits borrow-specific logs on errors, so we don't need to 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 */ function borrowFresh(address payable borrower, uint borrowAmount) internal { /* Fail if borrow not allowed */ uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount); if (allowed != 0) { revert BorrowComptrollerRejection(allowed); } /* Verify market's block number equals current block number */ if (accrualBlockNumber != getBlockNumber()) { revert BorrowFreshnessCheck(); } /* Fail gracefully if protocol has insufficient underlying cash */ if (getCashPrior() < borrowAmount) { revert BorrowCashNotAvailable(); } /* * We calculate the new borrower and total borrow balances, failing on overflow: * accountBorrowNew = accountBorrow + borrowAmount * totalBorrowsNew = totalBorrows + borrowAmount */ 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. * On success, the cToken borrowAmount less of cash. * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred. */ doTransferOut(borrower, borrowAmount); /* We emit a Borrow event */ emit Borrow(borrower, borrowAmount, accountBorrowsNew, totalBorrowsNew); } /** * @notice Sender repays their own borrow * @param repayAmount The amount to repay, or -1 for the full outstanding amount */ function repayBorrowInternal(uint repayAmount) internal nonReentrant { accrueInterest(); // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to 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, or -1 for the full outstanding amount */ function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant { accrueInterest(); // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to 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 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) { /* Fail if repayBorrow not allowed */ uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount); if (allowed != 0) { revert RepayBorrowComptrollerRejection(allowed); } /* Verify market's block number equals current block number */ if (accrualBlockNumber != getBlockNumber()) { revert RepayBorrowFreshnessCheck(); } /* We fetch the amount the borrower owes, with accumulated interest */ uint accountBorrowsPrev = borrowBalanceStoredInternal(borrower); /* If repayAmount == -1, repayAmount = accountBorrows */ uint repayAmountFinal = repayAmount == type(uint).max ? accountBorrowsPrev : repayAmount; ///////////////////////// // EFFECTS & INTERACTIONS // (No safe failures beyond this point) /* * We call doTransferIn for the payer and the repayAmount * Note: The cToken must handle variations between ERC-20 and ETH underlying. * On success, the cToken holds an additional repayAmount of cash. * 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. */ uint actualRepayAmount = doTransferIn(payer, repayAmountFinal); /* * We calculate the new borrower and total borrow balances, failing on underflow: * accountBorrowsNew = accountBorrows - actualRepayAmount * totalBorrowsNew = totalBorrows - actualRepayAmount */ uint accountBorrowsNew = accountBorrowsPrev - actualRepayAmount; uint totalBorrowsNew = totalBorrows - actualRepayAmount; /* We write the previously calculated values into storage */ accountBorrows[borrower].principal = accountBorrowsNew; accountBorrows[borrower].interestIndex = borrowIndex; totalBorrows = totalBorrowsNew; /* We emit a RepayBorrow event */ emit RepayBorrow(payer, borrower, actualRepayAmount, accountBorrowsNew, totalBorrowsNew); return actualRepayAmount; } /** * @notice The sender liquidates the borrowers collateral. * The collateral seized is transferred to the liquidator. * @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 */ function liquidateBorrowInternal(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) internal nonReentrant { accrueInterest(); 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 revert LiquidateAccrueCollateralInterestFailed(error); } // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to liquidateBorrowFresh(msg.sender, borrower, repayAmount, cTokenCollateral); } /** * @notice The liquidator liquidates the borrowers collateral. * The collateral seized is transferred to the liquidator. * @param borrower The borrower of this cToken to be liquidated * @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 */ 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) { revert LiquidateComptrollerRejection(allowed); } /* Verify market's block number equals current block number */ if (accrualBlockNumber != getBlockNumber()) { revert LiquidateFreshnessCheck(); } /* Verify cTokenCollateral market's block number equals current block number */ if (cTokenCollateral.accrualBlockNumber() != getBlockNumber()) { revert LiquidateCollateralFreshnessCheck(); } /* Fail if borrower = liquidator */ if (borrower == liquidator) { revert LiquidateLiquidatorIsBorrower(); } /* Fail if repayAmount = 0 */ if (repayAmount == 0) { revert LiquidateCloseAmountIsZero(); } /* Fail if repayAmount = -1 */ if (repayAmount == type(uint).max) { revert LiquidateCloseAmountIsUintMax(); } /* Fail if repayBorrow fails */ uint actualRepayAmount = repayBorrowFresh(liquidator, borrower, repayAmount); ///////////////////////// // EFFECTS & INTERACTIONS // (No safe failures beyond this point) /* We calculate the number of collateral tokens that will be seized */ (uint amountSeizeError, uint seizeTokens) = comptroller.liquidateCalculateSeizeTokens(address(this), address(cTokenCollateral), actualRepayAmount); 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 if (address(cTokenCollateral) == address(this)) { seizeInternal(address(this), liquidator, borrower, seizeTokens); } else { require(cTokenCollateral.seize(liquidator, borrower, seizeTokens) == NO_ERROR, "token seizure failed"); } /* We emit a LiquidateBorrow event */ emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(cTokenCollateral), seizeTokens); } /** * @notice Transfers collateral tokens (this market) to the liquidator. * @dev Will fail unless called by another cToken during the process of liquidation. * Its absolutely critical to use msg.sender as the borrowed cToken and not a parameter. * @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 seize(address liquidator, address borrower, uint seizeTokens) override external nonReentrant returns (uint) { seizeInternal(msg.sender, liquidator, borrower, seizeTokens); return NO_ERROR; } /** * @notice Transfers collateral tokens (this market) to the liquidator. * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another CToken. * Its absolutely critical to use msg.sender as the seizer cToken and not a parameter. * @param seizerToken The contract seizing the collateral (i.e. borrowed cToken) * @param liquidator The account receiving seized collateral * @param borrower The account having collateral seized * @param seizeTokens The number of cTokens to seize */ 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) { revert LiquidateSeizeComptrollerRejection(allowed); } /* Fail if borrower = liquidator */ if (borrower == liquidator) { revert LiquidateSeizeLiquidatorIsBorrower(); } /* * We calculate the new borrower and liquidator token balances, failing on underflow/overflow: * borrowerTokensNew = accountTokens[borrower] - seizeTokens * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens */ 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; ///////////////////////// // EFFECTS & INTERACTIONS // (No safe failures beyond this point) /* 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, liquidatorSeizeTokens); emit Transfer(borrower, address(this), protocolSeizeTokens); emit ReservesAdded(address(this), protocolSeizeAmount, totalReservesNew); } /*** Admin Functions ***/ /** * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer. * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer. * @param newPendingAdmin New pending admin. * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function _setPendingAdmin(address payable newPendingAdmin) override external returns (uint) { // Check caller = admin if (msg.sender != admin) { revert SetPendingAdminOwnerCheck(); } // Save current value, if any, for inclusion in log address oldPendingAdmin = pendingAdmin; // Store pendingAdmin with value newPendingAdmin pendingAdmin = newPendingAdmin; // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin) emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin); return NO_ERROR; } /** * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin * @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() override external returns (uint) { // Check caller is pendingAdmin and pendingAdmin ≠ address(0) if (msg.sender != pendingAdmin || msg.sender == address(0)) { revert AcceptAdminPendingAdminCheck(); } // Save current values for inclusion in log address oldAdmin = admin; address oldPendingAdmin = pendingAdmin; // Store admin with value pendingAdmin admin = pendingAdmin; // Clear the pending value pendingAdmin = payable(address(0)); emit NewAdmin(oldAdmin, admin); emit NewPendingAdmin(oldPendingAdmin, pendingAdmin); return NO_ERROR; } /** * @notice Sets a new comptroller for the market * @dev Admin function to set a new comptroller * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function _setComptroller(ComptrollerInterface newComptroller) override public returns (uint) { // Check caller is admin if (msg.sender != admin) { revert SetComptrollerOwnerCheck(); } ComptrollerInterface oldComptroller = comptroller; // Ensure invoke comptroller.isComptroller() returns true require(newComptroller.isComptroller(), "marker method returned false"); // Set market's comptroller to newComptroller comptroller = newComptroller; // Emit NewComptroller(oldComptroller, newComptroller) emit NewComptroller(oldComptroller, newComptroller); return NO_ERROR; } /** * @notice accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh * @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) override external nonReentrant returns (uint) { accrueInterest(); // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to. return _setReserveFactorFresh(newReserveFactorMantissa); } /** * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual) * @dev Admin function to set a new reserve factor * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) { // Check caller is admin if (msg.sender != admin) { revert SetReserveFactorAdminCheck(); } // Verify market's block number equals current block number if (accrualBlockNumber != getBlockNumber()) { revert SetReserveFactorFreshCheck(); } // Check newReserveFactor ≤ maxReserveFactor if (newReserveFactorMantissa > reserveFactorMaxMantissa) { revert SetReserveFactorBoundsCheck(); } uint oldReserveFactorMantissa = reserveFactorMantissa; reserveFactorMantissa = newReserveFactorMantissa; emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa); return NO_ERROR; } /** * @notice Accrues interest and reduces reserves by transferring from msg.sender * @param addAmount Amount of addition to reserves * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) { accrueInterest(); // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to. _addReservesFresh(addAmount); return NO_ERROR; } /** * @notice Add reserves by transferring from caller * @dev Requires fresh interest accrual * @param addAmount Amount of addition to reserves * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees */ function _addReservesFresh(uint addAmount) internal returns (uint, uint) { // totalReserves + actualAddAmount uint totalReservesNew; uint actualAddAmount; // We fail gracefully unless market's block number equals current block number if (accrualBlockNumber != getBlockNumber()) { revert AddReservesFactorFreshCheck(actualAddAmount); } ///////////////////////// // EFFECTS & INTERACTIONS // (No safe failures beyond this point) /* * We call doTransferIn for the caller and the addAmount * Note: The cToken must handle variations between ERC-20 and ETH underlying. * On success, the cToken holds an additional addAmount of cash. * 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. */ actualAddAmount = doTransferIn(msg.sender, addAmount); totalReservesNew = totalReserves + actualAddAmount; // Store reserves[n+1] = reserves[n] + actualAddAmount totalReserves = totalReservesNew; /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */ emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew); /* Return (NO_ERROR, actualAddAmount) */ return (NO_ERROR, actualAddAmount); } /** * @notice Accrues interest and reduces reserves by transferring to admin * @param reduceAmount Amount of reduction to reserves * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ 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); } /** * @notice Reduces reserves by transferring to admin * @dev Requires fresh interest accrual * @param reduceAmount Amount of reduction to reserves * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function _reduceReservesFresh(uint reduceAmount) internal returns (uint) { // totalReserves - reduceAmount uint totalReservesNew; // Check caller is admin if (msg.sender != admin) { revert ReduceReservesAdminCheck(); } // We fail gracefully unless market's block number equals current block number if (accrualBlockNumber != getBlockNumber()) { revert ReduceReservesFreshCheck(); } // Fail gracefully if protocol has insufficient underlying cash if (getCashPrior() < reduceAmount) { revert ReduceReservesCashNotAvailable(); } // Check reduceAmount ≤ reserves[n] (totalReserves) if (reduceAmount > totalReserves) { revert ReduceReservesCashValidation(); } ///////////////////////// // EFFECTS & INTERACTIONS // (No safe failures beyond this point) totalReservesNew = totalReserves - reduceAmount; // Store reserves[n+1] = reserves[n] - reduceAmount totalReserves = totalReservesNew; // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred. doTransferOut(admin, reduceAmount); emit ReservesReduced(admin, reduceAmount, totalReservesNew); return NO_ERROR; } /** * @notice accrues interest and updates the interest rate model using _setInterestRateModelFresh * @dev Admin function to accrue interest and update the interest rate model * @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) override public returns (uint) { accrueInterest(); // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to. return _setInterestRateModelFresh(newInterestRateModel); } /** * @notice updates the interest rate model (*requires fresh interest accrual) * @dev Admin function to update the interest rate model * @param newInterestRateModel the new interest rate model to use * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal returns (uint) { // Used to store old model for use in the event that is emitted on success InterestRateModel oldInterestRateModel; // Check caller is admin if (msg.sender != admin) { revert SetInterestRateModelOwnerCheck(); } // We fail gracefully unless market's block number equals current block number if (accrualBlockNumber != getBlockNumber()) { revert SetInterestRateModelFreshCheck(); } // Track the market's current interest rate model oldInterestRateModel = interestRateModel; // Ensure invoke newInterestRateModel.isInterestRateModel() returns true require(newInterestRateModel.isInterestRateModel(), "marker method returned false"); // Set the interest rate model to newInterestRateModel interestRateModel = newInterestRateModel; // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel) emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel); return NO_ERROR; } /*** Safe Token ***/ /** * @notice Gets balance of this contract in terms of the underlying * @dev This excludes the value of the current message, if any * @return The quantity of underlying owned by this contract */ 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) virtual internal returns (uint); /** * @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) virtual internal; /*** Reentrancy Guard ***/ /** * @dev Prevents a contract from calling itself, directly or indirectly. */ modifier nonReentrant() { require(_notEntered, "re-entered"); _notEntered = false; _; _notEntered = true; // get a gas-refund post-Istanbul } } interface CompLike { function delegate(address delegatee) external; } /** * @title Compound's CErc20 Contract * @notice CTokens which wrap an EIP-20 underlying * @author Compound */ contract CErc20 is CToken, CErc20Interface { /** * @notice Initialize the new money market * @param underlying_ The address of the underlying asset * @param comptroller_ The address of the Comptroller * @param interestRateModel_ The address of the interest rate model * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18 * @param name_ ERC-20 name of this token * @param symbol_ ERC-20 symbol of this token * @param decimals_ ERC-20 decimal precision of this token */ function initialize(address underlying_, ComptrollerInterface comptroller_, InterestRateModel interestRateModel_, uint initialExchangeRateMantissa_, string memory name_, string memory symbol_, uint8 decimals_) public { // CToken initialize does the bulk of the work super.initialize(comptroller_, interestRateModel_, initialExchangeRateMantissa_, name_, symbol_, decimals_); // Set underlying and sanity check it underlying = underlying_; EIP20Interface(underlying).totalSupply(); } /*** User Interface ***/ /** * @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 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function mint(uint mintAmount) override external returns (uint) { mintInternal(mintAmount); return NO_ERROR; } /** * @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 redeem(uint redeemTokens) override external returns (uint) { redeemInternal(redeemTokens); return NO_ERROR; } /** * @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 redeem * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function redeemUnderlying(uint redeemAmount) override external returns (uint) { redeemUnderlyingInternal(redeemAmount); return NO_ERROR; } /** * @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 borrow(uint borrowAmount) override external returns (uint) { borrowInternal(borrowAmount); return NO_ERROR; } /** * @notice Sender repays their own borrow * @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) 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, 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) override external returns (uint) { repayBorrowBehalfInternal(borrower, repayAmount); return NO_ERROR; } /** * @notice The sender liquidates the borrowers collateral. * The collateral seized is transferred to the liquidator. * @param borrower The borrower of this cToken to be liquidated * @param repayAmount The amount of the underlying borrowed asset to repay * @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) 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) 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); } /** * @notice The sender adds to reserves. * @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) override external returns (uint) { return _addReservesInternal(addAmount); } /*** Safe Token ***/ /** * @notice Gets balance of this contract in terms of the underlying * @dev This excludes the value of the current message, if any * @return The quantity of underlying tokens owned by this contract */ function getCashPrior() virtual override internal view returns (uint) { EIP20Interface token = EIP20Interface(underlying); return token.balanceOf(address(this)); } /** * @dev Similar to EIP20 transfer, except it handles a False result from `transferFrom` and reverts in that case. * This will revert due to insufficient balance or insufficient allowance. * This function returns the actual amount received, * which may be less than `amount` if there is a fee attached to the transfer. * * 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) 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; assembly { switch returndatasize() case 0 { // This is a non-standard ERC-20 success := not(0) // set success to true } case 32 { // This is a compliant ERC-20 returndatacopy(0, 0, 32) success := mload(0) // Set `success = returndata` of override external call } default { // This is an excessively non-compliant ERC-20, revert. revert(0, 0) } } require(success, "TOKEN_TRANSFER_IN_FAILED"); // Calculate the amount that was *actually* transferred uint balanceAfter = EIP20Interface(underlying_).balanceOf(address(this)); return balanceAfter - balanceBefore; // underflow already checked above, just subtract } /** * @dev Similar to EIP20 transfer, except it handles a False success from `transfer` and returns an explanatory * error code rather than reverting. If caller has not called checked protocol's balance, this may revert due to * insufficient cash held in this contract. If caller has checked protocol's balance prior to this call, and verified * it is >= amount, this should not revert in normal conditions. * * 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) virtual override internal { EIP20NonStandardInterface token = EIP20NonStandardInterface(underlying); token.transfer(to, amount); bool success; assembly { switch returndatasize() case 0 { // This is a non-standard ERC-20 success := not(0) // set success to true } case 32 { // This is a compliant ERC-20 returndatacopy(0, 0, 32) success := mload(0) // Set `success = returndata` of override external call } default { // This is an excessively non-compliant ERC-20, revert. revert(0, 0) } } require(success, "TOKEN_TRANSFER_OUT_FAILED"); } /** * @notice Admin call to delegate the votes of the COMP-like underlying * @param compLikeDelegatee The address to delegate votes to * @dev CTokens whose underlying are not CompLike should revert here */ function _delegateCompLikeTo(address compLikeDelegatee) external { require(msg.sender == admin, "only the admin may set the comp-like delegate"); CompLike(underlying).delegate(compLikeDelegatee); } } abstract contract PriceOracle { /// @notice Indicator that this is a PriceOracle contract (for inspection) bool public constant isPriceOracle = true; /** * @notice Get the underlying price of a cToken asset * @param cToken The cToken to get the underlying price of * @return The underlying asset price mantissa (scaled by 1e18). * Zero means the price is unavailable. */ function getUnderlyingPrice(CToken cToken) virtual external view returns (uint); } contract GovernorAlpha { /// @notice The name of this contract string public constant name = "Compound Governor Alpha"; /// @notice The number of votes in support of a proposal required in order for a quorum to be reached and for a vote to succeed function quorumVotes() public pure returns (uint) { return 400000e18; } // 400,000 = 4% of Comp /// @notice The number of votes required in order for a voter to become a proposer function proposalThreshold() public pure returns (uint) { return 100000e18; } // 100,000 = 1% of Comp /// @notice The maximum number of actions that can be included in a proposal function proposalMaxOperations() public pure returns (uint) { return 10; } // 10 actions /// @notice The delay before voting on a proposal may take place, once proposed function votingDelay() public pure returns (uint) { return 1; } // 1 block /// @notice The duration of voting on a proposal, in 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; /// @notice The address of the Compound governance token CompInterface public comp; /// @notice The address of the Governor Guardian address public guardian; /// @notice The total number of proposals uint public proposalCount; struct Proposal { /// @notice Unique id for looking up a proposal uint id; /// @notice Creator of the proposal address proposer; /// @notice The timestamp that the proposal will be available for execution, set once the vote succeeds uint eta; /// @notice the ordered list of target addresses for calls to be made address[] targets; /// @notice The ordered list of values (i.e. msg.value) to be passed to the calls to be made uint[] values; /// @notice The ordered list of function signatures to be called string[] signatures; /// @notice The ordered list of calldata to be passed to each call bytes[] calldatas; /// @notice The block at which voting begins: holders must delegate their votes prior to this block uint startBlock; /// @notice The block at which voting ends: votes must be cast prior to this block uint endBlock; /// @notice Current number of votes in favor of this proposal uint forVotes; /// @notice Current number of votes in opposition to this proposal uint againstVotes; /// @notice Flag marking whether the proposal has been canceled bool canceled; /// @notice Flag marking whether the proposal has been executed bool executed; /// @notice Receipts of ballots for the entire set of voters mapping (address => Receipt) receipts; } /// @notice Ballot receipt record for a voter struct Receipt { /// @notice Whether or not a vote has been cast bool hasVoted; /// @notice Whether or not the voter supports the proposal bool support; /// @notice The number of votes the voter had, which were cast uint96 votes; } /// @notice Possible states that a proposal may be in enum ProposalState { Pending, Active, Canceled, Defeated, Succeeded, Queued, Expired, Executed } /// @notice The official record of all proposals ever proposed mapping (uint => Proposal) public proposals; /// @notice The latest proposal for each proposer mapping (address => uint) public latestProposalIds; /// @notice The EIP-712 typehash for the contract's domain bytes32 public constant DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)"); /// @notice The EIP-712 typehash for the ballot struct used by the contract bytes32 public constant BALLOT_TYPEHASH = keccak256("Ballot(uint256 proposalId,bool support)"); /// @notice An event emitted when a new proposal is created event ProposalCreated(uint id, address proposer, address[] targets, uint[] values, string[] signatures, bytes[] calldatas, uint startBlock, uint endBlock, string description); /// @notice An event emitted when a vote has been cast on a proposal event VoteCast(address voter, uint proposalId, bool support, uint votes); /// @notice An event emitted when a proposal has been canceled event ProposalCanceled(uint id); /// @notice An event emitted when a proposal has been queued in the Timelock event ProposalQueued(uint id, uint eta); /// @notice An event emitted when a proposal has been executed in the Timelock event ProposalExecuted(uint id); constructor(address timelock_, address comp_, address guardian_) public { timelock = TimelockInterface(timelock_); comp = CompInterface(comp_); guardian = guardian_; } function propose(address[] memory targets, uint[] memory values, string[] memory signatures, bytes[] memory calldatas, string memory description) public returns (uint) { require(comp.getPriorVotes(msg.sender, sub256(block.number, 1)) > proposalThreshold(), "GovernorAlpha::propose: proposer votes below proposal threshold"); require(targets.length == values.length && targets.length == signatures.length && targets.length == calldatas.length, "GovernorAlpha::propose: proposal function information arity mismatch"); require(targets.length != 0, "GovernorAlpha::propose: must provide actions"); require(targets.length <= proposalMaxOperations(), "GovernorAlpha::propose: too many actions"); uint latestProposalId = latestProposalIds[msg.sender]; if (latestProposalId != 0) { ProposalState proposersLatestProposalState = state(latestProposalId); require(proposersLatestProposalState != ProposalState.Active, "GovernorAlpha::propose: one live proposal per proposer, found an already active proposal"); require(proposersLatestProposalState != ProposalState.Pending, "GovernorAlpha::propose: one live proposal per proposer, found an already pending proposal"); } uint startBlock = add256(block.number, votingDelay()); uint endBlock = add256(startBlock, votingPeriod()); proposalCount++; 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); return newProposal.id; } function queue(uint proposalId) public { require(state(proposalId) == ProposalState.Succeeded, "GovernorAlpha::queue: proposal can only be queued if it is succeeded"); Proposal storage proposal = proposals[proposalId]; uint eta = add256(block.timestamp, timelock.delay()); for (uint i = 0; i < proposal.targets.length; i++) { _queueOrRevert(proposal.targets[i], proposal.values[i], proposal.signatures[i], proposal.calldatas[i], eta); } proposal.eta = eta; emit ProposalQueued(proposalId, eta); } function _queueOrRevert(address target, uint value, string memory signature, bytes memory data, uint eta) internal { require(!timelock.queuedTransactions(keccak256(abi.encode(target, value, signature, data, eta))), "GovernorAlpha::_queueOrRevert: proposal action already queued at eta"); timelock.queueTransaction(target, value, signature, data, eta); } function execute(uint proposalId) public payable { require(state(proposalId) == ProposalState.Queued, "GovernorAlpha::execute: proposal can only be executed if it is queued"); 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); } emit ProposalExecuted(proposalId); } function cancel(uint proposalId) public { ProposalState state = state(proposalId); require(state != ProposalState.Executed, "GovernorAlpha::cancel: cannot cancel executed proposal"); Proposal storage proposal = proposals[proposalId]; require(msg.sender == guardian || comp.getPriorVotes(proposal.proposer, sub256(block.number, 1)) < proposalThreshold(), "GovernorAlpha::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); } emit ProposalCanceled(proposalId); } function getActions(uint proposalId) public view returns (address[] memory targets, uint[] memory values, string[] memory signatures, bytes[] memory calldatas) { Proposal storage p = proposals[proposalId]; return (p.targets, p.values, p.signatures, p.calldatas); } function getReceipt(uint proposalId, address voter) public view returns (Receipt memory) { return proposals[proposalId].receipts[voter]; } function state(uint proposalId) public view returns (ProposalState) { require(proposalCount >= proposalId && proposalId > 0, "GovernorAlpha::state: invalid proposal id"); Proposal storage proposal = proposals[proposalId]; if (proposal.canceled) { return ProposalState.Canceled; } else if (block.number <= proposal.startBlock) { return ProposalState.Pending; } else if (block.number <= proposal.endBlock) { return ProposalState.Active; } else if (proposal.forVotes <= proposal.againstVotes || proposal.forVotes < quorumVotes()) { return ProposalState.Defeated; } else if (proposal.eta == 0) { return ProposalState.Succeeded; } else if (proposal.executed) { return ProposalState.Executed; } else if (block.timestamp >= add256(proposal.eta, timelock.GRACE_PERIOD())) { return ProposalState.Expired; } else { return ProposalState.Queued; } } function castVote(uint proposalId, bool support) public { return _castVote(msg.sender, proposalId, support); } function castVoteBySig(uint proposalId, bool support, uint8 v, bytes32 r, bytes32 s) public { bytes32 domainSeparator = keccak256(abi.encode(DOMAIN_TYPEHASH, keccak256(bytes(name)), getChainId(), address(this))); bytes32 structHash = keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support)); bytes32 digest = keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); address signatory = ecrecover(digest, v, r, s); require(signatory != address(0), "GovernorAlpha::castVoteBySig: invalid signature"); return _castVote(signatory, proposalId, support); } function _castVote(address voter, uint proposalId, bool support) internal { require(state(proposalId) == ProposalState.Active, "GovernorAlpha::_castVote: voting is closed"); Proposal storage proposal = proposals[proposalId]; Receipt storage receipt = proposal.receipts[voter]; require(receipt.hasVoted == false, "GovernorAlpha::_castVote: voter already voted"); uint96 votes = comp.getPriorVotes(voter, proposal.startBlock); if (support) { proposal.forVotes = add256(proposal.forVotes, votes); } else { proposal.againstVotes = add256(proposal.againstVotes, votes); } receipt.hasVoted = true; receipt.support = support; receipt.votes = votes; emit VoteCast(voter, proposalId, support, votes); } function __acceptAdmin() public { require(msg.sender == guardian, "GovernorAlpha::__acceptAdmin: sender must be gov guardian"); timelock.acceptAdmin(); } function __abdicate() public { require(msg.sender == guardian, "GovernorAlpha::__abdicate: sender must be gov guardian"); guardian = address(0); } function __queueSetTimelockPendingAdmin(address newPendingAdmin, uint eta) public { require(msg.sender == guardian, "GovernorAlpha::__queueSetTimelockPendingAdmin: sender must be gov guardian"); timelock.queueTransaction(address(timelock), 0, "setPendingAdmin(address)", abi.encode(newPendingAdmin), eta); } function __executeSetTimelockPendingAdmin(address newPendingAdmin, uint eta) public { require(msg.sender == guardian, "GovernorAlpha::__executeSetTimelockPendingAdmin: sender must be gov guardian"); timelock.executeTransaction(address(timelock), 0, "setPendingAdmin(address)", abi.encode(newPendingAdmin), eta); } function add256(uint256 a, uint256 b) internal pure returns (uint) { uint c = a + b; require(c >= a, "addition overflow"); return c; } function sub256(uint256 a, uint256 b) internal pure returns (uint) { require(b <= a, "subtraction underflow"); return a - b; } function getChainId() internal view returns (uint) { uint chainId; assembly { chainId := chainid() } return chainId; } } interface TimelockInterface { function delay() external view returns (uint); function GRACE_PERIOD() external view returns (uint); function acceptAdmin() external; function queuedTransactions(bytes32 hash) external view returns (bool); function queueTransaction(address target, uint value, string calldata signature, bytes calldata data, uint eta) external returns (bytes32); function cancelTransaction(address target, uint value, string calldata signature, bytes calldata data, uint eta) external; function executeTransaction(address target, uint value, string calldata signature, bytes calldata data, uint eta) external payable returns (bytes memory); } interface CompInterface { function getPriorVotes(address account, uint blockNumber) external view returns (uint96); } contract Comp { /// @notice EIP-20 token name for this token string public constant name = "Compound"; /// @notice EIP-20 token symbol for this token string public constant symbol = "COMP"; /// @notice EIP-20 token decimals for this token uint8 public constant decimals = 18; /// @notice Total number of tokens in circulation uint public constant totalSupply = 10000000e18; // 10 million Comp /// @notice Allowance amounts on behalf of others mapping (address => mapping (address => uint96)) internal allowances; /// @notice Official record of token balances for each account mapping (address => uint96) internal balances; /// @notice A record of each accounts delegate mapping (address => address) public delegates; /// @notice A checkpoint for marking number of votes from a given block struct Checkpoint { uint32 fromBlock; uint96 votes; } /// @notice A record of votes checkpoints for each account, by index mapping (address => mapping (uint32 => Checkpoint)) public checkpoints; /// @notice The number of checkpoints for each account mapping (address => uint32) public numCheckpoints; /// @notice The EIP-712 typehash for the contract's domain bytes32 public constant DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)"); /// @notice The EIP-712 typehash for the delegation struct used by the contract bytes32 public constant DELEGATION_TYPEHASH = keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); /// @notice A record of states for signing / validating signatures mapping (address => uint) public nonces; /// @notice An event thats emitted when an account changes its delegate event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate); /// @notice An event thats emitted when a delegate account's vote balance changes event DelegateVotesChanged(address indexed delegate, uint previousBalance, uint newBalance); /// @notice The standard EIP-20 transfer event event Transfer(address indexed from, address indexed to, uint256 amount); /// @notice The standard EIP-20 approval event event Approval(address indexed owner, address indexed spender, uint256 amount); /** * @notice Construct a new Comp token * @param account The initial account to grant all the tokens */ constructor(address account) public { balances[account] = uint96(totalSupply); emit Transfer(address(0), account, totalSupply); } /** * @notice Get the number of tokens `spender` is approved to spend on behalf of `account` * @param account The address of the account holding the funds * @param spender The address of the account spending the funds * @return The number of tokens approved */ function allowance(address account, address spender) external view returns (uint) { return allowances[account][spender]; } /** * @notice Approve `spender` to transfer up to `amount` from `src` * @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 rawAmount The number of tokens that are approved (2^256-1 means infinite) * @return Whether or not the approval succeeded */ function approve(address spender, uint rawAmount) external returns (bool) { uint96 amount; if (rawAmount == type(uint).max) { amount = type(uint96).max; } else { amount = safe96(rawAmount, "Comp::approve: amount exceeds 96 bits"); } allowances[msg.sender][spender] = amount; emit Approval(msg.sender, spender, amount); return true; } /** * @notice Get the number of tokens held by the `account` * @param account The address of the account to get the balance of * @return The number of tokens held */ function balanceOf(address account) external view returns (uint) { return balances[account]; } /** * @notice Transfer `amount` tokens from `msg.sender` to `dst` * @param dst The address of the destination account * @param rawAmount The number of tokens to transfer * @return Whether or not the transfer succeeded */ function transfer(address dst, uint rawAmount) external returns (bool) { uint96 amount = safe96(rawAmount, "Comp::transfer: amount exceeds 96 bits"); _transferTokens(msg.sender, dst, amount); return true; } /** * @notice Transfer `amount` tokens from `src` to `dst` * @param src The address of the source account * @param dst The address of the destination account * @param rawAmount The number of tokens to transfer * @return Whether or not the transfer succeeded */ function transferFrom(address src, address dst, uint rawAmount) external returns (bool) { address spender = msg.sender; uint96 spenderAllowance = allowances[src][spender]; uint96 amount = safe96(rawAmount, "Comp::approve: amount exceeds 96 bits"); if (spender != src && spenderAllowance != type(uint96).max) { uint96 newAllowance = sub96(spenderAllowance, amount, "Comp::transferFrom: transfer amount exceeds spender allowance"); allowances[src][spender] = newAllowance; emit Approval(src, spender, newAllowance); } _transferTokens(src, dst, amount); return true; } /** * @notice Delegate votes from `msg.sender` to `delegatee` * @param delegatee The address to delegate votes to */ function delegate(address delegatee) public { return _delegate(msg.sender, delegatee); } /** * @notice Delegates votes from signatory to `delegatee` * @param delegatee The address to delegate votes to * @param nonce The contract state required to match the signature * @param expiry The time at which to expire the signature * @param v The recovery byte of the signature * @param r Half of the ECDSA signature pair * @param s Half of the ECDSA signature pair */ function delegateBySig(address delegatee, uint nonce, uint expiry, uint8 v, bytes32 r, bytes32 s) public { bytes32 domainSeparator = keccak256(abi.encode(DOMAIN_TYPEHASH, keccak256(bytes(name)), getChainId(), address(this))); bytes32 structHash = keccak256(abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)); bytes32 digest = keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); address signatory = ecrecover(digest, v, r, s); require(signatory != address(0), "Comp::delegateBySig: invalid signature"); require(nonce == nonces[signatory]++, "Comp::delegateBySig: invalid nonce"); require(block.timestamp <= expiry, "Comp::delegateBySig: signature expired"); return _delegate(signatory, delegatee); } /** * @notice Gets the current votes balance for `account` * @param account The address to get votes balance * @return The number of current votes for `account` */ function getCurrentVotes(address account) external view returns (uint96) { uint32 nCheckpoints = numCheckpoints[account]; return nCheckpoints > 0 ? checkpoints[account][nCheckpoints - 1].votes : 0; } /** * @notice Determine the prior number of votes for an account as of a block number * @dev Block number must be a finalized block or else this function will revert to prevent misinformation. * @param account The address of the account to check * @param blockNumber The block number to get the vote balance at * @return The number of votes the account had as of the given block */ function getPriorVotes(address account, uint blockNumber) public view returns (uint96) { require(blockNumber < block.number, "Comp::getPriorVotes: not yet determined"); uint32 nCheckpoints = numCheckpoints[account]; if (nCheckpoints == 0) { return 0; } // First check most recent balance if (checkpoints[account][nCheckpoints - 1].fromBlock <= blockNumber) { return checkpoints[account][nCheckpoints - 1].votes; } // Next check implicit zero balance if (checkpoints[account][0].fromBlock > blockNumber) { return 0; } uint32 lower = 0; uint32 upper = nCheckpoints - 1; while (upper > lower) { uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow Checkpoint memory cp = checkpoints[account][center]; if (cp.fromBlock == blockNumber) { return cp.votes; } else if (cp.fromBlock < blockNumber) { lower = center; } else { upper = center - 1; } } return checkpoints[account][lower].votes; } function _delegate(address delegator, address delegatee) internal { address currentDelegate = delegates[delegator]; uint96 delegatorBalance = balances[delegator]; delegates[delegator] = delegatee; emit DelegateChanged(delegator, currentDelegate, delegatee); _moveDelegates(currentDelegate, delegatee, delegatorBalance); } function _transferTokens(address src, address dst, uint96 amount) internal { require(src != address(0), "Comp::_transferTokens: cannot transfer from the zero address"); require(dst != address(0), "Comp::_transferTokens: cannot transfer to the zero address"); balances[src] = sub96(balances[src], amount, "Comp::_transferTokens: transfer amount exceeds balance"); balances[dst] = add96(balances[dst], amount, "Comp::_transferTokens: transfer amount overflows"); emit Transfer(src, dst, amount); _moveDelegates(delegates[src], delegates[dst], amount); } function _moveDelegates(address srcRep, address dstRep, uint96 amount) internal { if (srcRep != dstRep && amount > 0) { if (srcRep != address(0)) { uint32 srcRepNum = numCheckpoints[srcRep]; uint96 srcRepOld = srcRepNum > 0 ? checkpoints[srcRep][srcRepNum - 1].votes : 0; uint96 srcRepNew = sub96(srcRepOld, amount, "Comp::_moveVotes: vote amount underflows"); _writeCheckpoint(srcRep, srcRepNum, srcRepOld, srcRepNew); } if (dstRep != address(0)) { uint32 dstRepNum = numCheckpoints[dstRep]; uint96 dstRepOld = dstRepNum > 0 ? checkpoints[dstRep][dstRepNum - 1].votes : 0; uint96 dstRepNew = add96(dstRepOld, amount, "Comp::_moveVotes: vote amount overflows"); _writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew); } } } function _writeCheckpoint(address delegatee, uint32 nCheckpoints, uint96 oldVotes, uint96 newVotes) internal { uint32 blockNumber = safe32(block.number, "Comp::_writeCheckpoint: block number exceeds 32 bits"); if (nCheckpoints > 0 && checkpoints[delegatee][nCheckpoints - 1].fromBlock == blockNumber) { checkpoints[delegatee][nCheckpoints - 1].votes = newVotes; } else { checkpoints[delegatee][nCheckpoints] = Checkpoint(blockNumber, newVotes); numCheckpoints[delegatee] = nCheckpoints + 1; } emit DelegateVotesChanged(delegatee, oldVotes, newVotes); } function safe32(uint n, string memory errorMessage) internal pure returns (uint32) { require(n < 2**32, errorMessage); return uint32(n); } function safe96(uint n, string memory errorMessage) internal pure returns (uint96) { require(n < 2**96, errorMessage); return uint96(n); } function add96(uint96 a, uint96 b, string memory errorMessage) internal pure returns (uint96) { uint96 c = a + b; require(c >= a, errorMessage); return c; } function sub96(uint96 a, uint96 b, string memory errorMessage) internal pure returns (uint96) { require(b <= a, errorMessage); return a - b; } function getChainId() internal view returns (uint) { uint256 chainId; assembly { chainId := chainid() } return chainId; } } interface ComptrollerLensInterface { function markets(address) external view returns (bool, uint); function oracle() external view returns (PriceOracle); function getAccountLiquidity(address) external view returns (uint, uint, uint); function getAssetsIn(address) external view returns (CToken[] memory); function claimComp(address) external; function compAccrued(address) external view returns (uint); function compSpeeds(address) external view returns (uint); function compSupplySpeeds(address) external view returns (uint); function compBorrowSpeeds(address) external view returns (uint); function borrowCaps(address) external view returns (uint); } interface GovernorBravoInterface { struct Receipt { bool hasVoted; uint8 support; uint96 votes; } struct Proposal { uint id; address proposer; uint eta; uint startBlock; uint endBlock; uint forVotes; uint againstVotes; uint abstainVotes; bool canceled; bool executed; } function getActions(uint proposalId) external view returns (address[] memory targets, uint[] memory values, string[] memory signatures, bytes[] memory calldatas); function proposals(uint proposalId) external view returns (Proposal memory); function getReceipt(uint proposalId, address voter) external view returns (Receipt memory); } contract CompoundLens { struct CTokenMetadata { address cToken; uint exchangeRateCurrent; uint supplyRatePerBlock; uint borrowRatePerBlock; uint reserveFactorMantissa; uint totalBorrows; uint totalReserves; uint totalSupply; uint totalCash; bool isListed; uint collateralFactorMantissa; address underlyingAssetAddress; uint cTokenDecimals; uint underlyingDecimals; uint compSupplySpeed; uint compBorrowSpeed; uint borrowCap; } function getCompSpeeds(ComptrollerLensInterface comptroller, CToken cToken) internal returns (uint, uint) { // Getting comp speeds is gnarly due to not every network having the // split comp speeds from Proposal 62 and other networks don't even // have comp speeds. uint compSupplySpeed = 0; (bool compSupplySpeedSuccess, bytes memory compSupplySpeedReturnData) = address(comptroller).call( abi.encodePacked( comptroller.compSupplySpeeds.selector, abi.encode(address(cToken)) ) ); if (compSupplySpeedSuccess) { compSupplySpeed = abi.decode(compSupplySpeedReturnData, (uint)); } uint compBorrowSpeed = 0; (bool compBorrowSpeedSuccess, bytes memory compBorrowSpeedReturnData) = address(comptroller).call( abi.encodePacked( comptroller.compBorrowSpeeds.selector, abi.encode(address(cToken)) ) ); if (compBorrowSpeedSuccess) { compBorrowSpeed = abi.decode(compBorrowSpeedReturnData, (uint)); } // If the split comp speeds call doesn't work, try the oldest non-spit version. if (!compSupplySpeedSuccess || !compBorrowSpeedSuccess) { (bool compSpeedSuccess, bytes memory compSpeedReturnData) = address(comptroller).call( abi.encodePacked( comptroller.compSpeeds.selector, abi.encode(address(cToken)) ) ); if (compSpeedSuccess) { compSupplySpeed = compBorrowSpeed = abi.decode(compSpeedReturnData, (uint)); } } return (compSupplySpeed, compBorrowSpeed); } function cTokenMetadata(CToken cToken) public returns (CTokenMetadata memory) { uint exchangeRateCurrent = cToken.exchangeRateCurrent(); ComptrollerLensInterface comptroller = ComptrollerLensInterface(address(cToken.comptroller())); (bool isListed, uint collateralFactorMantissa) = comptroller.markets(address(cToken)); address underlyingAssetAddress; uint underlyingDecimals; if (compareStrings(cToken.symbol(), "bBTT")) { underlyingAssetAddress = address(0); underlyingDecimals = 18; } else { CErc20 cErc20 = CErc20(address(cToken)); underlyingAssetAddress = cErc20.underlying(); underlyingDecimals = EIP20Interface(cErc20.underlying()).decimals(); } (uint compSupplySpeed, uint compBorrowSpeed) = getCompSpeeds(comptroller, cToken); uint borrowCap = 0; (bool borrowCapSuccess, bytes memory borrowCapReturnData) = address(comptroller).call( abi.encodePacked( comptroller.borrowCaps.selector, abi.encode(address(cToken)) ) ); if (borrowCapSuccess) { borrowCap = abi.decode(borrowCapReturnData, (uint)); } return CTokenMetadata({ cToken: address(cToken), exchangeRateCurrent: exchangeRateCurrent, supplyRatePerBlock: cToken.supplyRatePerBlock(), borrowRatePerBlock: cToken.borrowRatePerBlock(), reserveFactorMantissa: cToken.reserveFactorMantissa(), totalBorrows: cToken.totalBorrows(), totalReserves: cToken.totalReserves(), totalSupply: cToken.totalSupply(), totalCash: cToken.getCash(), isListed: isListed, collateralFactorMantissa: collateralFactorMantissa, underlyingAssetAddress: underlyingAssetAddress, cTokenDecimals: cToken.decimals(), underlyingDecimals: underlyingDecimals, compSupplySpeed: compSupplySpeed, compBorrowSpeed: compBorrowSpeed, borrowCap: borrowCap }); } function cTokenMetadataAll(CToken[] calldata cTokens) external returns (CTokenMetadata[] memory) { uint cTokenCount = cTokens.length; CTokenMetadata[] memory res = new CTokenMetadata[](cTokenCount); for (uint i = 0; i < cTokenCount; i++) { res[i] = cTokenMetadata(cTokens[i]); } return res; } struct CTokenBalances { address cToken; uint balanceOf; uint borrowBalanceCurrent; uint balanceOfUnderlying; uint tokenBalance; uint tokenAllowance; } function cTokenBalances(CToken cToken, address payable account) public returns (CTokenBalances memory) { uint balanceOf = cToken.balanceOf(account); uint borrowBalanceCurrent = cToken.borrowBalanceCurrent(account); uint balanceOfUnderlying = cToken.balanceOfUnderlying(account); uint tokenBalance; uint tokenAllowance; if (compareStrings(cToken.symbol(), "bBTT")) { tokenBalance = account.balance; tokenAllowance = account.balance; } else { CErc20 cErc20 = CErc20(address(cToken)); EIP20Interface underlying = EIP20Interface(cErc20.underlying()); tokenBalance = underlying.balanceOf(account); tokenAllowance = underlying.allowance(account, address(cToken)); } return CTokenBalances({ cToken: address(cToken), balanceOf: balanceOf, borrowBalanceCurrent: borrowBalanceCurrent, balanceOfUnderlying: balanceOfUnderlying, tokenBalance: tokenBalance, tokenAllowance: tokenAllowance }); } function cTokenBalancesAll(CToken[] calldata cTokens, address payable account) external returns (CTokenBalances[] memory) { uint cTokenCount = cTokens.length; CTokenBalances[] memory res = new CTokenBalances[](cTokenCount); for (uint i = 0; i < cTokenCount; i++) { res[i] = cTokenBalances(cTokens[i], account); } return res; } struct CTokenUnderlyingPrice { address cToken; uint underlyingPrice; } function cTokenUnderlyingPrice(CToken cToken) public returns (CTokenUnderlyingPrice memory) { ComptrollerLensInterface comptroller = ComptrollerLensInterface(address(cToken.comptroller())); PriceOracle priceOracle = comptroller.oracle(); return CTokenUnderlyingPrice({ cToken: address(cToken), underlyingPrice: priceOracle.getUnderlyingPrice(cToken) }); } function cTokenUnderlyingPriceAll(CToken[] calldata cTokens) external returns (CTokenUnderlyingPrice[] memory) { uint cTokenCount = cTokens.length; CTokenUnderlyingPrice[] memory res = new CTokenUnderlyingPrice[](cTokenCount); for (uint i = 0; i < cTokenCount; i++) { res[i] = cTokenUnderlyingPrice(cTokens[i]); } return res; } struct AccountLimits { CToken[] markets; uint liquidity; uint shortfall; } function getAccountLimits(ComptrollerLensInterface comptroller, address account) public returns (AccountLimits memory) { (uint errorCode, uint liquidity, uint shortfall) = comptroller.getAccountLiquidity(account); require(errorCode == 0); return AccountLimits({ markets: comptroller.getAssetsIn(account), liquidity: liquidity, shortfall: shortfall }); } struct GovReceipt { uint proposalId; bool hasVoted; bool support; uint96 votes; } function getGovReceipts(GovernorAlpha governor, address voter, uint[] memory proposalIds) public view returns (GovReceipt[] memory) { uint proposalCount = proposalIds.length; GovReceipt[] memory res = new GovReceipt[](proposalCount); for (uint i = 0; i < proposalCount; i++) { GovernorAlpha.Receipt memory receipt = governor.getReceipt(proposalIds[i], voter); res[i] = GovReceipt({ proposalId: proposalIds[i], hasVoted: receipt.hasVoted, support: receipt.support, votes: receipt.votes }); } return res; } struct GovBravoReceipt { uint proposalId; bool hasVoted; uint8 support; uint96 votes; } function getGovBravoReceipts(GovernorBravoInterface governor, address voter, uint[] memory proposalIds) public view returns (GovBravoReceipt[] memory) { uint proposalCount = proposalIds.length; GovBravoReceipt[] memory res = new GovBravoReceipt[](proposalCount); for (uint i = 0; i < proposalCount; i++) { GovernorBravoInterface.Receipt memory receipt = governor.getReceipt(proposalIds[i], voter); res[i] = GovBravoReceipt({ proposalId: proposalIds[i], hasVoted: receipt.hasVoted, support: receipt.support, votes: receipt.votes }); } return res; } struct GovProposal { uint proposalId; address proposer; uint eta; address[] targets; uint[] values; string[] signatures; bytes[] calldatas; uint startBlock; uint endBlock; uint forVotes; uint againstVotes; bool canceled; bool executed; } function setProposal(GovProposal memory res, GovernorAlpha governor, uint proposalId) internal view { ( , address proposer, uint eta, uint startBlock, uint endBlock, uint forVotes, uint againstVotes, bool canceled, bool executed ) = governor.proposals(proposalId); res.proposalId = proposalId; res.proposer = proposer; res.eta = eta; res.startBlock = startBlock; res.endBlock = endBlock; res.forVotes = forVotes; res.againstVotes = againstVotes; res.canceled = canceled; res.executed = executed; } function getGovProposals(GovernorAlpha governor, uint[] calldata proposalIds) external view returns (GovProposal[] memory) { GovProposal[] memory res = new GovProposal[](proposalIds.length); for (uint i = 0; i < proposalIds.length; i++) { ( address[] memory targets, uint[] memory values, string[] memory signatures, bytes[] memory calldatas ) = governor.getActions(proposalIds[i]); res[i] = GovProposal({ proposalId: 0, proposer: address(0), eta: 0, targets: targets, values: values, signatures: signatures, calldatas: calldatas, startBlock: 0, endBlock: 0, forVotes: 0, againstVotes: 0, canceled: false, executed: false }); setProposal(res[i], governor, proposalIds[i]); } return res; } struct GovBravoProposal { uint proposalId; address proposer; uint eta; address[] targets; uint[] values; string[] signatures; bytes[] calldatas; uint startBlock; uint endBlock; uint forVotes; uint againstVotes; uint abstainVotes; bool canceled; bool executed; } function setBravoProposal(GovBravoProposal memory res, GovernorBravoInterface governor, uint proposalId) internal view { GovernorBravoInterface.Proposal memory p = governor.proposals(proposalId); res.proposalId = proposalId; res.proposer = p.proposer; res.eta = p.eta; res.startBlock = p.startBlock; res.endBlock = p.endBlock; res.forVotes = p.forVotes; res.againstVotes = p.againstVotes; res.abstainVotes = p.abstainVotes; res.canceled = p.canceled; res.executed = p.executed; } function getGovBravoProposals(GovernorBravoInterface governor, uint[] calldata proposalIds) external view returns (GovBravoProposal[] memory) { GovBravoProposal[] memory res = new GovBravoProposal[](proposalIds.length); for (uint i = 0; i < proposalIds.length; i++) { ( address[] memory targets, uint[] memory values, string[] memory signatures, bytes[] memory calldatas ) = governor.getActions(proposalIds[i]); res[i] = GovBravoProposal({ proposalId: 0, proposer: address(0), eta: 0, targets: targets, values: values, signatures: signatures, calldatas: calldatas, startBlock: 0, endBlock: 0, forVotes: 0, againstVotes: 0, abstainVotes: 0, canceled: false, executed: false }); setBravoProposal(res[i], governor, proposalIds[i]); } return res; } struct CompBalanceMetadata { uint balance; uint votes; address delegate; } function getCompBalanceMetadata(Comp comp, address account) external view returns (CompBalanceMetadata memory) { return CompBalanceMetadata({ balance: comp.balanceOf(account), votes: uint256(comp.getCurrentVotes(account)), delegate: comp.delegates(account) }); } struct CompBalanceMetadataExt { uint balance; uint votes; address delegate; uint allocated; } function getCompBalanceMetadataExt(Comp comp, ComptrollerLensInterface comptroller, address account) external returns (CompBalanceMetadataExt memory) { uint balance = comp.balanceOf(account); comptroller.claimComp(account); uint newBalance = comp.balanceOf(account); uint accrued = comptroller.compAccrued(account); uint total = add(accrued, newBalance, "sum comp total"); uint allocated = sub(total, balance, "sub allocated"); return CompBalanceMetadataExt({ balance: balance, votes: uint256(comp.getCurrentVotes(account)), delegate: comp.delegates(account), allocated: allocated }); } struct CompVotes { uint blockNumber; uint votes; } function getCompVotes(Comp comp, address account, uint32[] calldata blockNumbers) external view returns (CompVotes[] memory) { CompVotes[] memory res = new CompVotes[](blockNumbers.length); for (uint i = 0; i < blockNumbers.length; i++) { res[i] = CompVotes({ blockNumber: uint256(blockNumbers[i]), votes: uint256(comp.getPriorVotes(account, blockNumbers[i])) }); } return res; } function compareStrings(string memory a, string memory b) internal pure returns (bool) { return (keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b)))); } function add(uint a, uint b, string memory errorMessage) internal pure returns (uint) { uint c = a + b; require(c >= a, errorMessage); return c; } function sub(uint a, uint b, string memory errorMessage) internal pure returns (uint) { require(b <= a, errorMessage); uint c = a - b; return c; } }
[{"inputs":[{"internalType":"contract CToken","name":"cToken","type":"address"},{"internalType":"address payable","name":"account","type":"address"}],"name":"cTokenBalances","outputs":[{"components":[{"internalType":"address","name":"cToken","type":"address"},{"internalType":"uint256","name":"balanceOf","type":"uint256"},{"internalType":"uint256","name":"borrowBalanceCurrent","type":"uint256"},{"internalType":"uint256","name":"balanceOfUnderlying","type":"uint256"},{"internalType":"uint256","name":"tokenBalance","type":"uint256"},{"internalType":"uint256","name":"tokenAllowance","type":"uint256"}],"internalType":"struct CompoundLens.CTokenBalances","name":"","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract CToken[]","name":"cTokens","type":"address[]"},{"internalType":"address payable","name":"account","type":"address"}],"name":"cTokenBalancesAll","outputs":[{"components":[{"internalType":"address","name":"cToken","type":"address"},{"internalType":"uint256","name":"balanceOf","type":"uint256"},{"internalType":"uint256","name":"borrowBalanceCurrent","type":"uint256"},{"internalType":"uint256","name":"balanceOfUnderlying","type":"uint256"},{"internalType":"uint256","name":"tokenBalance","type":"uint256"},{"internalType":"uint256","name":"tokenAllowance","type":"uint256"}],"internalType":"struct CompoundLens.CTokenBalances[]","name":"","type":"tuple[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract CToken","name":"cToken","type":"address"}],"name":"cTokenMetadata","outputs":[{"components":[{"internalType":"address","name":"cToken","type":"address"},{"internalType":"uint256","name":"exchangeRateCurrent","type":"uint256"},{"internalType":"uint256","name":"supplyRatePerBlock","type":"uint256"},{"internalType":"uint256","name":"borrowRatePerBlock","type":"uint256"},{"internalType":"uint256","name":"reserveFactorMantissa","type":"uint256"},{"internalType":"uint256","name":"totalBorrows","type":"uint256"},{"internalType":"uint256","name":"totalReserves","type":"uint256"},{"internalType":"uint256","name":"totalSupply","type":"uint256"},{"internalType":"uint256","name":"totalCash","type":"uint256"},{"internalType":"bool","name":"isListed","type":"bool"},{"internalType":"uint256","name":"collateralFactorMantissa","type":"uint256"},{"internalType":"address","name":"underlyingAssetAddress","type":"address"},{"internalType":"uint256","name":"cTokenDecimals","type":"uint256"},{"internalType":"uint256","name":"underlyingDecimals","type":"uint256"},{"internalType":"uint256","name":"compSupplySpeed","type":"uint256"},{"internalType":"uint256","name":"compBorrowSpeed","type":"uint256"},{"internalType":"uint256","name":"borrowCap","type":"uint256"}],"internalType":"struct CompoundLens.CTokenMetadata","name":"","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract CToken[]","name":"cTokens","type":"address[]"}],"name":"cTokenMetadataAll","outputs":[{"components":[{"internalType":"address","name":"cToken","type":"address"},{"internalType":"uint256","name":"exchangeRateCurrent","type":"uint256"},{"internalType":"uint256","name":"supplyRatePerBlock","type":"uint256"},{"internalType":"uint256","name":"borrowRatePerBlock","type":"uint256"},{"internalType":"uint256","name":"reserveFactorMantissa","type":"uint256"},{"internalType":"uint256","name":"totalBorrows","type":"uint256"},{"internalType":"uint256","name":"totalReserves","type":"uint256"},{"internalType":"uint256","name":"totalSupply","type":"uint256"},{"internalType":"uint256","name":"totalCash","type":"uint256"},{"internalType":"bool","name":"isListed","type":"bool"},{"internalType":"uint256","name":"collateralFactorMantissa","type":"uint256"},{"internalType":"address","name":"underlyingAssetAddress","type":"address"},{"internalType":"uint256","name":"cTokenDecimals","type":"uint256"},{"internalType":"uint256","name":"underlyingDecimals","type":"uint256"},{"internalType":"uint256","name":"compSupplySpeed","type":"uint256"},{"internalType":"uint256","name":"compBorrowSpeed","type":"uint256"},{"internalType":"uint256","name":"borrowCap","type":"uint256"}],"internalType":"struct CompoundLens.CTokenMetadata[]","name":"","type":"tuple[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract CToken","name":"cToken","type":"address"}],"name":"cTokenUnderlyingPrice","outputs":[{"components":[{"internalType":"address","name":"cToken","type":"address"},{"internalType":"uint256","name":"underlyingPrice","type":"uint256"}],"internalType":"struct CompoundLens.CTokenUnderlyingPrice","name":"","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract CToken[]","name":"cTokens","type":"address[]"}],"name":"cTokenUnderlyingPriceAll","outputs":[{"components":[{"internalType":"address","name":"cToken","type":"address"},{"internalType":"uint256","name":"underlyingPrice","type":"uint256"}],"internalType":"struct CompoundLens.CTokenUnderlyingPrice[]","name":"","type":"tuple[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ComptrollerLensInterface","name":"comptroller","type":"address"},{"internalType":"address","name":"account","type":"address"}],"name":"getAccountLimits","outputs":[{"components":[{"internalType":"contract CToken[]","name":"markets","type":"address[]"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"shortfall","type":"uint256"}],"internalType":"struct CompoundLens.AccountLimits","name":"","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract Comp","name":"comp","type":"address"},{"internalType":"address","name":"account","type":"address"}],"name":"getCompBalanceMetadata","outputs":[{"components":[{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"votes","type":"uint256"},{"internalType":"address","name":"delegate","type":"address"}],"internalType":"struct CompoundLens.CompBalanceMetadata","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract Comp","name":"comp","type":"address"},{"internalType":"contract ComptrollerLensInterface","name":"comptroller","type":"address"},{"internalType":"address","name":"account","type":"address"}],"name":"getCompBalanceMetadataExt","outputs":[{"components":[{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"votes","type":"uint256"},{"internalType":"address","name":"delegate","type":"address"},{"internalType":"uint256","name":"allocated","type":"uint256"}],"internalType":"struct CompoundLens.CompBalanceMetadataExt","name":"","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract Comp","name":"comp","type":"address"},{"internalType":"address","name":"account","type":"address"},{"internalType":"uint32[]","name":"blockNumbers","type":"uint32[]"}],"name":"getCompVotes","outputs":[{"components":[{"internalType":"uint256","name":"blockNumber","type":"uint256"},{"internalType":"uint256","name":"votes","type":"uint256"}],"internalType":"struct CompoundLens.CompVotes[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract GovernorBravoInterface","name":"governor","type":"address"},{"internalType":"uint256[]","name":"proposalIds","type":"uint256[]"}],"name":"getGovBravoProposals","outputs":[{"components":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"address","name":"proposer","type":"address"},{"internalType":"uint256","name":"eta","type":"uint256"},{"internalType":"address[]","name":"targets","type":"address[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"string[]","name":"signatures","type":"string[]"},{"internalType":"bytes[]","name":"calldatas","type":"bytes[]"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"},{"internalType":"uint256","name":"forVotes","type":"uint256"},{"internalType":"uint256","name":"againstVotes","type":"uint256"},{"internalType":"uint256","name":"abstainVotes","type":"uint256"},{"internalType":"bool","name":"canceled","type":"bool"},{"internalType":"bool","name":"executed","type":"bool"}],"internalType":"struct CompoundLens.GovBravoProposal[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract GovernorBravoInterface","name":"governor","type":"address"},{"internalType":"address","name":"voter","type":"address"},{"internalType":"uint256[]","name":"proposalIds","type":"uint256[]"}],"name":"getGovBravoReceipts","outputs":[{"components":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"bool","name":"hasVoted","type":"bool"},{"internalType":"uint8","name":"support","type":"uint8"},{"internalType":"uint96","name":"votes","type":"uint96"}],"internalType":"struct CompoundLens.GovBravoReceipt[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract GovernorAlpha","name":"governor","type":"address"},{"internalType":"uint256[]","name":"proposalIds","type":"uint256[]"}],"name":"getGovProposals","outputs":[{"components":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"address","name":"proposer","type":"address"},{"internalType":"uint256","name":"eta","type":"uint256"},{"internalType":"address[]","name":"targets","type":"address[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"string[]","name":"signatures","type":"string[]"},{"internalType":"bytes[]","name":"calldatas","type":"bytes[]"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"},{"internalType":"uint256","name":"forVotes","type":"uint256"},{"internalType":"uint256","name":"againstVotes","type":"uint256"},{"internalType":"bool","name":"canceled","type":"bool"},{"internalType":"bool","name":"executed","type":"bool"}],"internalType":"struct CompoundLens.GovProposal[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract GovernorAlpha","name":"governor","type":"address"},{"internalType":"address","name":"voter","type":"address"},{"internalType":"uint256[]","name":"proposalIds","type":"uint256[]"}],"name":"getGovReceipts","outputs":[{"components":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"bool","name":"hasVoted","type":"bool"},{"internalType":"bool","name":"support","type":"bool"},{"internalType":"uint96","name":"votes","type":"uint96"}],"internalType":"struct CompoundLens.GovReceipt[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b50613a2a806100206000396000f3fe608060405234801561001057600080fd5b50600436106100ea5760003560e01c8063595642191161008c57806396994869116100665780639699486914610285578063995ed99f146102a5578063bdf950c9146102c5578063c5ae5934146102e557600080fd5b8063595642191461022557806375d80e90146102455780637dd8f6d91461026557600080fd5b80632b2d5ed6116100c85780632b2d5ed614610187578063416405d7146101a757806343c811cc146101e55780634b70d84b1461020557600080fd5b80630972bf8b146100ef578063158eca8b146101185780631ea6374114610138575b600080fd5b6101026100fd366004612808565b610305565b60405161010f919061289e565b60405180910390f35b61012b6101263660046128ec565b6103d5565b60405161010f91906129d5565b61014b6101463660046129e4565b610b75565b60405161010f919081518152602080830151908201526040808301516001600160a01b0316908201526060918201519181019190915260800190565b61019a610195366004612a24565b610ed6565b60405161010f9190612a65565b6101ba6101b5366004612ac5565b610fab565b604080518251815260208084015190820152918101516001600160a01b03169082015260600161010f565b6101f86101f3366004612c1d565b61114c565b60405161010f9190612c7e565b610218610213366004612a24565b6112ee565b60405161010f9190612ce3565b610238610233366004612d26565b6113ac565b60405161010f9190612d8a565b610258610253366004612dcc565b611548565b60405161010f9190612f38565b610278610273366004612ac5565b6117a9565b60405161010f9190613072565b610298610293366004612dcc565b6118e3565b60405161010f91906130e1565b6102b86102b3366004612c1d565b611b2d565b60405161010f9190613202565b6102d86102d3366004612ac5565b611cce565b60405161010f9190613266565b6102f86102f33660046128ec565b612017565b60405161010f9190613274565b6060826000816001600160401b0381111561032257610322612afe565b60405190808252806020026020018201604052801561035b57816020015b6103486126d5565b8152602001906001900390816103405790505b50905060005b828110156103c95761039987878381811061037e5761037e613294565b905060200201602081019061039391906128ec565b86611cce565b8282815181106103ab576103ab613294565b602002602001018190525080806103c1906132c0565b915050610361565b509150505b9392505050565b6103dd612714565b6000826001600160a01b031663bd6d894d6040518163ffffffff1660e01b81526004016020604051808303816000875af115801561041f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061044391906132db565b90506000836001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610485573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104a991906132f4565b604051638e8f294b60e01b81526001600160a01b038681166004830152919250600091829190841690638e8f294b906024016040805180830381865afa1580156104f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061051b9190613326565b915091506000806105ad886001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015610563573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261058b91908101906133c0565b604051806040016040528060048152602001631890951560e21b815250612181565b156105be57506000905060126106f1565b6000889050806001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015610601573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061062591906132f4565b9250806001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015610665573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061068991906132f4565b6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106ea9190613418565b60ff169150505b6000806106fe878b6121da565b9150915060008080896001600160a01b0316634a58443260e01b8e60405160200161073891906001600160a01b0391909116815260200190565b60408051601f19818403018152908290526107569291602001613433565b60408051601f198184030181529082905261077091613464565b6000604051808303816000865af19150503d80600081146107ad576040519150601f19603f3d011682016040523d82523d6000602084013e6107b2565b606091505b509150915081156107d457808060200190518101906107d191906132db565b92505b6040518061022001604052808e6001600160a01b031681526020018c81526020018e6001600160a01b031663ae9d70b06040518163ffffffff1660e01b8152600401602060405180830381865afa158015610833573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061085791906132db565b81526020018e6001600160a01b031663f8f9da286040518163ffffffff1660e01b8152600401602060405180830381865afa15801561089a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108be91906132db565b81526020018e6001600160a01b031663173b99046040518163ffffffff1660e01b8152600401602060405180830381865afa158015610901573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061092591906132db565b81526020018e6001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa158015610968573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061098c91906132db565b81526020018e6001600160a01b0316638f840ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109cf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109f391906132db565b81526020018e6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a5a91906132db565b81526020018e6001600160a01b0316633b1d21a26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a9d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ac191906132db565b81526020018a15158152602001898152602001886001600160a01b031681526020018e6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b459190613418565b60ff168152602001878152602001868152602001858152602001848152509b505050505050505050505050919050565b610ba96040518060800160405280600081526020016000815260200160006001600160a01b03168152602001600081525090565b6040516370a0823160e01b81526001600160a01b038381166004830152600091908616906370a0823190602401602060405180830381865afa158015610bf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1791906132db565b6040516374d7814960e11b81526001600160a01b0385811660048301529192509085169063e9af029290602401600060405180830381600087803b158015610c5e57600080fd5b505af1158015610c72573d6000803e3d6000fd5b50506040516370a0823160e01b81526001600160a01b03868116600483015260009350881691506370a0823190602401602060405180830381865afa158015610cbf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ce391906132db565b60405163331faf7160e21b81526001600160a01b03868116600483015291925060009187169063cc7ebdc490602401602060405180830381865afa158015610d2f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d5391906132db565b90506000610d8882846040518060400160405280600e81526020016d1cdd5b4818dbdb5c081d1bdd185b60921b81525061245d565b90506000610dbc82866040518060400160405280600d81526020016c1cdd5888185b1b1bd8d85d1959609a1b815250612497565b60408051608081018252878152905163b4b5ea5760e01b81526001600160a01b038a8116600483015292935090916020830191908c169063b4b5ea5790602401602060405180830381865afa158015610e19573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e3d9190613497565b6001600160601b03168152604051632c3e6f0f60e11b81526001600160a01b038a811660048301526020909201918c169063587cde1e90602401602060405180830381865afa158015610e94573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eb891906132f4565b6001600160a01b031681526020019190915298975050505050505050565b6060816000816001600160401b03811115610ef357610ef3612afe565b604051908082528060200260200182016040528015610f3857816020015b6040805180820190915260008082526020820152815260200190600190039081610f115790505b50905060005b82811015610fa057610f70868683818110610f5b57610f5b613294565b90506020020160208101906102f391906128ec565b828281518110610f8257610f82613294565b60200260200101819052508080610f98906132c0565b915050610f3e565b509150505b92915050565b610fd86040518060600160405280600081526020016000815260200160006001600160a01b031681525090565b6040805160608101918290526370a0823160e01b9091526001600160a01b038381166064830152819085166370a0823160848301602060405180830381865afa158015611029573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061104d91906132db565b815260405163b4b5ea5760e01b81526001600160a01b03858116600483015260209092019186169063b4b5ea5790602401602060405180830381865afa15801561109b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110bf9190613497565b6001600160601b03168152604051632c3e6f0f60e11b81526001600160a01b03858116600483015260209092019186169063587cde1e90602401602060405180830381865afa158015611116573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061113a91906132f4565b6001600160a01b031690529392505050565b80516060906000816001600160401b0381111561116b5761116b612afe565b6040519080825280602002602001820160405280156111bd57816020015b6040805160808101825260008082526020808301829052928201819052606082015282526000199092019101816111895790505b50905060005b828110156103c9576000876001600160a01b031663e23a9a528784815181106111ee576111ee613294565b6020026020010151896040518363ffffffff1660e01b81526004016112269291909182526001600160a01b0316602082015260400190565b606060405180830381865afa158015611243573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061126791906134b2565b9050604051806080016040528087848151811061128657611286613294565b60200260200101518152602001826000015115158152602001826020015160ff16815260200182604001516001600160601b03168152508383815181106112cf576112cf613294565b60200260200101819052505080806112e6906132c0565b9150506111c3565b6060816000816001600160401b0381111561130b5761130b612afe565b60405190808252806020026020018201604052801561134457816020015b611331612714565b8152602001906001900390816113295790505b50905060005b82811015610fa05761137c86868381811061136757611367613294565b905060200201602081019061012691906128ec565b82828151811061138e5761138e613294565b602002602001018190525080806113a4906132c0565b91505061134a565b60606000826001600160401b038111156113c8576113c8612afe565b60405190808252806020026020018201604052801561140d57816020015b60408051808201909152600080825260208201528152602001906001900390816113e65790505b50905060005b8381101561153e57604051806040016040528086868481811061143857611438613294565b905060200201602081019061144d9190613500565b63ffffffff168152602001886001600160a01b031663782d6fe18989898781811061147a5761147a613294565b905060200201602081019061148f9190613500565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015263ffffffff166024820152604401602060405180830381865afa1580156114de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115029190613497565b6001600160601b031681525082828151811061152057611520613294565b60200260200101819052508080611536906132c0565b915050611413565b5095945050505050565b60606000826001600160401b0381111561156457611564612afe565b60405190808252806020026020018201604052801561161457816020015b611601604051806101c001604052806000815260200160006001600160a01b03168152602001600081526020016060815260200160608152602001606081526020016060815260200160008152602001600081526020016000815260200160008152602001600081526020016000151581526020016000151581525090565b8152602001906001900390816115825790505b50905060005b838110156117a057600080600080896001600160a01b031663328dd9828a8a8881811061164957611649613294565b905060200201356040518263ffffffff1660e01b815260040161166e91815260200190565b600060405180830381865afa15801561168b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526116b39190810190613694565b9350935093509350604051806101c001604052806000815260200160006001600160a01b031681526020016000815260200185815260200184815260200183815260200182815260200160008152602001600081526020016000815260200160008152602001600081526020016000151581526020016000151581525086868151811061174257611742613294565b602002602001018190525061178986868151811061176257611762613294565b60200260200101518b8b8b8981811061177d5761177d613294565b905060200201356124d1565b505050508080611798906132c0565b91505061161a565b50949350505050565b6117cd60405180606001604052806060815260200160008152602001600081525090565b604051635ec88c7960e01b81526001600160a01b0383811660048301526000918291829190871690635ec88c7990602401606060405180830381865afa15801561181b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061183f91906137a1565b9250925092508260001461185257600080fd5b604080516060810191829052632aff3bff60e21b9091526001600160a01b0386811660648301528190881663abfceffc60848301600060405180830381865afa1580156118a3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526118cb91908101906137cf565b81526020810193909352604090920152949350505050565b60606000826001600160401b038111156118ff576118ff612afe565b6040519080825280602002602001820160405280156119a857816020015b611995604051806101a001604052806000815260200160006001600160a01b031681526020016000815260200160608152602001606081526020016060815260200160608152602001600081526020016000815260200160008152602001600081526020016000151581526020016000151581525090565b81526020019060019003908161191d5790505b50905060005b838110156117a057600080600080896001600160a01b031663328dd9828a8a888181106119dd576119dd613294565b905060200201356040518263ffffffff1660e01b8152600401611a0291815260200190565b600060405180830381865afa158015611a1f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611a479190810190613694565b9350935093509350604051806101a001604052806000815260200160006001600160a01b03168152602001600081526020018581526020018481526020018381526020018281526020016000815260200160008152602001600081526020016000815260200160001515815260200160001515815250868681518110611acf57611acf613294565b6020026020010181905250611b16868681518110611aef57611aef613294565b60200260200101518b8b8b89818110611b0a57611b0a613294565b905060200201356125bc565b505050508080611b25906132c0565b9150506119ae565b80516060906000816001600160401b03811115611b4c57611b4c612afe565b604051908082528060200260200182016040528015611b9e57816020015b604080516080810182526000808252602080830182905292820181905260608201528252600019909201910181611b6a5790505b50905060005b828110156103c9576000876001600160a01b031663e23a9a52878481518110611bcf57611bcf613294565b6020026020010151896040518363ffffffff1660e01b8152600401611c079291909182526001600160a01b0316602082015260400190565b606060405180830381865afa158015611c24573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c489190613868565b90506040518060800160405280878481518110611c6757611c67613294565b6020026020010151815260200182600001511515815260200182602001511515815260200182604001516001600160601b0316815250838381518110611caf57611caf613294565b6020026020010181905250508080611cc6906132c0565b915050611ba4565b611cd66126d5565b6040516370a0823160e01b81526001600160a01b038381166004830152600091908516906370a0823190602401602060405180830381865afa158015611d20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d4491906132db565b6040516305eff7ef60e21b81526001600160a01b0385811660048301529192506000918616906317bfdfbc906024016020604051808303816000875af1158015611d92573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611db691906132db565b604051633af9e66960e01b81526001600160a01b038681166004830152919250600091871690633af9e669906024016020604051808303816000875af1158015611e04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e2891906132db565b9050600080611e6e886001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015610563573d6000803e3d6000fd5b15611e885750506001600160a01b03851680319031611fda565b60008890506000816001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ecd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ef191906132f4565b6040516370a0823160e01b81526001600160a01b038b81166004830152919250908216906370a0823190602401602060405180830381865afa158015611f3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5f91906132db565b604051636eb1769f60e11b81526001600160a01b038b811660048301528c811660248301529195509082169063dd62ed3e90604401602060405180830381865afa158015611fb1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd591906132db565b925050505b6040805160c0810182526001600160a01b039990991689526020890195909552938701929092526060860152608085015260a08401525090919050565b60408051808201909152600080825260208201526000826001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561206b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061208f91906132f4565b90506000816001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156120d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120f591906132f4565b6040805180820182526001600160a01b03808816808352925163fc57d4df60e01b815260048101939093529293509160208301919084169063fc57d4df90602401602060405180830381865afa158015612153573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061217791906132db565b9052949350505050565b6000816040516020016121949190613464565b60405160208183030381529060405280519060200120836040516020016121bb9190613464565b6040516020818303038152906040528051906020012014905092915050565b60008060008080866001600160a01b0316636aa875b560e01b8760405160200161221391906001600160a01b0391909116815260200190565b60408051601f19818403018152908290526122319291602001613433565b60408051601f198184030181529082905261224b91613464565b6000604051808303816000865af19150503d8060008114612288576040519150601f19603f3d011682016040523d82523d6000602084013e61228d565b606091505b509150915081156122af57808060200190518101906122ac91906132db565b92505b604080516001600160a01b038881166020830152600092839283928c16916303d290cf60e61b910160408051601f19818403018152908290526122f59291602001613433565b60408051601f198184030181529082905261230f91613464565b6000604051808303816000865af19150503d806000811461234c576040519150601f19603f3d011682016040523d82523d6000602084013e612351565b606091505b50915091508115612373578080602001905181019061237091906132db565b92505b84158061237e575081155b1561244c57604080516001600160a01b038b811660208301526000928392918e1691631d7b33d760e01b910160408051601f19818403018152908290526123c89291602001613433565b60408051601f19818403018152908290526123e291613464565b6000604051808303816000865af19150503d806000811461241f576040519150601f19603f3d011682016040523d82523d6000602084013e612424565b606091505b50915091508115612449578080602001905181019061244391906132db565b94508497505b50505b5093955093505050505b9250929050565b60008061246a8486613899565b905082858210156117a05760405162461bcd60e51b815260040161248e91906138b1565b60405180910390fd5b600081848411156124bb5760405162461bcd60e51b815260040161248e91906138b1565b5060006124c884866138c4565b95945050505050565b60405163013cf08b60e01b8152600481018290526000906001600160a01b0384169063013cf08b9060240161014060405180830381865afa15801561251a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061253e91906138db565b918452506020808201516001600160a01b03169084015260408082015190840152606081015160e08085019190915260808201516101008086019190915260a08301516101208087019190915260c0840151610140870152918301516101608601528201511515610180850152015115156101a09092019190915250565b600080600080600080600080896001600160a01b031663013cf08b8a6040518263ffffffff1660e01b81526004016125f691815260200190565b61012060405180830381865afa158015612614573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126389190613972565b9850985098509850985098509850985050888b6000018181525050878b602001906001600160a01b031690816001600160a01b031681525050868b6040018181525050858b60e0018181525050848b610100018181525050838b610120018181525050828b610140018181525050818b610160019015159081151581525050808b6101800190151590811515815250505050505050505050505050565b6040518060c0016040528060006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081525090565b60405180610220016040528060006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000151581526020016000815260200160006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081525090565b60008083601f8401126127be57600080fd5b5081356001600160401b038111156127d557600080fd5b6020830191508360208260051b850101111561245657600080fd5b6001600160a01b038116811461280557600080fd5b50565b60008060006040848603121561281d57600080fd5b83356001600160401b0381111561283357600080fd5b61283f868287016127ac565b9094509250506020840135612853816127f0565b809150509250925092565b80516001600160a01b031682526020808201519083015260408082015190830152606080820151908301526080808201519083015260a090810151910152565b6020808252825182820181905260009190848201906040850190845b818110156128e0576128cd83855161285e565b9284019260c092909201916001016128ba565b50909695505050505050565b6000602082840312156128fe57600080fd5b81356103ce816127f0565b80516001600160a01b031682526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c083015260e081015160e08301526101008082015181840152506101208082015161297c8285018215159052565b50506101408181015190830152610160808201516001600160a01b03169083015261018080820151908301526101a080820151908301526101c080820151908301526101e0808201519083015261020090810151910152565b6102208101610fa58284612909565b6000806000606084860312156129f957600080fd5b8335612a04816127f0565b92506020840135612a14816127f0565b91506040840135612853816127f0565b60008060208385031215612a3757600080fd5b82356001600160401b03811115612a4d57600080fd5b612a59858286016127ac565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b82811015612ab857612aa884835180516001600160a01b03168252602090810151910152565b9284019290850190600101612a82565b5091979650505050505050565b60008060408385031215612ad857600080fd5b8235612ae3816127f0565b91506020830135612af3816127f0565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b0381118282101715612b3657612b36612afe565b60405290565b60405161014081016001600160401b0381118282101715612b3657612b36612afe565b604051601f8201601f191681016001600160401b0381118282101715612b8757612b87612afe565b604052919050565b60006001600160401b03821115612ba857612ba8612afe565b5060051b60200190565b600082601f830112612bc357600080fd5b81356020612bd8612bd383612b8f565b612b5f565b82815260059290921b84018101918181019086841115612bf757600080fd5b8286015b84811015612c125780358352918301918301612bfb565b509695505050505050565b600080600060608486031215612c3257600080fd5b8335612c3d816127f0565b92506020840135612c4d816127f0565b915060408401356001600160401b03811115612c6857600080fd5b612c7486828701612bb2565b9150509250925092565b602080825282518282018190526000919060409081850190868401855b82811015612ab857815180518552868101511515878601528581015160ff16868601526060908101516001600160601b03169085015260809093019290850190600101612c9b565b6020808252825182820181905260009190848201906040850190845b818110156128e057612d12838551612909565b928401926102209290920191600101612cff565b60008060008060608587031215612d3c57600080fd5b8435612d47816127f0565b93506020850135612d57816127f0565b925060408501356001600160401b03811115612d7257600080fd5b612d7e878288016127ac565b95989497509550505050565b602080825282518282018190526000919060409081850190868401855b82811015612ab857815180518552860151868501529284019290850190600101612da7565b600080600060408486031215612de157600080fd5b8335612dec816127f0565b925060208401356001600160401b03811115612e0757600080fd5b612e13868287016127ac565b9497909650939450505050565b600081518084526020808501945080840160005b83811015612e595781516001600160a01b031687529582019590820190600101612e34565b509495945050505050565b600081518084526020808501945080840160005b83811015612e5957815187529582019590820190600101612e78565b60005b83811015612eaf578181015183820152602001612e97565b83811115612ebe576000848401525b50505050565b60008151808452612edc816020860160208601612e94565b601f01601f19169290920160200192915050565b600081518084526020808501808196508360051b8101915082860160005b85811015612ab8578284038952612f26848351612ec4565b98850198935090840190600101612f0e565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b8381101561306457888303603f19018552815180518452878101516001600160a01b038116898601526101c0905087820151888601526060808301518282880152612fac83880182612e20565b9250505060808083015186830382880152612fc78382612e64565b9250505060a08083015186830382880152612fe28382612ef0565b9250505060c08083015186830382880152612ffd8382612ef0565b60e085810151908901526101008086015190890152610120808601519089015261014080860151908901526101608086015190890152610180808601511515908901526101a094850151151594909701939093525050509386019390860190600101612f5f565b509098975050505050505050565b6020808252825160608383015280516080840181905260009291820190839060a08601905b808310156130c05783516001600160a01b03168252928401926001929092019190840190613097565b50838701516040870152604087015160608701528094505050505092915050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b8381101561306457888303603f19018552815180518452878101516001600160a01b038116898601526101a090508782015188860152606080830151828288015261315583880182612e20565b92505050608080830151868303828801526131708382612e64565b9250505060a0808301518683038288015261318b8382612ef0565b9250505060c080830151868303828801526131a68382612ef0565b60e085810151908901526101008086015190890152610120808601519089015261014080860151908901526101608086015115159089015261018094850151151594909701939093525050509386019390860190600101613108565b602080825282518282018190526000919060409081850190868401855b82811015612ab85781518051855286810151151587860152858101511515868601526060908101516001600160601b0316908501526080909301929085019060010161321f565b60c08101610fa5828461285e565b81516001600160a01b031681526020808301519082015260408101610fa5565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006000198214156132d4576132d46132aa565b5060010190565b6000602082840312156132ed57600080fd5b5051919050565b60006020828403121561330657600080fd5b81516103ce816127f0565b8051801515811461332157600080fd5b919050565b6000806040838503121561333957600080fd5b61334283613311565b9150602083015190509250929050565b60006001600160401b0383111561336b5761336b612afe565b61337e601f8401601f1916602001612b5f565b905082815283838301111561339257600080fd5b6103ce836020830184612e94565b600082601f8301126133b157600080fd5b6103ce83835160208501613352565b6000602082840312156133d257600080fd5b81516001600160401b038111156133e857600080fd5b6133f4848285016133a0565b949350505050565b8051613321816127f0565b805160ff8116811461332157600080fd5b60006020828403121561342a57600080fd5b6103ce82613407565b6001600160e01b0319831681528151600090613456816004850160208701612e94565b919091016004019392505050565b60008251613476818460208701612e94565b9190910192915050565b80516001600160601b038116811461332157600080fd5b6000602082840312156134a957600080fd5b6103ce82613480565b6000606082840312156134c457600080fd5b6134cc612b14565b6134d583613311565b81526134e360208401613407565b60208201526134f460408401613480565b60408201529392505050565b60006020828403121561351257600080fd5b813563ffffffff811681146103ce57600080fd5b600082601f83011261353757600080fd5b81516020613547612bd383612b8f565b82815260059290921b8401810191818101908684111561356657600080fd5b8286015b84811015612c12578051835291830191830161356a565b600082601f83011261359257600080fd5b815160206135a2612bd383612b8f565b82815260059290921b840181019181810190868411156135c157600080fd5b8286015b84811015612c125780516001600160401b038111156135e45760008081fd5b6135f28986838b01016133a0565b8452509183019183016135c5565b600082601f83011261361157600080fd5b81516020613621612bd383612b8f565b82815260059290921b8401810191818101908684111561364057600080fd5b8286015b84811015612c125780516001600160401b038111156136635760008081fd5b8701603f810189136136755760008081fd5b613686898683015160408401613352565b845250918301918301613644565b600080600080608085870312156136aa57600080fd5b84516001600160401b03808211156136c157600080fd5b818701915087601f8301126136d557600080fd5b815160206136e5612bd383612b8f565b82815260059290921b8401810191818101908b84111561370457600080fd5b948201945b8386101561372b57855161371c816127f0565b82529482019490820190613709565b918a015191985090935050508082111561374457600080fd5b61375088838901613526565b9450604087015191508082111561376657600080fd5b61377288838901613581565b9350606087015191508082111561378857600080fd5b5061379587828801613600565b91505092959194509250565b6000806000606084860312156137b657600080fd5b8351925060208401519150604084015190509250925092565b600060208083850312156137e257600080fd5b82516001600160401b038111156137f857600080fd5b8301601f8101851361380957600080fd5b8051613817612bd382612b8f565b81815260059190911b8201830190838101908783111561383657600080fd5b928401925b8284101561385d57835161384e816127f0565b8252928401929084019061383b565b979650505050505050565b60006060828403121561387a57600080fd5b613882612b14565b61388b83613311565b81526134e360208401613311565b600082198211156138ac576138ac6132aa565b500190565b6020815260006103ce6020830184612ec4565b6000828210156138d6576138d66132aa565b500390565b600061014082840312156138ee57600080fd5b6138f6612b3c565b82518152613906602084016133fc565b602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e0820152610100613955818501613311565b90820152610120613967848201613311565b908201529392505050565b60008060008060008060008060006101208a8c03121561399157600080fd5b8951985060208a01516139a3816127f0565b8098505060408a0151965060608a0151955060808a0151945060a08a0151935060c08a015192506139d660e08b01613311565b91506139e56101008b01613311565b9050929598509295985092959856fea2646970667358221220c23660bb5a4b5a874581aadf874880fe5c7d59841cc18597e39f10a55eb68ba864736f6c634300080a0033
Deployed ByteCode Sourcemap
120214:16759:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;126660:389;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;122700:2228;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;135121:717::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;5203:13:1;;5185:32;;5273:4;5261:17;;;5255:24;5233:20;;;5226:54;5340:4;5328:17;;;5322:24;-1:-1:-1;;;;;5318:50:1;5296:20;;;5289:80;5425:4;5413:17;;;5407:24;5385:20;;;5378:54;;;;5172:3;5157:19;;4958:480;127590:390:0;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;134647:324::-;;;;;;:::i;:::-;;:::i;:::-;;;;7530:13:1;;7512:32;;7600:4;7588:17;;;7582:24;7560:20;;;7553:54;7655:17;;;7649:24;-1:-1:-1;;;;;7645:50:1;7623:20;;;7616:80;7500:2;7485:18;134647:324:0;7292:410:1;129480:704:0;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;124936:355::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;135927:480::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;133369:1156::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;128102:435::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;131285:1083::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;128675:661::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;125516:1136::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;127158:424::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;126660:389::-;126757:23;126812:7;126793:16;126812:7;-1:-1:-1;;;;;126867:33:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;126837:63;;126916:6;126911:110;126932:11;126928:1;:15;126911:110;;;126974:35;126989:7;;126997:1;126989:10;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;127001:7;126974:14;:35::i;:::-;126965:3;126969:1;126965:6;;;;;;;;:::i;:::-;;;;;;:44;;;;126945:3;;;;;:::i;:::-;;;;126911:110;;;-1:-1:-1;127038:3:0;-1:-1:-1;;126660:389:0;;;;;;:::o;122700:2228::-;122755:21;;:::i;:::-;122789:24;122816:6;-1:-1:-1;;;;;122816:26:0;;:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;122789:55;;122855:36;122927:6;-1:-1:-1;;;;;122927:18:0;;:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;123009:36;;-1:-1:-1;;;123009:36:0;;-1:-1:-1;;;;;27082:32:1;;;123009:36:0;;;27064:51:1;122855:94:0;;-1:-1:-1;122961:13:0;;;;123009:19;;;;;;27037:18:1;;123009:36:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;122960:85;;;;123056:30;123097:23;123137:39;123152:6;-1:-1:-1;;;;;123152:13:0;;:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;123152:15:0;;;;;;;;;;;;:::i;:::-;123137:39;;;;;;;;;;;;;-1:-1:-1;;;123137:39:0;;;:14;:39::i;:::-;123133:358;;;-1:-1:-1;123226:1:0;;-1:-1:-1;123264:2:0;123133:358;;;123299:13;123330:6;123299:39;;123378:6;-1:-1:-1;;;;;123378:17:0;;:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;123353:44;;123448:6;-1:-1:-1;;;;;123448:17:0;;:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;123433:44:0;;:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;123412:67;;;;123284:207;123133:358;123504:20;123526;123550:34;123564:11;123577:6;123550:13;:34::i;:::-;123503:81;;;;123597:14;123627:21;123650:32;123707:11;-1:-1:-1;;;;;123699:25:0;123782:31;;;123855:6;123836:27;;;;;;;-1:-1:-1;;;;;27082:32:1;;;;27064:51;;27052:2;27037:18;;26918:203;123836:27:0;;;;-1:-1:-1;;123836:27:0;;;;;;;;;;123743:139;;;123836:27;123743:139;;:::i;:::-;;;;-1:-1:-1;;123743:139:0;;;;;;;;;;123699:198;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;123626:271;;;;123912:16;123908:100;;;123968:19;123957:39;;;;;;;;;;;;:::i;:::-;123945:51;;123908:100;124027:893;;;;;;;;124073:6;-1:-1:-1;;;;;124027:893:0;;;;;124116:19;124027:893;;;;124170:6;-1:-1:-1;;;;;124170:25:0;;:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;124027:893;;;;124232:6;-1:-1:-1;;;;;124232:25:0;;:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;124027:893;;;;124297:6;-1:-1:-1;;;;;124297:28:0;;:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;124027:893;;;;124356:6;-1:-1:-1;;;;;124356:19:0;;:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;124027:893;;;;124407:6;-1:-1:-1;;;;;124407:20:0;;:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;124027:893;;;;124457:6;-1:-1:-1;;;;;124457:18:0;;:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;124027:893;;;;124503:6;-1:-1:-1;;;;;124503:14:0;;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;124027:893;;;;124544:8;124027:893;;;;;;124593:24;124027:893;;;;124656:22;-1:-1:-1;;;;;124027:893:0;;;;;124709:6;-1:-1:-1;;;;;124709:15:0;;:17;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;124027:893;;;;;;124761:18;124027:893;;;;124811:15;124027:893;;;;124858:15;124027:893;;;;124899:9;124027:893;;;124020:900;;;;;;;;;;;;;122700:2228;;;:::o;135121:717::-;135240:29;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;135240:29:0;135297:23;;-1:-1:-1;;;135297:23:0;;-1:-1:-1;;;;;27082:32:1;;;135297:23:0;;;27064:51:1;135282:12:0;;135297:14;;;;;;27037:18:1;;135297:23:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;135331:30;;-1:-1:-1;;;135331:30:0;;-1:-1:-1;;;;;27082:32:1;;;135331:30:0;;;27064:51:1;135282:38:0;;-1:-1:-1;135331:21:0;;;;;;27037:18:1;;135331:30:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;135390:23:0;;-1:-1:-1;;;135390:23:0;;-1:-1:-1;;;;;27082:32:1;;;135390:23:0;;;27064:51:1;135372:15:0;;-1:-1:-1;135390:14:0;;;-1:-1:-1;135390:14:0;;27037:18:1;;135390:23:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;135439:32;;-1:-1:-1;;;135439:32:0;;-1:-1:-1;;;;;27082:32:1;;;135439::0;;;27064:51:1;135372:41:0;;-1:-1:-1;135424:12:0;;135439:23;;;;;27037:18:1;;135439:32:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;135424:47;;135482:10;135495:42;135499:7;135508:10;135495:42;;;;;;;;;;;;;-1:-1:-1;;;135495:42:0;;;:3;:42::i;:::-;135482:55;;135548:14;135565:36;135569:5;135576:7;135565:36;;;;;;;;;;;;;-1:-1:-1;;;135565:36:0;;;:3;:36::i;:::-;135621:209;;;;;;;;;;;135705:29;;-1:-1:-1;;;135705:29:0;;-1:-1:-1;;;;;27082:32:1;;;135705:29:0;;;27064:51:1;135548:53:0;;-1:-1:-1;135621:209:0;;;;;;135705:20;;;;;;27037:18:1;;135705:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;135697:38:0;135621:209;;135760:23;;-1:-1:-1;;;135760:23:0;;-1:-1:-1;;;;;27082:32:1;;;135760:23:0;;;27064:51:1;135621:209:0;;;;;135760:14;;;;;27037:18:1;;135760:23:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;135621:209:0;;;;;;;;;;135121:717;-1:-1:-1;;;;;;;;135121:717:0:o;127590:390::-;127669:30;127731:7;127712:16;127731:7;-1:-1:-1;;;;;127793:40:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;127793:40:0;;;;;;;;;;;;;;;;127756:77;;127849:6;127844:108;127865:11;127861:1;:15;127844:108;;;127907:33;127929:7;;127937:1;127929:10;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;127907:33::-;127898:3;127902:1;127898:6;;;;;;;;:::i;:::-;;;;;;:42;;;;127878:3;;;;;:::i;:::-;;;;127844:108;;;-1:-1:-1;127969:3:0;-1:-1:-1;;127590:390:0;;;;;:::o;134647:324::-;134730:26;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;134730:26:0;134776:187;;;;;;;;;;-1:-1:-1;;;134820:23:0;;;-1:-1:-1;;;;;27082:32:1;;;134820:23:0;;;27064:51:1;134776:187:0;;134820:14;;;27037:18:1;;;134820:23:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;134776:187;;134873:29;;-1:-1:-1;;;134873:29:0;;-1:-1:-1;;;;;27082:32:1;;;134873:29:0;;;27064:51:1;134776:187:0;;;;;134873:20;;;;;27037:18:1;;134873:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;134865:38:0;134776:187;;134928:23;;-1:-1:-1;;;134928:23:0;;-1:-1:-1;;;;;27082:32:1;;;134928:23:0;;;27064:51:1;134776:187:0;;;;;134928:14;;;;;27037:18:1;;134928:23:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;134776:187:0;;;134769:194;134647:324;-1:-1:-1;;;134647:324:0:o;129480:704::-;129663:18;;129605:24;;129642:18;129663;-1:-1:-1;;;;;129723:36:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;129723:36:0;;-1:-1:-1;;129723:36:0;;;;;;;;;;;;129692:67;;129775:6;129770:386;129791:13;129787:1;:17;129770:386;;;129826:45;129874:8;-1:-1:-1;;;;;129874:19:0;;129894:11;129906:1;129894:14;;;;;;;;:::i;:::-;;;;;;;129910:5;129874:42;;;;;;;;;;;;;;;30547:25:1;;;-1:-1:-1;;;;;30608:32:1;30603:2;30588:18;;30581:60;30535:2;30520:18;;30373:274;129874:42:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;129826:90;;129940:204;;;;;;;;129987:11;129999:1;129987:14;;;;;;;;:::i;:::-;;;;;;;129940:204;;;;130030:7;:16;;;129940:204;;;;;;130074:7;:15;;;129940:204;;;;;;130115:7;:13;;;-1:-1:-1;;;;;129940:204:0;;;;129931:3;129935:1;129931:6;;;;;;;;:::i;:::-;;;;;;:213;;;;129811:345;129806:3;;;;;:::i;:::-;;;;129770:386;;124936:355;125008:23;125063:7;125044:16;125063:7;-1:-1:-1;;;;;125118:33:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;125088:63;;125167:6;125162:101;125183:11;125179:1;:15;125162:101;;;125225:26;125240:7;;125248:1;125240:10;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;125225:26::-;125216:3;125220:1;125216:6;;;;;;;;:::i;:::-;;;;;;:35;;;;125196:3;;;;;:::i;:::-;;;;125162:101;;135927:480;136032:18;136063:22;136104:12;-1:-1:-1;;;;;136088:36:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;136088:36:0;;;;;;;;;;;;;;;;136063:61;;136140:6;136135:244;136152:23;;;136135:244;;;136206:161;;;;;;;;136256:12;;136269:1;136256:15;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;136248:24;;136206:161;;;;136306:4;-1:-1:-1;;;;;136306:18:0;;136325:7;136334:12;;136347:1;136334:15;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;136306:44;;-1:-1:-1;;;;;;136306:44:0;;;;;;;-1:-1:-1;;;;;31593:32:1;;;136306:44:0;;;31575:51:1;136306:44:0;31662:23:1;31642:18;;;31635:51;31548:18;;136306:44:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;136298:53:0;136206:161;;;136197:3;136201:1;136197:6;;;;;;;;:::i;:::-;;;;;;:170;;;;136177:3;;;;;:::i;:::-;;;;136135:244;;;-1:-1:-1;136396:3:0;135927:480;-1:-1:-1;;;;;135927:480:0:o;133369:1156::-;133484:25;133522:29;133577:11;-1:-1:-1;;;;;133554:42:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;133554:42:0;;;;;;;;;;;;;;;;;133522:74;;133612:6;133607:890;133624:22;;;133607:890;;;133687:24;133730:20;133769:26;133814:24;133856:8;-1:-1:-1;;;;;133856:19:0;;133876:11;;133888:1;133876:14;;;;;;;:::i;:::-;;;;;;;133856:35;;;;;;;;;;;;;31843:25:1;;31831:2;31816:18;;31697:177;133856:35:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;133856:35:0;;;;;;;;;;;;:::i;:::-;133668:223;;;;;;;;133915:505;;;;;;;;133963:1;133915:505;;;;134001:1;-1:-1:-1;;;;;133915:505:0;;;;;134027:1;133915:505;;;;134056:7;133915:505;;;;134090:6;133915:505;;;;134127:10;133915:505;;;;134167:9;133915:505;;;;134207:1;133915:505;;;;134237:1;133915:505;;;;134267:1;133915:505;;;;134301:1;133915:505;;;;134335:1;133915:505;;;;134365:5;133915:505;;;;;;134399:5;133915:505;;;;;133906:3;133910:1;133906:6;;;;;;;;:::i;:::-;;;;;;:514;;;;134435:50;134452:3;134456:1;134452:6;;;;;;;;:::i;:::-;;;;;;;134460:8;134470:11;;134482:1;134470:14;;;;;;;:::i;:::-;;;;;;;134435:16;:50::i;:::-;133653:844;;;;133648:3;;;;;:::i;:::-;;;;133607:890;;;-1:-1:-1;134514:3:0;133369:1156;-1:-1:-1;;;;133369:1156:0:o;128102:435::-;128199:20;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;128199:20:0;128283:40;;-1:-1:-1;;;128283:40:0;;-1:-1:-1;;;;;27082:32:1;;;128283:40:0;;;27064:51:1;128233:14:0;;;;;;128283:31;;;;;;27037:18:1;;128283:40:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;128232:91;;;;;;128342:9;128355:1;128342:14;128334:23;;;;;;128377:152;;;;;;;;;;-1:-1:-1;;;128415:32:0;;;-1:-1:-1;;;;;27082:32:1;;;128415::0;;;27064:51:1;128377:152:0;;128415:23;;;27037:18:1;;;128415:32:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;128415:32:0;;;;;;;;;;;;:::i;:::-;128377:152;;;;;;;;;;;;;;;128102:435;-1:-1:-1;;;;128102:435:0:o;131285:1083::-;131386:20;131419:24;131464:11;-1:-1:-1;;;;;131446:37:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;131446:37:0;;;;;;;;;;;;;;;;;131419:64;;131499:6;131494:846;131511:22;;;131494:846;;;131574:24;131617:20;131656:26;131701:24;131743:8;-1:-1:-1;;;;;131743:19:0;;131763:11;;131775:1;131763:14;;;;;;;:::i;:::-;;;;;;;131743:35;;;;;;;;;;;;;31843:25:1;;31831:2;31816:18;;31697:177;131743:35:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;131743:35:0;;;;;;;;;;;;:::i;:::-;131555:223;;;;;;;;131802:466;;;;;;;;131845:1;131802:466;;;;131883:1;-1:-1:-1;;;;;131802:466:0;;;;;131909:1;131802:466;;;;131938:7;131802:466;;;;131972:6;131802:466;;;;132009:10;131802:466;;;;132049:9;131802:466;;;;132089:1;131802:466;;;;132119:1;131802:466;;;;132149:1;131802:466;;;;132183:1;131802:466;;;;132213:5;131802:466;;;;;;132247:5;131802:466;;;;;131793:3;131797:1;131793:6;;;;;;;;:::i;:::-;;;;;;:475;;;;132283:45;132295:3;132299:1;132295:6;;;;;;;;:::i;:::-;;;;;;;132303:8;132313:11;;132325:1;132313:14;;;;;;;:::i;:::-;;;;;;;132283:11;:45::i;:::-;131540:800;;;;131535:3;;;;;:::i;:::-;;;;131494:846;;128675:661;128839:18;;128786:19;;128818:18;128839;-1:-1:-1;;;;;128894:31:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;128894:31:0;;-1:-1:-1;;128894:31:0;;;;;;;;;;;;128868:57;;128941:6;128936:372;128957:13;128953:1;:17;128936:372;;;128992:36;129031:8;-1:-1:-1;;;;;129031:19:0;;129051:11;129063:1;129051:14;;;;;;;;:::i;:::-;;;;;;;129067:5;129031:42;;;;;;;;;;;;;;;30547:25:1;;;-1:-1:-1;;;;;30608:32:1;30603:2;30588:18;;30581:60;30535:2;30520:18;;30373:274;129031:42:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;128992:81;;129097:199;;;;;;;;129139:11;129151:1;129139:14;;;;;;;;:::i;:::-;;;;;;;129097:199;;;;129182:7;:16;;;129097:199;;;;;;129226:7;:15;;;129097:199;;;;;;129267:7;:13;;;-1:-1:-1;;;;;129097:199:0;;;;129088:3;129092:1;129088:6;;;;;;;;:::i;:::-;;;;;;:208;;;;128977:331;128972:3;;;;;:::i;:::-;;;;128936:372;;125516:1136;125596:21;;:::i;:::-;125647:25;;-1:-1:-1;;;125647:25:0;;-1:-1:-1;;;;;27082:32:1;;;125647:25:0;;;27064:51:1;125630:14:0;;125647:16;;;;;;27037:18:1;;125647:25:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;125711:36;;-1:-1:-1;;;125711:36:0;;-1:-1:-1;;;;;27082:32:1;;;125711:36:0;;;27064:51:1;125630:42:0;;-1:-1:-1;125683:25:0;;125711:27;;;;;27037:18:1;;125711:36:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;125785:35;;-1:-1:-1;;;125785:35:0;;-1:-1:-1;;;;;27082:32:1;;;125785:35:0;;;27064:51:1;125683:64:0;;-1:-1:-1;125758:24:0;;125785:26;;;;;27037:18:1;;125785:35:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;125758:62;;125831:17;125859:19;125895:39;125910:6;-1:-1:-1;;;;;125910:13:0;;:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;125895:39;125891:436;;;-1:-1:-1;;;;;;;125966:15:0;;;;;126013;125891:436;;;126061:13;126092:6;126061:39;;126115:25;126158:6;-1:-1:-1;;;;;126158:17:0;;:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;126208:29;;-1:-1:-1;;;126208:29:0;;-1:-1:-1;;;;;27082:32:1;;;126208:29:0;;;27064:51:1;126115:63:0;;-1:-1:-1;126208:20:0;;;;;;27037:18:1;;126208:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;126269:46;;-1:-1:-1;;;126269:46:0;;-1:-1:-1;;;;;38454:15:1;;;126269:46:0;;;38436:34:1;38506:15;;;38486:18;;;38479:43;126193:44:0;;-1:-1:-1;126269:20:0;;;;;;38371:18:1;;126269:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;126252:63;;126046:281;;125891:436;126346:298;;;;;;;;-1:-1:-1;;;;;126346:298:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;126346:298:0;;125516:1136;-1:-1:-1;125516:1136:0:o;127158:424::-;-1:-1:-1;;;;;;;;;;;;;;;;;127261:36:0;127333:6;-1:-1:-1;;;;;127333:18:0;;:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;127261:94;;127366:23;127392:11;-1:-1:-1;;;;;127392:18:0;;:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;127432:142;;;;;;;;-1:-1:-1;;;;;127432:142:0;;;;;;127524:38;;-1:-1:-1;;;127524:38:0;;;;;27064:51:1;;;;127366:46:0;;-1:-1:-1;127432:142:0;;;;;127524:30;;;;;;27037:18:1;;127524:38:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;127432:142;;127425:149;127158:424;-1:-1:-1;;;;127158:424:0:o;136415:183::-;136496:4;136585:1;136567:21;;;;;;;;:::i;:::-;;;;;;;;;;;;;136557:32;;;;;;136549:1;136531:21;;;;;;;;:::i;:::-;;;;;;;;;;;;;136521:32;;;;;;:68;136513:77;;136415:183;;;;:::o;120811:1881::-;120905:4;120911;121113:20;121149:27;121178:38;121241:11;-1:-1:-1;;;;;121233:25:0;121316:37;;;121395:6;121376:27;;;;;;;-1:-1:-1;;;;;27082:32:1;;;;27064:51;;27052:2;27037:18;;26918:203;121376:27:0;;;;-1:-1:-1;;121376:27:0;;;;;;;;;;121277:145;;;121376:27;121277:145;;:::i;:::-;;;;-1:-1:-1;;121277:145:0;;;;;;;;;;121233:204;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;121148:289;;;;121452:22;121448:118;;;121520:25;121509:45;;;;;;;;;;;;:::i;:::-;121491:63;;121448:118;121841:27;;;-1:-1:-1;;;;;27082:32:1;;;121841:27:0;;;27064:51:1;121578:20:0;;;;;;121698:25;;;-1:-1:-1;;;121781:37:0;27037:18:1;121841:27:0;;;-1:-1:-1;;121841:27:0;;;;;;;;;;121742:145;;;121841:27;121742:145;;:::i;:::-;;;;-1:-1:-1;;121742:145:0;;;;;;;;;;121698:204;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;121613:289;;;;121917:22;121913:118;;;121985:25;121974:45;;;;;;;;;;;;:::i;:::-;121956:63;;121913:118;122138:22;122137:23;:50;;;;122165:22;122164:23;122137:50;122133:500;;;122414:27;;;-1:-1:-1;;;;;27082:32:1;;;122414:27:0;;;27064:51:1;122205:21:0;;;;122277:25;;;;-1:-1:-1;;;122360:31:0;27037:18:1;122414:27:0;;;-1:-1:-1;;122414:27:0;;;;;;;;;;122321:139;;;122414:27;122321:139;;:::i;:::-;;;;-1:-1:-1;;122321:139:0;;;;;;;;;;122277:198;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;122204:271;;;;122494:16;122490:132;;;122578:19;122567:39;;;;;;;;;;;;:::i;:::-;122549:57;;;122531:75;;122490:132;122189:444;;122133:500;-1:-1:-1;122651:15:0;;-1:-1:-1;122668:15:0;-1:-1:-1;;;;120811:1881:0;;;;;;:::o;136606:178::-;136686:4;;136712:5;136716:1;136712;:5;:::i;:::-;136703:14;-1:-1:-1;136744:12:0;136736:6;;;;136728:29;;;;-1:-1:-1;;;136728:29:0;;;;;;;;:::i;:::-;;;;;;;;136792:178;136872:4;136905:12;136897:6;;;;136889:29;;;;-1:-1:-1;;;136889:29:0;;;;;;;;:::i;:::-;-1:-1:-1;136929:6:0;136938:5;136942:1;136938;:5;:::i;:::-;136929:14;136792:178;-1:-1:-1;;;;;136792:178:0:o;132776:585::-;132949:30;;-1:-1:-1;;;132949:30:0;;;;;31843:25:1;;;132906:40:0;;-1:-1:-1;;;;;132949:18:0;;;;;31816::1;;132949:30:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;132992:27;;;-1:-1:-1;133045:10:0;;;;;-1:-1:-1;;;;;133030:25:0;:12;;;:25;133076:5;;;;;133066:7;;;:15;133109:12;;;;133092:14;;;;:29;;;;133147:10;;;;133132:12;;;;:25;;;;133183:10;;;;133168:12;;;;:25;;;;133223:14;;;;133204:16;;;:33;133267:14;;;;133248:16;;;:33;133307:10;;;133292:25;;:12;;;:25;133343:10;;133328:25;;:12;;;;:25;;;;-1:-1:-1;132776:585:0:o;130559:718::-;130700:16;130731:8;130754:15;130784:13;130812;130840:17;130872:13;130900;130927:8;-1:-1:-1;;;;;130927:18:0;;130946:10;130927:30;;;;;;;;;;;;;31843:25:1;;31831:2;31816:18;;31697:177;130927:30:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;130670:287;;;;;;;;;;;;;;;;;130985:10;130968:3;:14;;:27;;;;;131021:8;131006:3;:12;;:23;-1:-1:-1;;;;;131006:23:0;;;-1:-1:-1;;;;;131006:23:0;;;;;131050:3;131040;:7;;:13;;;;;131081:10;131064:3;:14;;:27;;;;;131117:8;131102:3;:12;;:23;;;;;131151:8;131136:3;:12;;:23;;;;;131189:12;131170:3;:16;;:31;;;;;131227:8;131212:3;:12;;:23;;;;;;;;;;;131261:8;131246:3;:12;;:23;;;;;;;;;;;130659:618;;;;;;;;130559:718;;;:::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;14:375:1:-;85:8;95:6;149:3;142:4;134:6;130:17;126:27;116:55;;167:1;164;157:12;116:55;-1:-1:-1;190:20:1;;-1:-1:-1;;;;;222:30:1;;219:50;;;265:1;262;255:12;219:50;302:4;294:6;290:17;278:29;;362:3;355:4;345:6;342:1;338:14;330:6;326:27;322:38;319:47;316:67;;;379:1;376;369:12;394:139;-1:-1:-1;;;;;477:31:1;;467:42;;457:70;;523:1;520;513:12;457:70;394:139;:::o;538:611::-;656:6;664;672;725:2;713:9;704:7;700:23;696:32;693:52;;;741:1;738;731:12;693:52;781:9;768:23;-1:-1:-1;;;;;806:6:1;803:30;800:50;;;846:1;843;836:12;800:50;885:78;955:7;946:6;935:9;931:22;885:78;:::i;:::-;982:8;;-1:-1:-1;859:104:1;-1:-1:-1;;1067:2:1;1052:18;;1039:32;1080:39;1039:32;1080:39;:::i;:::-;1138:5;1128:15;;;538:611;;;;;:::o;1263:405::-;1347:12;;-1:-1:-1;;;;;1343:38:1;1331:51;;1431:4;1420:16;;;1414:23;1398:14;;;1391:47;1487:4;1476:16;;;1470:23;1454:14;;;1447:47;1543:4;1532:16;;;1526:23;1510:14;;;1503:47;1599:4;1588:16;;;1582:23;1566:14;;;1559:47;1369:3;1644:16;;;1638:23;1622:14;;1615:47;1263:405::o;1673:724::-;1908:2;1960:21;;;2030:13;;1933:18;;;2052:22;;;1879:4;;1908:2;2131:15;;;;2105:2;2090:18;;;1879:4;2174:197;2188:6;2185:1;2182:13;2174:197;;;2237:52;2285:3;2276:6;2270:13;2237:52;:::i;:::-;2346:15;;;;2318:4;2309:14;;;;;2210:1;2203:9;2174:197;;;-1:-1:-1;2388:3:1;;1673:724;-1:-1:-1;;;;;;1673:724:1:o;2402:270::-;2476:6;2529:2;2517:9;2508:7;2504:23;2500:32;2497:52;;;2545:1;2542;2535:12;2497:52;2584:9;2571:23;2603:39;2636:5;2603:39;:::i;2773:1303::-;2860:12;;-1:-1:-1;;;;;1220:31:1;1208:44;;2927:4;2920:5;2916:16;2910:23;2903:4;2898:3;2894:14;2887:47;2983:4;2976:5;2972:16;2966:23;2959:4;2954:3;2950:14;2943:47;3039:4;3032:5;3028:16;3022:23;3015:4;3010:3;3006:14;2999:47;3095:4;3088:5;3084:16;3078:23;3071:4;3066:3;3062:14;3055:47;3151:4;3144:5;3140:16;3134:23;3127:4;3122:3;3118:14;3111:47;3207:4;3200:5;3196:16;3190:23;3183:4;3178:3;3174:14;3167:47;3263:4;3256:5;3252:16;3246:23;3239:4;3234:3;3230:14;3223:47;3289:6;3342:2;3335:5;3331:14;3325:21;3320:2;3315:3;3311:12;3304:43;;3366:6;3418:2;3411:5;3407:14;3401:21;3431:43;3470:2;3465:3;3461:12;3447;2747:13;2740:21;2728:34;;2677:91;3431:43;-1:-1:-1;;3493:6:1;3535:14;;;3529:21;3515:12;;;3508:43;3570:6;3613:14;;;3607:21;-1:-1:-1;;;;;1220:31:1;3672:12;;;1208:44;3704:6;3746:14;;;3740:21;3726:12;;;3719:43;3781:6;3823:14;;;3817:21;3803:12;;;3796:43;3858:6;3900:14;;;3894:21;3880:12;;;3873:43;3935:6;3977:14;;;3971:21;3957:12;;;3950:43;4012:6;4054:14;;;4048:21;4034:12;;4027:43;2773:1303::o;4081:268::-;4279:3;4264:19;;4292:51;4268:9;4325:6;4292:51;:::i;4354:599::-;4477:6;4485;4493;4546:2;4534:9;4525:7;4521:23;4517:32;4514:52;;;4562:1;4559;4552:12;4514:52;4601:9;4588:23;4620:39;4653:5;4620:39;:::i;:::-;4678:5;-1:-1:-1;4735:2:1;4720:18;;4707:32;4748:41;4707:32;4748:41;:::i;:::-;4808:7;-1:-1:-1;4867:2:1;4852:18;;4839:32;4880:41;4839:32;4880:41;:::i;5443:460::-;5544:6;5552;5605:2;5593:9;5584:7;5580:23;5576:32;5573:52;;;5621:1;5618;5611:12;5573:52;5661:9;5648:23;-1:-1:-1;;;;;5686:6:1;5683:30;5680:50;;;5726:1;5723;5716:12;5680:50;5765:78;5835:7;5826:6;5815:9;5811:22;5765:78;:::i;:::-;5862:8;;5739:104;;-1:-1:-1;5443:460:1;-1:-1:-1;;;;5443:460:1:o;6101:764::-;6350:2;6402:21;;;6472:13;;6375:18;;;6494:22;;;6321:4;;6350:2;6535;;6553:18;;;;6594:15;;;6321:4;6637:202;6651:6;6648:1;6645:13;6637:202;;;6700:59;6755:3;6746:6;6740:13;5999:12;;-1:-1:-1;;;;;5995:38:1;5983:51;;6083:4;6072:16;;;6066:23;6050:14;;6043:47;5908:188;6700:59;6779:12;;;;6814:15;;;;6673:1;6666:9;6637:202;;;-1:-1:-1;6856:3:1;;6101:764;-1:-1:-1;;;;;;;6101:764:1:o;6870:417::-;6951:6;6959;7012:2;7000:9;6991:7;6987:23;6983:32;6980:52;;;7028:1;7025;7018:12;6980:52;7067:9;7054:23;7086:39;7119:5;7086:39;:::i;:::-;7144:5;-1:-1:-1;7201:2:1;7186:18;;7173:32;7214:41;7173:32;7214:41;:::i;:::-;7274:7;7264:17;;;6870:417;;;;;:::o;7707:127::-;7768:10;7763:3;7759:20;7756:1;7749:31;7799:4;7796:1;7789:15;7823:4;7820:1;7813:15;7839:251;7911:2;7905:9;7953:2;7941:15;;-1:-1:-1;;;;;7971:34:1;;8007:22;;;7968:62;7965:88;;;8033:18;;:::i;:::-;8069:2;8062:22;7839:251;:::o;8095:252::-;8167:2;8161:9;8209:3;8197:16;;-1:-1:-1;;;;;8228:34:1;;8264:22;;;8225:62;8222:88;;;8290:18;;:::i;8352:275::-;8423:2;8417:9;8488:2;8469:13;;-1:-1:-1;;8465:27:1;8453:40;;-1:-1:-1;;;;;8508:34:1;;8544:22;;;8505:62;8502:88;;;8570:18;;:::i;:::-;8606:2;8599:22;8352:275;;-1:-1:-1;8352:275:1:o;8632:183::-;8692:4;-1:-1:-1;;;;;8717:6:1;8714:30;8711:56;;;8747:18;;:::i;:::-;-1:-1:-1;8792:1:1;8788:14;8804:4;8784:25;;8632:183::o;8820:662::-;8874:5;8927:3;8920:4;8912:6;8908:17;8904:27;8894:55;;8945:1;8942;8935:12;8894:55;8981:6;8968:20;9007:4;9031:60;9047:43;9087:2;9047:43;:::i;:::-;9031:60;:::i;:::-;9125:15;;;9211:1;9207:10;;;;9195:23;;9191:32;;;9156:12;;;;9235:15;;;9232:35;;;9263:1;9260;9253:12;9232:35;9299:2;9291:6;9287:15;9311:142;9327:6;9322:3;9319:15;9311:142;;;9393:17;;9381:30;;9431:12;;;;9344;;9311:142;;;-1:-1:-1;9471:5:1;8820:662;-1:-1:-1;;;;;;8820:662:1:o;9487:671::-;9620:6;9628;9636;9689:2;9677:9;9668:7;9664:23;9660:32;9657:52;;;9705:1;9702;9695:12;9657:52;9744:9;9731:23;9763:39;9796:5;9763:39;:::i;:::-;9821:5;-1:-1:-1;9878:2:1;9863:18;;9850:32;9891:41;9850:32;9891:41;:::i;:::-;9951:7;-1:-1:-1;10009:2:1;9994:18;;9981:32;-1:-1:-1;;;;;10025:30:1;;10022:50;;;10068:1;10065;10058:12;10022:50;10091:61;10144:7;10135:6;10124:9;10120:22;10091:61;:::i;:::-;10081:71;;;9487:671;;;;;:::o;10163:999::-;10400:2;10452:21;;;10522:13;;10425:18;;;10544:22;;;10371:4;;10400:2;10585;;10603:18;;;;10644:15;;;10371:4;10687:449;10701:6;10698:1;10695:13;10687:449;;;10760:13;;10798:9;;10786:22;;10862:11;;;10856:18;10849:26;10842:34;10828:12;;;10821:56;10921:11;;;10915:18;10935:4;10911:29;10897:12;;;10890:51;10964:4;11012:11;;;11006:18;-1:-1:-1;;;;;11002:51:1;10988:12;;;10981:73;11083:4;11074:14;;;;11111:15;;;;10723:1;10716:9;10687:449;;11167:726;11402:2;11454:21;;;11524:13;;11427:18;;;11546:22;;;11373:4;;11402:2;11625:15;;;;11599:2;11584:18;;;11373:4;11668:199;11682:6;11679:1;11676:13;11668:199;;;11731:52;11779:3;11770:6;11764:13;11731:52;:::i;:::-;11842:15;;;;11812:6;11803:16;;;;;11704:1;11697:9;11668:199;;11898:749;12014:6;12022;12030;12038;12091:2;12079:9;12070:7;12066:23;12062:32;12059:52;;;12107:1;12104;12097:12;12059:52;12146:9;12133:23;12165:39;12198:5;12165:39;:::i;:::-;12223:5;-1:-1:-1;12280:2:1;12265:18;;12252:32;12293:41;12252:32;12293:41;:::i;:::-;12353:7;-1:-1:-1;12411:2:1;12396:18;;12383:32;-1:-1:-1;;;;;12427:30:1;;12424:50;;;12470:1;12467;12460:12;12424:50;12509:78;12579:7;12570:6;12559:9;12555:22;12509:78;:::i;:::-;11898:749;;;;-1:-1:-1;12606:8:1;-1:-1:-1;;;;11898:749:1:o;12652:792::-;12877:2;12929:21;;;12999:13;;12902:18;;;13021:22;;;12848:4;;12877:2;13062;;13080:18;;;;13121:15;;;12848:4;13164:254;13178:6;13175:1;13172:13;13164:254;;;13237:13;;13275:9;;13263:22;;13325:11;;13319:18;13305:12;;;13298:40;13358:12;;;;13393:15;;;;13200:1;13193:9;13164:254;;13449:619;13575:6;13583;13591;13644:2;13632:9;13623:7;13619:23;13615:32;13612:52;;;13660:1;13657;13650:12;13612:52;13699:9;13686:23;13718:39;13751:5;13718:39;:::i;:::-;13776:5;-1:-1:-1;13832:2:1;13817:18;;13804:32;-1:-1:-1;;;;;13848:30:1;;13845:50;;;13891:1;13888;13881:12;13845:50;13930:78;14000:7;13991:6;13980:9;13976:22;13930:78;:::i;:::-;13449:619;;14027:8;;-1:-1:-1;13904:104:1;;-1:-1:-1;;;;13449:619:1:o;14073:461::-;14126:3;14164:5;14158:12;14191:6;14186:3;14179:19;14217:4;14246:2;14241:3;14237:12;14230:19;;14283:2;14276:5;14272:14;14304:1;14314:195;14328:6;14325:1;14322:13;14314:195;;;14393:13;;-1:-1:-1;;;;;14389:39:1;14377:52;;14449:12;;;;14484:15;;;;14425:1;14343:9;14314:195;;;-1:-1:-1;14525:3:1;;14073:461;-1:-1:-1;;;;;14073:461:1:o;14539:435::-;14592:3;14630:5;14624:12;14657:6;14652:3;14645:19;14683:4;14712:2;14707:3;14703:12;14696:19;;14749:2;14742:5;14738:14;14770:1;14780:169;14794:6;14791:1;14788:13;14780:169;;;14855:13;;14843:26;;14889:12;;;;14924:15;;;;14816:1;14809:9;14780:169;;14979:258;15051:1;15061:113;15075:6;15072:1;15069:13;15061:113;;;15151:11;;;15145:18;15132:11;;;15125:39;15097:2;15090:10;15061:113;;;15192:6;15189:1;15186:13;15183:48;;;15227:1;15218:6;15213:3;15209:16;15202:27;15183:48;;14979:258;;;:::o;15242:::-;15284:3;15322:5;15316:12;15349:6;15344:3;15337:19;15365:63;15421:6;15414:4;15409:3;15405:14;15398:4;15391:5;15387:16;15365:63;:::i;:::-;15482:2;15461:15;-1:-1:-1;;15457:29:1;15448:39;;;;15489:4;15444:50;;15242:258;-1:-1:-1;;15242:258:1:o;15505:616::-;15557:3;15595:5;15589:12;15622:6;15617:3;15610:19;15648:4;15689:2;15684:3;15680:12;15714:11;15741;15734:18;;15791:6;15788:1;15784:14;15777:5;15773:26;15761:38;;15833:2;15826:5;15822:14;15854:1;15864:231;15878:6;15875:1;15872:13;15864:231;;;15949:5;15943:4;15939:16;15934:3;15927:29;15977:38;16010:4;16001:6;15995:13;15977:38;:::i;:::-;16073:12;;;;15969:46;-1:-1:-1;16038:15:1;;;;15900:1;15893:9;15864:231;;16126:2691;16336:4;16365:2;16405;16394:9;16390:18;16435:2;16424:9;16417:21;16458:6;16493;16487:13;16524:6;16516;16509:22;16550:2;16540:12;;16583:2;16572:9;16568:18;16561:25;;16645:2;16635:6;16632:1;16628:14;16617:9;16613:30;16609:39;16683:2;16675:6;16671:15;16704:1;16714:2074;16728:6;16725:1;16722:13;16714:2074;;;16793:22;;;-1:-1:-1;;16789:36:1;16777:49;;16849:13;;16919:9;;16904:25;;16968:11;;;16962:18;-1:-1:-1;;;;;1220:31:1;;17026:15;;;1208:44;16885:6;;16993:49;17093:2;17089;17085:11;17079:18;17074:2;17066:6;17062:15;17055:43;17121:4;17174:2;17170;17166:11;17160:18;17215:2;17210;17202:6;17198:15;17191:27;17245:61;17302:2;17294:6;17290:15;17274:14;17245:61;:::i;:::-;17231:75;;;;17329:4;17382:2;17378;17374:11;17368:18;17435:6;17427;17423:19;17418:2;17410:6;17406:15;17399:44;17470:52;17515:6;17499:14;17470:52;:::i;:::-;17456:66;;;;17545:4;17598:2;17594;17590:11;17584:18;17651:6;17643;17639:19;17634:2;17626:6;17622:15;17615:44;17686:51;17730:6;17714:14;17686:51;:::i;:::-;17672:65;;;;17760:4;17813:2;17809;17805:11;17799:18;17866:6;17858;17854:19;17849:2;17841:6;17837:15;17830:44;17901:51;17945:6;17929:14;17901:51;:::i;:::-;17975:4;18022:11;;;18016:18;17999:15;;;17992:43;18059:6;18109:12;;;18103:19;18085:16;;;18078:45;18147:6;18197:12;;;18191:19;18173:16;;;18166:45;18235:6;18285:12;;;18279:19;18261:16;;;18254:45;18323:6;18373:12;;;18367:19;18349:16;;;18342:45;18411:6;18458:12;;;18452:19;2747:13;2740:21;18516:16;;;2728:34;18557:6;18604:12;;;18598:19;2747:13;2740:21;18662:16;;;;2728:34;;;;-1:-1:-1;;;18766:12:1;;;;18731:15;;;;16750:1;16743:9;16714:2074;;;-1:-1:-1;18805:6:1;;16126:2691;-1:-1:-1;;;;;;;;16126:2691:1:o;19264:887::-;19447:2;19458:21;;;19550:13;;19599:4;19579:18;;;19572:32;19653:19;;19517:3;19502:19;;19681:22;;;19418:4;;19447:2;19761:21;;;19418:4;;19734:3;19719:19;;;19810:195;19824:6;19821:1;19818:13;19810:195;;;19889:13;;-1:-1:-1;;;;;19885:39:1;19873:52;;19980:15;;;;19921:1;19839:9;;;;;19945:12;;;;19810:195;;;19814:3;20059:2;20051:6;20047:15;20041:22;20036:2;20025:9;20021:18;20014:50;20120:2;20112:6;20108:15;20102:22;20095:4;20084:9;20080:20;20073:52;20142:3;20134:11;;;;;;19264:887;;;;:::o;20771:2593::-;20971:4;21000:2;21040;21029:9;21025:18;21070:2;21059:9;21052:21;21093:6;21128;21122:13;21159:6;21151;21144:22;21185:2;21175:12;;21218:2;21207:9;21203:18;21196:25;;21280:2;21270:6;21267:1;21263:14;21252:9;21248:30;21244:39;21318:2;21310:6;21306:15;21339:1;21349:1986;21363:6;21360:1;21357:13;21349:1986;;;21428:22;;;-1:-1:-1;;21424:36:1;21412:49;;21484:13;;21554:9;;21539:25;;21603:11;;;21597:18;-1:-1:-1;;;;;1220:31:1;;21661:15;;;1208:44;21520:6;;21628:49;21728:2;21724;21720:11;21714:18;21709:2;21701:6;21697:15;21690:43;21756:4;21809:2;21805;21801:11;21795:18;21850:2;21845;21837:6;21833:15;21826:27;21880:61;21937:2;21929:6;21925:15;21909:14;21880:61;:::i;:::-;21866:75;;;;21964:4;22017:2;22013;22009:11;22003:18;22070:6;22062;22058:19;22053:2;22045:6;22041:15;22034:44;22105:52;22150:6;22134:14;22105:52;:::i;:::-;22091:66;;;;22180:4;22233:2;22229;22225:11;22219:18;22286:6;22278;22274:19;22269:2;22261:6;22257:15;22250:44;22321:51;22365:6;22349:14;22321:51;:::i;:::-;22307:65;;;;22395:4;22448:2;22444;22440:11;22434:18;22501:6;22493;22489:19;22484:2;22476:6;22472:15;22465:44;22536:51;22580:6;22564:14;22536:51;:::i;:::-;22610:4;22657:11;;;22651:18;22634:15;;;22627:43;22694:6;22744:12;;;22738:19;22720:16;;;22713:45;22782:6;22832:12;;;22826:19;22808:16;;;22801:45;22870:6;22920:12;;;22914:19;22896:16;;;22889:45;22958:6;23005:12;;;22999:19;2747:13;2740:21;23063:16;;;2728:34;23104:6;23151:12;;;23145:19;2747:13;2740:21;23209:16;;;;2728:34;;;;-1:-1:-1;;;23313:12:1;;;;23278:15;;;;21385:1;21378:9;21349:1986;;24036:994;24263:2;24315:21;;;24385:13;;24288:18;;;24407:22;;;24234:4;;24263:2;24448;;24466:18;;;;24507:15;;;24234:4;24550:454;24564:6;24561:1;24558:13;24550:454;;;24623:13;;24661:9;;24649:22;;24725:11;;;24719:18;24712:26;24705:34;24691:12;;;24684:56;24794:11;;;24788:18;24781:26;24774:34;24760:12;;;24753:56;24832:4;24880:11;;;24874:18;-1:-1:-1;;;;;24870:51:1;24856:12;;;24849:73;24951:4;24942:14;;;;24979:15;;;;24586:1;24579:9;24550:454;;25467:268;25665:3;25650:19;;25678:51;25654:9;25711:6;25678:51;:::i;25740:288::-;5999:12;;-1:-1:-1;;;;;5995:38:1;5983:51;;6083:4;6072:16;;;6066:23;6050:14;;;6043:47;25952:2;25937:18;;25964:58;5908:188;26033:127;26094:10;26089:3;26085:20;26082:1;26075:31;26125:4;26122:1;26115:15;26149:4;26146:1;26139:15;26165:127;26226:10;26221:3;26217:20;26214:1;26207:31;26257:4;26254:1;26247:15;26281:4;26278:1;26271:15;26297:135;26336:3;-1:-1:-1;;26357:17:1;;26354:43;;;26377:18;;:::i;:::-;-1:-1:-1;26424:1:1;26413:13;;26297:135::o;26437:184::-;26507:6;26560:2;26548:9;26539:7;26535:23;26531:32;26528:52;;;26576:1;26573;26566:12;26528:52;-1:-1:-1;26599:16:1;;26437:184;-1:-1:-1;26437:184:1:o;26626:287::-;26724:6;26777:2;26765:9;26756:7;26752:23;26748:32;26745:52;;;26793:1;26790;26783:12;26745:52;26825:9;26819:16;26844:39;26877:5;26844:39;:::i;27126:164::-;27202:13;;27251;;27244:21;27234:32;;27224:60;;27280:1;27277;27270:12;27224:60;27126:164;;;:::o;27295:263::-;27371:6;27379;27432:2;27420:9;27411:7;27407:23;27403:32;27400:52;;;27448:1;27445;27438:12;27400:52;27471:37;27498:9;27471:37;:::i;:::-;27461:47;;27548:2;27537:9;27533:18;27527:25;27517:35;;27295:263;;;;;:::o;27563:378::-;27639:5;-1:-1:-1;;;;;27665:6:1;27662:30;27659:56;;;27695:18;;:::i;:::-;27733:57;27778:2;27757:15;;-1:-1:-1;;27753:29:1;27784:4;27749:40;27733:57;:::i;:::-;27724:66;;27813:6;27806:5;27799:21;27853:3;27844:6;27839:3;27835:16;27832:25;27829:45;;;27870:1;27867;27860:12;27829:45;27883:52;27928:6;27921:4;27914:5;27910:16;27905:3;27883:52;:::i;27946:237::-;28000:5;28053:3;28046:4;28038:6;28034:17;28030:27;28020:55;;28071:1;28068;28061:12;28020:55;28093:84;28173:3;28164:6;28158:13;28151:4;28143:6;28139:17;28093:84;:::i;28188:337::-;28268:6;28321:2;28309:9;28300:7;28296:23;28292:32;28289:52;;;28337:1;28334;28327:12;28289:52;28370:9;28364:16;-1:-1:-1;;;;;28395:6:1;28392:30;28389:50;;;28435:1;28432;28425:12;28389:50;28458:61;28511:7;28502:6;28491:9;28487:22;28458:61;:::i;:::-;28448:71;28188:337;-1:-1:-1;;;;28188:337:1:o;28530:146::-;28609:13;;28631:39;28609:13;28631:39;:::i;28945:160::-;29022:13;;29075:4;29064:16;;29054:27;;29044:55;;29095:1;29092;29085:12;29110:204;29178:6;29231:2;29219:9;29210:7;29206:23;29202:32;29199:52;;;29247:1;29244;29237:12;29199:52;29270:38;29298:9;29270:38;:::i;29319:371::-;-1:-1:-1;;;;;;29504:33:1;;29492:46;;29561:13;;29474:3;;29583:61;29561:13;29633:1;29624:11;;29617:4;29605:17;;29583:61;:::i;:::-;29664:16;;;;29682:1;29660:24;;29319:371;-1:-1:-1;;;29319:371:1:o;29695:274::-;29824:3;29862:6;29856:13;29878:53;29924:6;29919:3;29912:4;29904:6;29900:17;29878:53;:::i;:::-;29947:16;;;;;29695:274;-1:-1:-1;;29695:274:1:o;29974:183::-;30052:13;;-1:-1:-1;;;;;30094:38:1;;30084:49;;30074:77;;30147:1;30144;30137:12;30162:206;30231:6;30284:2;30272:9;30263:7;30259:23;30255:32;30252:52;;;30300:1;30297;30290:12;30252:52;30323:39;30352:9;30323:39;:::i;30652:464::-;30747:6;30800:2;30788:9;30779:7;30775:23;30771:32;30768:52;;;30816:1;30813;30806:12;30768:52;30842:22;;:::i;:::-;30887:37;30914:9;30887:37;:::i;:::-;30880:5;30873:52;30957:47;31000:2;30989:9;30985:18;30957:47;:::i;:::-;30952:2;30945:5;30941:14;30934:71;31037:48;31081:2;31070:9;31066:18;31037:48;:::i;:::-;31032:2;31021:14;;31014:72;31025:5;30652:464;-1:-1:-1;;;30652:464:1:o;31121:276::-;31179:6;31232:2;31220:9;31211:7;31207:23;31203:32;31200:52;;;31248:1;31245;31238:12;31200:52;31287:9;31274:23;31337:10;31330:5;31326:22;31319:5;31316:33;31306:61;;31363:1;31360;31353:12;31879:659;31944:5;31997:3;31990:4;31982:6;31978:17;31974:27;31964:55;;32015:1;32012;32005:12;31964:55;32044:6;32038:13;32070:4;32094:60;32110:43;32150:2;32110:43;:::i;32094:60::-;32188:15;;;32274:1;32270:10;;;;32258:23;;32254:32;;;32219:12;;;;32298:15;;;32295:35;;;32326:1;32323;32316:12;32295:35;32362:2;32354:6;32350:15;32374:135;32390:6;32385:3;32382:15;32374:135;;;32456:10;;32444:23;;32487:12;;;;32407;;32374:135;;32543:896;32607:5;32660:3;32653:4;32645:6;32641:17;32637:27;32627:55;;32678:1;32675;32668:12;32627:55;32707:6;32701:13;32733:4;32757:60;32773:43;32813:2;32773:43;:::i;32757:60::-;32851:15;;;32937:1;32933:10;;;;32921:23;;32917:32;;;32882:12;;;;32961:15;;;32958:35;;;32989:1;32986;32979:12;32958:35;33025:2;33017:6;33013:15;33037:373;33053:6;33048:3;33045:15;33037:373;;;33132:3;33126:10;-1:-1:-1;;;;;33155:11:1;33152:35;33149:125;;;33228:1;33257:2;33253;33246:14;33149:125;33299:68;33363:3;33358:2;33344:11;33336:6;33332:24;33328:33;33299:68;:::i;:::-;33287:81;;-1:-1:-1;33388:12:1;;;;33070;;33037:373;;33444:1089;33507:5;33560:3;33553:4;33545:6;33541:17;33537:27;33527:55;;33578:1;33575;33568:12;33527:55;33607:6;33601:13;33633:4;33657:60;33673:43;33713:2;33673:43;:::i;33657:60::-;33751:15;;;33837:1;33833:10;;;;33821:23;;33817:32;;;33782:12;;;;33861:15;;;33858:35;;;33889:1;33886;33879:12;33858:35;33925:2;33917:6;33913:15;33937:567;33953:6;33948:3;33945:15;33937:567;;;34032:3;34026:10;-1:-1:-1;;;;;34055:11:1;34052:35;34049:125;;;34128:1;34157:2;34153;34146:14;34049:125;34197:24;;34256:2;34248:11;;34244:21;-1:-1:-1;34234:119:1;;34307:1;34336:2;34332;34325:14;34234:119;34378:83;34457:3;34451:2;34447;34443:11;34437:18;34432:2;34428;34424:11;34378:83;:::i;:::-;34366:96;;-1:-1:-1;34482:12:1;;;;33970;;33937:567;;34538:1694;34754:6;34762;34770;34778;34831:3;34819:9;34810:7;34806:23;34802:33;34799:53;;;34848:1;34845;34838:12;34799:53;34881:9;34875:16;-1:-1:-1;;;;;34951:2:1;34943:6;34940:14;34937:34;;;34967:1;34964;34957:12;34937:34;35005:6;34994:9;34990:22;34980:32;;35050:7;35043:4;35039:2;35035:13;35031:27;35021:55;;35072:1;35069;35062:12;35021:55;35101:2;35095:9;35123:4;35147:60;35163:43;35203:2;35163:43;:::i;35147:60::-;35241:15;;;35323:1;35319:10;;;;35311:19;;35307:28;;;35272:12;;;;35347:19;;;35344:39;;;35379:1;35376;35369:12;35344:39;35403:11;;;;35423:218;35439:6;35434:3;35431:15;35423:218;;;35512:3;35506:10;35529:39;35562:5;35529:39;:::i;:::-;35581:18;;35456:12;;;;35619;;;;35423:218;;;35696:18;;;35690:25;35660:5;;-1:-1:-1;35690:25:1;;-1:-1:-1;;;35727:16:1;;;35724:36;;;35756:1;35753;35746:12;35724:36;35779:74;35845:7;35834:8;35823:9;35819:24;35779:74;:::i;:::-;35769:84;;35899:2;35888:9;35884:18;35878:25;35862:41;;35928:2;35918:8;35915:16;35912:36;;;35944:1;35941;35934:12;35912:36;35967:73;36032:7;36021:8;36010:9;36006:24;35967:73;:::i;:::-;35957:83;;36086:2;36075:9;36071:18;36065:25;36049:41;;36115:2;36105:8;36102:16;36099:36;;;36131:1;36128;36121:12;36099:36;;36154:72;36218:7;36207:8;36196:9;36192:24;36154:72;:::i;:::-;36144:82;;;34538:1694;;;;;;;:::o;36237:306::-;36325:6;36333;36341;36394:2;36382:9;36373:7;36369:23;36365:32;36362:52;;;36410:1;36407;36400:12;36362:52;36439:9;36433:16;36423:26;;36489:2;36478:9;36474:18;36468:25;36458:35;;36533:2;36522:9;36518:18;36512:25;36502:35;;36237:306;;;;;:::o;36548:979::-;36658:6;36689:2;36732;36720:9;36711:7;36707:23;36703:32;36700:52;;;36748:1;36745;36738:12;36700:52;36781:9;36775:16;-1:-1:-1;;;;;36806:6:1;36803:30;36800:50;;;36846:1;36843;36836:12;36800:50;36869:22;;36922:4;36914:13;;36910:27;-1:-1:-1;36900:55:1;;36951:1;36948;36941:12;36900:55;36980:2;36974:9;37003:60;37019:43;37059:2;37019:43;:::i;37003:60::-;37097:15;;;37179:1;37175:10;;;;37167:19;;37163:28;;;37128:12;;;;37203:19;;;37200:39;;;37235:1;37232;37225:12;37200:39;37259:11;;;;37279:218;37295:6;37290:3;37287:15;37279:218;;;37368:3;37362:10;37385:39;37418:5;37385:39;:::i;:::-;37437:18;;37312:12;;;;37475;;;;37279:218;;;37516:5;36548:979;-1:-1:-1;;;;;;;36548:979:1:o;37532:463::-;37627:6;37680:2;37668:9;37659:7;37655:23;37651:32;37648:52;;;37696:1;37693;37686:12;37648:52;37722:22;;:::i;:::-;37767:37;37794:9;37767:37;:::i;:::-;37760:5;37753:52;37837:46;37879:2;37868:9;37864:18;37837:46;:::i;39321:128::-;39361:3;39392:1;39388:6;39385:1;39382:13;39379:39;;;39398:18;;:::i;:::-;-1:-1:-1;39434:9:1;;39321:128::o;39454:220::-;39603:2;39592:9;39585:21;39566:4;39623:45;39664:2;39653:9;39649:18;39641:6;39623:45;:::i;39679:125::-;39719:4;39747:1;39744;39741:8;39738:34;;;39752:18;;:::i;:::-;-1:-1:-1;39789:9:1;;39679:125::o;39809:924::-;39905:6;39958:3;39946:9;39937:7;39933:23;39929:33;39926:53;;;39975:1;39972;39965:12;39926:53;40001:22;;:::i;:::-;40052:9;40046:16;40039:5;40032:31;40095:49;40140:2;40129:9;40125:18;40095:49;:::i;:::-;40090:2;40083:5;40079:14;40072:73;40198:2;40187:9;40183:18;40177:25;40172:2;40165:5;40161:14;40154:49;40256:2;40245:9;40241:18;40235:25;40230:2;40223:5;40219:14;40212:49;40315:3;40304:9;40300:19;40294:26;40288:3;40281:5;40277:15;40270:51;40375:3;40364:9;40360:19;40354:26;40348:3;40341:5;40337:15;40330:51;40435:3;40424:9;40420:19;40414:26;40408:3;40401:5;40397:15;40390:51;40495:3;40484:9;40480:19;40474:26;40468:3;40461:5;40457:15;40450:51;40520:3;40555:46;40597:2;40586:9;40582:18;40555:46;:::i;:::-;40539:14;;;40532:70;40621:3;40656:46;40683:18;;;40656:46;:::i;:::-;40640:14;;;40633:70;40644:5;39809:924;-1:-1:-1;;;39809:924:1:o;40738:789::-;40874:6;40882;40890;40898;40906;40914;40922;40930;40938;40991:3;40979:9;40970:7;40966:23;40962:33;40959:53;;;41008:1;41005;40998:12;40959:53;41037:9;41031:16;41021:26;;41090:2;41079:9;41075:18;41069:25;41103:39;41136:5;41103:39;:::i;:::-;41161:5;41151:15;;;41206:2;41195:9;41191:18;41185:25;41175:35;;41250:2;41239:9;41235:18;41229:25;41219:35;;41294:3;41283:9;41279:19;41273:26;41263:36;;41339:3;41328:9;41324:19;41318:26;41308:36;;41384:3;41373:9;41369:19;41363:26;41353:36;;41408:47;41450:3;41439:9;41435:19;41408:47;:::i;:::-;41398:57;;41474:47;41516:3;41505:9;41501:19;41474:47;:::i;:::-;41464:57;;40738:789;;;;;;;;;;;:::o
Swarm Source
ipfs://c23660bb5a4b5a874581aadf874880fe5c7d59841cc18597e39f10a55eb68ba8
Age | Block | Fee Address | BC Fee Address | Voting Power | Jailed | Incoming |
---|
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.