Source Code
Latest 25 from a total of 382 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| _set Borrow Paus... | 14198538 | 2 days ago | IN | 0 GLMR | 0.00597575 | ||||
| _set Borrow Paus... | 14198537 | 2 days ago | IN | 0 GLMR | 0.00597575 | ||||
| _set Borrow Paus... | 14198535 | 2 days ago | IN | 0 GLMR | 0.00597575 | ||||
| _set Borrow Paus... | 14198532 | 2 days ago | IN | 0 GLMR | 0.00597575 | ||||
| _set Borrow Paus... | 14198529 | 2 days ago | IN | 0 GLMR | 0.00597575 | ||||
| _set Borrow Paus... | 14198526 | 2 days ago | IN | 0 GLMR | 0.00597575 | ||||
| _set Borrow Paus... | 14198521 | 2 days ago | IN | 0 GLMR | 0.00597575 | ||||
| _set Borrow Paus... | 14198514 | 2 days ago | IN | 0 GLMR | 0.00597575 | ||||
| Enter Markets | 14136068 | 7 days ago | IN | 0 GLMR | 0.0119675 | ||||
| Enter Markets | 14082556 | 11 days ago | IN | 0 GLMR | 0.0119515 | ||||
| Exit Market | 14082421 | 11 days ago | IN | 0 GLMR | 0.090471 | ||||
| Enter Markets | 14079930 | 11 days ago | IN | 0 GLMR | 0.00598375 | ||||
| Enter Markets | 14073652 | 12 days ago | IN | 0 GLMR | 0.00598375 | ||||
| Enter Markets | 14057547 | 13 days ago | IN | 0 GLMR | 0.00598375 | ||||
| Enter Markets | 14001667 | 18 days ago | IN | 0 GLMR | 0.00732005 | ||||
| Enter Markets | 13978074 | 20 days ago | IN | 0 GLMR | 0.0119515 | ||||
| Enter Markets | 13959199 | 21 days ago | IN | 0 GLMR | 0.00598375 | ||||
| Enter Markets | 13959157 | 21 days ago | IN | 0 GLMR | 0.00589675 | ||||
| Enter Markets | 13957701 | 21 days ago | IN | 0 GLMR | 0.0119515 | ||||
| Enter Markets | 13955908 | 21 days ago | IN | 0 GLMR | 0.0119515 | ||||
| Enter Markets | 13954000 | 22 days ago | IN | 0 GLMR | 0.00597575 | ||||
| Enter Markets | 13929868 | 24 days ago | IN | 0 GLMR | 0.00598375 | ||||
| Exit Market | 13850644 | 30 days ago | IN | 0 GLMR | 0.0845195 | ||||
| Exit Market | 13758132 | 37 days ago | IN | 0 GLMR | 0.02240475 | ||||
| Enter Markets | 13758110 | 37 days ago | IN | 0 GLMR | 0.00597575 |
View more zero value Internal Transactions in Advanced View mode
Cross-Chain Transactions
Loading...
Loading
Contract Name:
Comptroller
Compiler Version
v0.8.10+commit.fc410830
Contract Source Code (Solidity)
/**
*Submitted for verification at moonbeam.moonscan.io on 2023-06-07
*/
// SPDX-License-Identifier: BSD-3-Clause
// File: contracts/Orbiter/Governance/OrbiterInterface.sol
pragma solidity ^0.8.10;
abstract contract OrbiterInterface {
function allowance(address account, address spender)
external
view
virtual
returns (uint256);
function approve(address spender, uint256 rawAmount)
external
virtual
returns (bool);
function balanceOf(address account) external view virtual returns (uint256);
function transfer(address dst, uint256 rawAmount)
external
virtual
returns (bool);
function transferFrom(
address src,
address dst,
uint256 rawAmount
) external virtual returns (bool);
function delegate(address delegatee) public virtual;
function delegateBySig(
address delegatee,
uint256 nonce,
uint256 expiry,
uint8 v,
bytes32 r,
bytes32 s
) public virtual;
function getCurrentVotes(address account)
external
view
virtual
returns (uint96);
function getPriorVotes(address account, uint256 blockNumber)
public
view
virtual
returns (uint96);
}
// File: contracts/Orbiter/IncentiveInterface.sol
pragma solidity 0.8.10;
abstract contract IncentiveInterface {
function distributeSupplier(address cToken, address supplier)
external
virtual;
function distributeBorrower(address cToken, address borrower)
external
virtual;
}
// File: contracts/Orbiter/ExponentialNoError.sol
pragma solidity ^0.8.10;
/**
* @title Exponential module for storing fixed-precision decimals
* @author Compound
* @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.
* Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:
* `Exp({mantissa: 5100000000000000000})`.
*/
contract 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)});
}
}
// File: contracts/Orbiter/EIP20Interface.sol
pragma solidity ^0.8.10;
/**
* @title ERC 20 Token Standard Interface
* https://eips.ethereum.org/EIPS/eip-20
*/
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);
}
// File: contracts/Orbiter/ErrorReporter.sol
pragma solidity ^0.8.10;
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,
SET_INCENTIVE_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();
}
// File: contracts/Orbiter/EIP20NonStandardInterface.sol
pragma solidity ^0.8.10;
/**
* @title EIP20NonStandardInterface
* @dev Version of ERC20 with no return values for `transfer` and `transferFrom`
* See https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca
*/
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);
}
// File: contracts/Orbiter/InterestRateModel.sol
pragma solidity ^0.8.10;
/**
* @title Compound's InterestRateModel Interface
* @author Compound
*/
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);
}
// File: contracts/Orbiter/ComptrollerInterface.sol
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);
}
// File: contracts/Orbiter/CTokenInterfaces.sol
pragma solidity ^0.8.10;
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;
}
// File: contracts/Orbiter/CToken.sol
pragma solidity ^0.8.10;
/**
* @title Compound's CToken Contract
* @notice Abstract base for CTokens
* @author Compound
*/
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
}
}
// File: contracts/Orbiter/PriceOracle.sol
pragma solidity ^0.8.10;
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);
}
// File: contracts/Orbiter/ComptrollerStorage.sol
pragma solidity ^0.8.10;
contract UnitrollerAdminStorage {
/**
* @notice Administrator for this contract
*/
address public admin;
/**
* @notice Pending administrator for this contract
*/
address public pendingAdmin;
/**
* @notice Active brains of Unitroller
*/
address public comptrollerImplementation;
/**
* @notice Pending brains of Unitroller
*/
address public pendingComptrollerImplementation;
}
contract ComptrollerV1Storage is UnitrollerAdminStorage {
/**
* @notice Oracle which gives the price of any given asset
*/
PriceOracle public oracle;
/**
* @notice Incentive
*/
IncentiveInterface public incentive;
/**
* @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow
*/
uint public closeFactorMantissa;
/**
* @notice Multiplier representing the discount on collateral that a liquidator receives
*/
uint public liquidationIncentiveMantissa;
/**
* @notice Max number of assets a single account can participate in (borrow or use as collateral)
*/
uint public maxAssets;
/**
* @notice Per-account mapping of "assets you are in", capped by maxAssets
*/
mapping(address => CToken[]) public accountAssets;
}
contract ComptrollerV2Storage is ComptrollerV1Storage {
struct Market {
// Whether or not this market is listed
bool isListed;
// Multiplier representing the most one can borrow against their collateral in this market.
// For instance, 0.9 to allow borrowing 90% of collateral value.
// Must be between 0 and 1, and stored as a mantissa.
uint collateralFactorMantissa;
// Per-market mapping of "accounts in this asset"
mapping(address => bool) accountMembership;
// Whether or not this market receives COMP
bool isComped;
}
/**
* @notice Official mapping of cTokens -> Market metadata
* @dev Used e.g. to determine if a market is supported
*/
mapping(address => Market) public markets;
/**
* @notice The Pause Guardian can pause certain actions as a safety mechanism.
* Actions which allow users to remove their own assets cannot be paused.
* Liquidation / seizing / transfer can only be paused globally, not by market.
*/
address public pauseGuardian;
bool public _mintGuardianPaused;
bool public _borrowGuardianPaused;
bool public transferGuardianPaused;
bool public seizeGuardianPaused;
mapping(address => bool) public mintGuardianPaused;
mapping(address => bool) public borrowGuardianPaused;
}
contract ComptrollerV3Storage is ComptrollerV2Storage {
struct CompMarketState {
// The market's last updated compBorrowIndex or compSupplyIndex
uint224 index;
// The block number the index was last updated at
uint32 block;
}
/// @notice A list of all markets
CToken[] public allMarkets;
/// @notice The rate at which the flywheel distributes COMP, per block
uint public compRate;
/// @notice The portion of compRate that each market currently receives
mapping(address => uint) public compSpeeds;
/// @notice The COMP market supply state for each market
mapping(address => CompMarketState) public compSupplyState;
/// @notice The COMP market borrow state for each market
mapping(address => CompMarketState) public compBorrowState;
/// @notice The COMP borrow index for each market for each supplier as of the last time they accrued COMP
mapping(address => mapping(address => uint)) public compSupplierIndex;
/// @notice The COMP borrow index for each market for each borrower as of the last time they accrued COMP
mapping(address => mapping(address => uint)) public compBorrowerIndex;
/// @notice The COMP accrued but not yet transferred to each user
mapping(address => uint) public compAccrued;
}
contract ComptrollerV4Storage is ComptrollerV3Storage {
// @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.
address public borrowCapGuardian;
// @notice Borrow caps enforced by borrowAllowed for each cToken address. Defaults to zero which corresponds to unlimited borrowing.
mapping(address => uint) public borrowCaps;
}
contract ComptrollerV5Storage is ComptrollerV4Storage {
/// @notice The portion of COMP that each contributor receives per block
mapping(address => uint) public compContributorSpeeds;
/// @notice Last block at which a contributor's COMP rewards have been allocated
mapping(address => uint) public lastContributorBlock;
}
contract ComptrollerV6Storage is ComptrollerV5Storage {
/// @notice The rate at which comp is distributed to the corresponding borrow market (per block)
mapping(address => uint) public compBorrowSpeeds;
/// @notice The rate at which comp is distributed to the corresponding supply market (per block)
mapping(address => uint) public compSupplySpeeds;
}
contract ComptrollerV7Storage is ComptrollerV6Storage {
/// @notice Flag indicating whether the function to fix COMP accruals has been executed (RE: proposal 62 bug)
bool public proposal65FixExecuted;
/// @notice Accounting storage mapping account addresses to how much COMP they owe the protocol.
mapping(address => uint) public compReceivable;
}
// File: contracts/Orbiter/Unitroller.sol
pragma solidity ^0.8.10;
/**
* @title ComptrollerCore
* @dev Storage for the comptroller is at this address, while execution is delegated to the `comptrollerImplementation`.
* CTokens should reference this contract as their comptroller.
*/
contract Unitroller is UnitrollerAdminStorage, ComptrollerErrorReporter {
/**
* @notice Emitted when pendingComptrollerImplementation is changed
*/
event NewPendingImplementation(address oldPendingImplementation, address newPendingImplementation);
/**
* @notice Emitted when pendingComptrollerImplementation is accepted, which means comptroller implementation is updated
*/
event NewImplementation(address oldImplementation, address newImplementation);
/**
* @notice Emitted when pendingAdmin is changed
*/
event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);
/**
* @notice Emitted when pendingAdmin is accepted, which means admin is updated
*/
event NewAdmin(address oldAdmin, address newAdmin);
constructor() public {
// Set admin to caller
admin = msg.sender;
}
/*** Admin Functions ***/
function _setPendingImplementation(address newPendingImplementation) public returns (uint) {
if (msg.sender != admin) {
return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_IMPLEMENTATION_OWNER_CHECK);
}
address oldPendingImplementation = pendingComptrollerImplementation;
pendingComptrollerImplementation = newPendingImplementation;
emit NewPendingImplementation(oldPendingImplementation, pendingComptrollerImplementation);
return uint(Error.NO_ERROR);
}
/**
* @notice Accepts new implementation of comptroller. msg.sender must be pendingImplementation
* @dev Admin function for new implementation to accept it's role as implementation
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/
function _acceptImplementation() public returns (uint) {
// Check caller is pendingImplementation and pendingImplementation ≠ address(0)
if (msg.sender != pendingComptrollerImplementation || pendingComptrollerImplementation == address(0)) {
return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK);
}
// Save current values for inclusion in log
address oldImplementation = comptrollerImplementation;
address oldPendingImplementation = pendingComptrollerImplementation;
comptrollerImplementation = pendingComptrollerImplementation;
pendingComptrollerImplementation = address(0);
emit NewImplementation(oldImplementation, comptrollerImplementation);
emit NewPendingImplementation(oldPendingImplementation, pendingComptrollerImplementation);
return uint(Error.NO_ERROR);
}
/**
* @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 newPendingAdmin) public returns (uint) {
// Check caller = admin
if (msg.sender != admin) {
return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);
}
// 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 uint(Error.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() public returns (uint) {
// Check caller is pendingAdmin and pendingAdmin ≠ address(0)
if (msg.sender != pendingAdmin || msg.sender == address(0)) {
return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);
}
// 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 = address(0);
emit NewAdmin(oldAdmin, admin);
emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);
return uint(Error.NO_ERROR);
}
/**
* @dev Delegates execution to an implementation contract.
* It returns to the external caller whatever the implementation returns
* or forwards reverts.
*/
fallback() payable external {
// delegate all other functions to current implementation
(bool success, ) = comptrollerImplementation.delegatecall(msg.data);
assembly {
let free_mem_ptr := mload(0x40)
returndatacopy(free_mem_ptr, 0, returndatasize())
switch success
case 0 { revert(free_mem_ptr, returndatasize()) }
default { return(free_mem_ptr, returndatasize()) }
}
}
}
// File: contracts/Orbiter/Comptroller.sol
pragma solidity 0.8.10;
/**
* @title Compound's Comptroller Contract
* @author Compound
*/
contract Comptroller is
ComptrollerV7Storage,
ComptrollerInterface,
ComptrollerErrorReporter,
ExponentialNoError
{
/// @notice Emitted when an admin supports a market
event MarketListed(CToken cToken);
/// @notice Emitted when an account enters a market
event MarketEntered(CToken cToken, address account);
/// @notice Emitted when an account exits a market
event MarketExited(CToken cToken, address account);
/// @notice Emitted when close factor is changed by admin
event NewCloseFactor(
uint256 oldCloseFactorMantissa,
uint256 newCloseFactorMantissa
);
/// @notice Emitted when a collateral factor is changed by admin
event NewCollateralFactor(
CToken cToken,
uint256 oldCollateralFactorMantissa,
uint256 newCollateralFactorMantissa
);
/// @notice Emitted when liquidation incentive is changed by admin
event NewLiquidationIncentive(
uint256 oldLiquidationIncentiveMantissa,
uint256 newLiquidationIncentiveMantissa
);
/// @notice Emitted when price oracle is changed
event NewPriceOracle(
PriceOracle oldPriceOracle,
PriceOracle newPriceOracle
);
/// @notice Emitted when incentive is changed
event NewIncentive(
IncentiveInterface oldInscentive,
IncentiveInterface newInscentive
);
/// @notice Emitted when pause guardian is changed
event NewPauseGuardian(address oldPauseGuardian, address newPauseGuardian);
/// @notice Emitted when an action is paused globally
event ActionPaused(string action, bool pauseState);
/// @notice Emitted when an action is paused on a market
event ActionPaused(CToken cToken, string action, bool pauseState);
/// @notice Emitted when a new borrow-side COMP speed is calculated for a market
event CompBorrowSpeedUpdated(CToken indexed cToken, uint256 newSpeed);
/// @notice Emitted when a new supply-side COMP speed is calculated for a market
event CompSupplySpeedUpdated(CToken indexed cToken, uint256 newSpeed);
/// @notice Emitted when a new COMP speed is set for a contributor
event ContributorCompSpeedUpdated(
address indexed contributor,
uint256 newSpeed
);
/// @notice Emitted when COMP is distributed to a supplier
event DistributedSupplierComp(
CToken indexed cToken,
address indexed supplier,
uint256 compDelta,
uint256 compSupplyIndex
);
/// @notice Emitted when COMP is distributed to a borrower
event DistributedBorrowerComp(
CToken indexed cToken,
address indexed borrower,
uint256 compDelta,
uint256 compBorrowIndex
);
/// @notice Emitted when borrow cap for a cToken is changed
event NewBorrowCap(CToken indexed cToken, uint256 newBorrowCap);
/// @notice Emitted when borrow cap guardian is changed
event NewBorrowCapGuardian(
address oldBorrowCapGuardian,
address newBorrowCapGuardian
);
/// @notice Emitted when COMP is granted by admin
event CompGranted(address recipient, uint256 amount);
/// @notice Emitted when COMP accrued for a user has been manually adjusted.
event CompAccruedAdjusted(
address indexed user,
uint256 oldCompAccrued,
uint256 newCompAccrued
);
/// @notice Emitted when COMP receivable for a user has been updated.
event CompReceivableUpdated(
address indexed user,
uint256 oldCompReceivable,
uint256 newCompReceivable
);
/// @notice The initial COMP index for a market
uint224 public constant compInitialIndex = 1e36;
// closeFactorMantissa must be strictly greater than this value
uint256 internal constant closeFactorMinMantissa = 0.05e18; // 0.05
// closeFactorMantissa must not exceed this value
uint256 internal constant closeFactorMaxMantissa = 0.9e18; // 0.9
// No collateralFactorMantissa may exceed this value
uint256 internal constant collateralFactorMaxMantissa = 0.9e18; // 0.9
address ORBITER = 0xe5ABf4fcE02fbb3b47b5704E198F947433BFaEEd;
constructor() {
admin = msg.sender;
}
/*** Assets You Are In ***/
/**
* @notice Returns the assets an account has entered
* @param account The address of the account to pull assets for
* @return A dynamic list with the assets the account has entered
*/
function getAssetsIn(address account)
external
view
returns (CToken[] memory)
{
CToken[] memory assetsIn = accountAssets[account];
return assetsIn;
}
/**
* @notice Returns whether the given account is entered in the given asset
* @param account The address of the account to check
* @param cToken The cToken to check
* @return True if the account is in the asset, otherwise false.
*/
function checkMembership(address account, CToken cToken)
external
view
returns (bool)
{
return markets[address(cToken)].accountMembership[account];
}
/**
* @notice Add assets to be included in account liquidity calculation
* @param cTokens The list of addresses of the cToken markets to be enabled
* @return Success indicator for whether each corresponding market was entered
*/
function enterMarkets(address[] memory cTokens)
public
override
returns (uint256[] memory)
{
uint256 len = cTokens.length;
uint256[] memory results = new uint256[](len);
for (uint256 i = 0; i < len; i++) {
CToken cToken = CToken(cTokens[i]);
results[i] = uint256(addToMarketInternal(cToken, msg.sender));
}
return results;
}
/**
* @notice Add the market to the borrower's "assets in" for liquidity calculations
* @param cToken The market to enter
* @param borrower The address of the account to modify
* @return Success indicator for whether the market was entered
*/
function addToMarketInternal(CToken cToken, address borrower)
internal
returns (Error)
{
Market storage marketToJoin = markets[address(cToken)];
if (!marketToJoin.isListed) {
// market is not listed, cannot join
return Error.MARKET_NOT_LISTED;
}
if (marketToJoin.accountMembership[borrower] == true) {
// already joined
return Error.NO_ERROR;
}
// survived the gauntlet, add to list
// NOTE: we store these somewhat redundantly as a significant optimization
// this avoids having to iterate through the list for the most common use cases
// that is, only when we need to perform liquidity checks
// and not whenever we want to check if an account is in a particular market
marketToJoin.accountMembership[borrower] = true;
accountAssets[borrower].push(cToken);
emit MarketEntered(cToken, borrower);
return Error.NO_ERROR;
}
/**
* @notice Removes asset from sender's account liquidity calculation
* @dev Sender must not have an outstanding borrow balance in the asset,
* or be providing necessary collateral for an outstanding borrow.
* @param cTokenAddress The address of the asset to be removed
* @return Whether or not the account successfully exited the market
*/
function exitMarket(address cTokenAddress)
external
override
returns (uint256)
{
CToken cToken = CToken(cTokenAddress);
/* Get sender tokensHeld and amountOwed underlying from the cToken */
(uint256 oErr, uint256 tokensHeld, uint256 amountOwed, ) = cToken
.getAccountSnapshot(msg.sender);
require(oErr == 0, "exitMarket: getAccountSnapshot failed"); // semi-opaque error code
/* Fail if the sender has a borrow balance */
if (amountOwed != 0) {
return
fail(
Error.NONZERO_BORROW_BALANCE,
FailureInfo.EXIT_MARKET_BALANCE_OWED
);
}
/* Fail if the sender is not permitted to redeem all of their tokens */
uint256 allowed = redeemAllowedInternal(
cTokenAddress,
msg.sender,
tokensHeld
);
if (allowed != 0) {
return
failOpaque(
Error.REJECTION,
FailureInfo.EXIT_MARKET_REJECTION,
allowed
);
}
Market storage marketToExit = markets[address(cToken)];
/* Return true if the sender is not already ‘in’ the market */
if (!marketToExit.accountMembership[msg.sender]) {
return uint256(Error.NO_ERROR);
}
/* Set cToken account membership to false */
delete marketToExit.accountMembership[msg.sender];
/* Delete cToken from the account’s list of assets */
// load into memory for faster iteration
CToken[] memory userAssetList = accountAssets[msg.sender];
uint256 len = userAssetList.length;
uint256 assetIndex = len;
for (uint256 i = 0; i < len; i++) {
if (userAssetList[i] == cToken) {
assetIndex = i;
break;
}
}
// We *must* have found the asset in the list or our redundant data structure is broken
assert(assetIndex < len);
// copy last item in list to location of item to be removed, reduce length by 1
CToken[] storage storedList = accountAssets[msg.sender];
storedList[assetIndex] = storedList[storedList.length - 1];
storedList.pop();
emit MarketExited(cToken, msg.sender);
return uint256(Error.NO_ERROR);
}
/*** Policy Hooks ***/
/**
* @notice Checks if the account should be allowed to mint tokens in the given market
* @param cToken The market to verify the mint against
* @param minter The account which would get the minted tokens
* @param mintAmount The amount of underlying being supplied to the market in exchange for tokens
* @return 0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)
*/
function mintAllowed(
address cToken,
address minter,
uint256 mintAmount
) external override returns (uint256) {
// Pausing is a very serious situation - we revert to sound the alarms
require(!mintGuardianPaused[cToken], "mint is paused");
// Shh - currently unused
minter;
mintAmount;
if (!markets[cToken].isListed) {
return uint256(Error.MARKET_NOT_LISTED);
}
// Keep the flywheel moving
updateCompSupplyIndex(cToken);
distributeSupplierComp(cToken, minter);
if (address(incentive) != address(0)) {
incentive.distributeSupplier(cToken, minter);
}
return uint256(Error.NO_ERROR);
}
/**
* @notice Validates mint and reverts on rejection. May emit logs.
* @param cToken Asset being minted
* @param minter The address minting the tokens
* @param actualMintAmount The amount of the underlying asset being minted
* @param mintTokens The number of tokens being minted
*/
function mintVerify(
address cToken,
address minter,
uint256 actualMintAmount,
uint256 mintTokens
) external override {
// Shh - currently unused
cToken;
minter;
actualMintAmount;
mintTokens;
// Shh - we don't ever want this hook to be marked pure
if (false) {
maxAssets = maxAssets;
}
}
/**
* @notice Checks if the account should be allowed to redeem tokens in the given market
* @param cToken The market to verify the redeem against
* @param redeemer The account which would redeem the tokens
* @param redeemTokens The number of cTokens to exchange for the underlying asset in the market
* @return 0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)
*/
function redeemAllowed(
address cToken,
address redeemer,
uint256 redeemTokens
) external override returns (uint256) {
uint256 allowed = redeemAllowedInternal(cToken, redeemer, redeemTokens);
if (allowed != uint256(Error.NO_ERROR)) {
return allowed;
}
// Keep the flywheel moving
updateCompSupplyIndex(cToken);
distributeSupplierComp(cToken, redeemer);
if (address(incentive) != address(0)) {
incentive.distributeSupplier(cToken, redeemer);
}
return uint256(Error.NO_ERROR);
}
function redeemAllowedInternal(
address cToken,
address redeemer,
uint256 redeemTokens
) internal view returns (uint256) {
if (!markets[cToken].isListed) {
return uint256(Error.MARKET_NOT_LISTED);
}
/* If the redeemer is not 'in' the market, then we can bypass the liquidity check */
if (!markets[cToken].accountMembership[redeemer]) {
return uint256(Error.NO_ERROR);
}
/* Otherwise, perform a hypothetical liquidity check to guard against shortfall */
(
Error err,
,
uint256 shortfall
) = getHypotheticalAccountLiquidityInternal(
redeemer,
CToken(cToken),
redeemTokens,
0
);
if (err != Error.NO_ERROR) {
return uint256(err);
}
if (shortfall > 0) {
return uint256(Error.INSUFFICIENT_LIQUIDITY);
}
return uint256(Error.NO_ERROR);
}
/**
* @notice Validates redeem and reverts on rejection. May emit logs.
* @param cToken Asset being redeemed
* @param redeemer The address redeeming the tokens
* @param redeemAmount The amount of the underlying asset being redeemed
* @param redeemTokens The number of tokens being redeemed
*/
function redeemVerify(
address cToken,
address redeemer,
uint256 redeemAmount,
uint256 redeemTokens
) external override {
// Shh - currently unused
cToken;
redeemer;
// Require tokens is zero or amount is also zero
if (redeemTokens == 0 && redeemAmount > 0) {
revert("redeemTokens zero");
}
}
/**
* @notice Checks if the account should be allowed to borrow the underlying asset of the given market
* @param cToken The market to verify the borrow against
* @param borrower The account which would borrow the asset
* @param borrowAmount The amount of underlying the account would borrow
* @return 0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)
*/
function borrowAllowed(
address cToken,
address borrower,
uint256 borrowAmount
) external override returns (uint256) {
// Pausing is a very serious situation - we revert to sound the alarms
require(!borrowGuardianPaused[cToken], "borrow is paused");
if (!markets[cToken].isListed) {
return uint256(Error.MARKET_NOT_LISTED);
}
if (!markets[cToken].accountMembership[borrower]) {
// only cTokens may call borrowAllowed if borrower not in market
require(msg.sender == cToken, "sender must be cToken");
// attempt to add borrower to the market
Error err = addToMarketInternal(CToken(msg.sender), borrower);
if (err != Error.NO_ERROR) {
return uint256(err);
}
// it should be impossible to break the important invariant
assert(markets[cToken].accountMembership[borrower]);
}
if (oracle.getUnderlyingPrice(CToken(cToken)) == 0) {
return uint256(Error.PRICE_ERROR);
}
uint256 borrowCap = borrowCaps[cToken];
// Borrow cap of 0 corresponds to unlimited borrowing
if (borrowCap != 0) {
uint256 totalBorrows = CToken(cToken).totalBorrows();
uint256 nextTotalBorrows = add_(totalBorrows, borrowAmount);
require(nextTotalBorrows < borrowCap, "market borrow cap reached");
}
(
Error err,
,
uint256 shortfall
) = getHypotheticalAccountLiquidityInternal(
borrower,
CToken(cToken),
0,
borrowAmount
);
if (err != Error.NO_ERROR) {
return uint256(err);
}
if (shortfall > 0) {
return uint256(Error.INSUFFICIENT_LIQUIDITY);
}
// Keep the flywheel moving
Exp memory borrowIndex = Exp({mantissa: CToken(cToken).borrowIndex()});
updateCompBorrowIndex(cToken, borrowIndex);
distributeBorrowerComp(cToken, borrower, borrowIndex);
if (address(incentive) != address(0)) {
incentive.distributeBorrower(cToken, borrower);
}
return uint256(Error.NO_ERROR);
}
/**
* @notice Validates borrow and reverts on rejection. May emit logs.
* @param cToken Asset whose underlying is being borrowed
* @param borrower The address borrowing the underlying
* @param borrowAmount The amount of the underlying asset requested to borrow
*/
function borrowVerify(
address cToken,
address borrower,
uint256 borrowAmount
) external override {
// Shh - currently unused
cToken;
borrower;
borrowAmount;
// Shh - we don't ever want this hook to be marked pure
if (false) {
maxAssets = maxAssets;
}
}
/**
* @notice Checks if the account should be allowed to repay a borrow in the given market
* @param cToken The market to verify the repay against
* @param payer The account which would repay the asset
* @param borrower The account which would borrowed the asset
* @param repayAmount The amount of the underlying asset the account would repay
* @return 0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)
*/
function repayBorrowAllowed(
address cToken,
address payer,
address borrower,
uint256 repayAmount
) external override returns (uint256) {
// Shh - currently unused
payer;
borrower;
repayAmount;
if (!markets[cToken].isListed) {
return uint256(Error.MARKET_NOT_LISTED);
}
// Keep the flywheel moving
Exp memory borrowIndex = Exp({mantissa: CToken(cToken).borrowIndex()});
updateCompBorrowIndex(cToken, borrowIndex);
distributeBorrowerComp(cToken, borrower, borrowIndex);
if (address(incentive) != address(0)) {
incentive.distributeBorrower(cToken, borrower);
}
return uint256(Error.NO_ERROR);
}
/**
* @notice Validates repayBorrow and reverts on rejection. May emit logs.
* @param cToken Asset being repaid
* @param payer The address repaying the borrow
* @param borrower The address of the borrower
* @param actualRepayAmount The amount of underlying being repaid
*/
function repayBorrowVerify(
address cToken,
address payer,
address borrower,
uint256 actualRepayAmount,
uint256 borrowerIndex
) external override {
// Shh - currently unused
cToken;
payer;
borrower;
actualRepayAmount;
borrowerIndex;
// Shh - we don't ever want this hook to be marked pure
if (false) {
maxAssets = maxAssets;
}
}
/**
* @notice Checks if the liquidation should be allowed to occur
* @param cTokenBorrowed Asset which was borrowed by the borrower
* @param cTokenCollateral Asset which was used as collateral and will be seized
* @param liquidator The address repaying the borrow and seizing the collateral
* @param borrower The address of the borrower
* @param repayAmount The amount of underlying being repaid
*/
function liquidateBorrowAllowed(
address cTokenBorrowed,
address cTokenCollateral,
address liquidator,
address borrower,
uint256 repayAmount
) external override returns (uint256) {
// Shh - currently unused
liquidator;
if (
!markets[cTokenBorrowed].isListed ||
!markets[cTokenCollateral].isListed
) {
return uint256(Error.MARKET_NOT_LISTED);
}
uint256 borrowBalance = CToken(cTokenBorrowed).borrowBalanceStored(
borrower
);
/* allow accounts to be liquidated if the market is deprecated */
if (isDeprecated(CToken(cTokenBorrowed))) {
require(
borrowBalance >= repayAmount,
"Can not repay more than the total borrow"
);
} else {
/* The borrower must have shortfall in order to be liquidatable */
(Error err, , uint256 shortfall) = getAccountLiquidityInternal(
borrower
);
if (err != Error.NO_ERROR) {
return uint256(err);
}
if (shortfall == 0) {
return uint256(Error.INSUFFICIENT_SHORTFALL);
}
/* The liquidator may not repay more than what is allowed by the closeFactor */
uint256 maxClose = mul_ScalarTruncate(
Exp({mantissa: closeFactorMantissa}),
borrowBalance
);
if (repayAmount > maxClose) {
return uint256(Error.TOO_MUCH_REPAY);
}
}
return uint256(Error.NO_ERROR);
}
/**
* @notice Validates liquidateBorrow and reverts on rejection. May emit logs.
* @param cTokenBorrowed Asset which was borrowed by the borrower
* @param cTokenCollateral Asset which was used as collateral and will be seized
* @param liquidator The address repaying the borrow and seizing the collateral
* @param borrower The address of the borrower
* @param actualRepayAmount The amount of underlying being repaid
*/
function liquidateBorrowVerify(
address cTokenBorrowed,
address cTokenCollateral,
address liquidator,
address borrower,
uint256 actualRepayAmount,
uint256 seizeTokens
) external override {
// Shh - currently unused
cTokenBorrowed;
cTokenCollateral;
liquidator;
borrower;
actualRepayAmount;
seizeTokens;
// Shh - we don't ever want this hook to be marked pure
if (false) {
maxAssets = maxAssets;
}
}
/**
* @notice Checks if the seizing of assets should be allowed to occur
* @param cTokenCollateral Asset which was used as collateral and will be seized
* @param cTokenBorrowed Asset which was borrowed by the borrower
* @param liquidator The address repaying the borrow and seizing the collateral
* @param borrower The address of the borrower
* @param seizeTokens The number of collateral tokens to seize
*/
function seizeAllowed(
address cTokenCollateral,
address cTokenBorrowed,
address liquidator,
address borrower,
uint256 seizeTokens
) external override returns (uint256) {
// Pausing is a very serious situation - we revert to sound the alarms
require(!seizeGuardianPaused, "seize is paused");
// Shh - currently unused
seizeTokens;
if (
!markets[cTokenCollateral].isListed ||
!markets[cTokenBorrowed].isListed
) {
return uint256(Error.MARKET_NOT_LISTED);
}
if (
CToken(cTokenCollateral).comptroller() !=
CToken(cTokenBorrowed).comptroller()
) {
return uint256(Error.COMPTROLLER_MISMATCH);
}
// Keep the flywheel moving
updateCompSupplyIndex(cTokenCollateral);
distributeSupplierComp(cTokenCollateral, borrower);
distributeSupplierComp(cTokenCollateral, liquidator);
if (address(incentive) != address(0)) {
incentive.distributeSupplier(cTokenCollateral, borrower);
incentive.distributeSupplier(cTokenCollateral, liquidator);
}
return uint256(Error.NO_ERROR);
}
/**
* @notice Validates seize and reverts on rejection. May emit logs.
* @param cTokenCollateral Asset which was used as collateral and will be seized
* @param cTokenBorrowed Asset which was borrowed by the borrower
* @param liquidator The address repaying the borrow and seizing the collateral
* @param borrower The address of the borrower
* @param seizeTokens The number of collateral tokens to seize
*/
function seizeVerify(
address cTokenCollateral,
address cTokenBorrowed,
address liquidator,
address borrower,
uint256 seizeTokens
) external override {
// Shh - currently unused
cTokenCollateral;
cTokenBorrowed;
liquidator;
borrower;
seizeTokens;
// Shh - we don't ever want this hook to be marked pure
if (false) {
maxAssets = maxAssets;
}
}
/**
* @notice Checks if the account should be allowed to transfer tokens in the given market
* @param cToken The market to verify the transfer against
* @param src The account which sources the tokens
* @param dst The account which receives the tokens
* @param transferTokens The number of cTokens to transfer
* @return 0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)
*/
function transferAllowed(
address cToken,
address src,
address dst,
uint256 transferTokens
) external override returns (uint256) {
// Pausing is a very serious situation - we revert to sound the alarms
require(!transferGuardianPaused, "transfer is paused");
// Currently the only consideration is whether or not
// the src is allowed to redeem this many tokens
uint256 allowed = redeemAllowedInternal(cToken, src, transferTokens);
if (allowed != uint256(Error.NO_ERROR)) {
return allowed;
}
// Keep the flywheel moving
updateCompSupplyIndex(cToken);
distributeSupplierComp(cToken, src);
distributeSupplierComp(cToken, dst);
if (address(incentive) != address(0)) {
incentive.distributeSupplier(cToken, src);
incentive.distributeSupplier(cToken, dst);
}
return uint256(Error.NO_ERROR);
}
/**
* @notice Validates transfer and reverts on rejection. May emit logs.
* @param cToken Asset being transferred
* @param src The account which sources the tokens
* @param dst The account which receives the tokens
* @param transferTokens The number of cTokens to transfer
*/
function transferVerify(
address cToken,
address src,
address dst,
uint256 transferTokens
) external override {
// Shh - currently unused
cToken;
src;
dst;
transferTokens;
// Shh - we don't ever want this hook to be marked pure
if (false) {
maxAssets = maxAssets;
}
}
/*** Liquidity/Liquidation Calculations ***/
/**
* @dev Local vars for avoiding stack-depth limits in calculating account liquidity.
* Note that `cTokenBalance` is the number of cTokens the account owns in the market,
* whereas `borrowBalance` is the amount of underlying that the account has borrowed.
*/
struct AccountLiquidityLocalVars {
uint256 sumCollateral;
uint256 sumBorrowPlusEffects;
uint256 cTokenBalance;
uint256 borrowBalance;
uint256 exchangeRateMantissa;
uint256 oraclePriceMantissa;
Exp collateralFactor;
Exp exchangeRate;
Exp oraclePrice;
Exp tokensToDenom;
}
/**
* @notice Determine the current account liquidity wrt collateral requirements
* @return (possible error code (semi-opaque),
account liquidity in excess of collateral requirements,
* account shortfall below collateral requirements)
*/
function getAccountLiquidity(address account)
public
view
returns (
uint256,
uint256,
uint256
)
{
(
Error err,
uint256 liquidity,
uint256 shortfall
) = getHypotheticalAccountLiquidityInternal(
account,
CToken(address(0)),
0,
0
);
return (uint256(err), liquidity, shortfall);
}
/**
* @notice Determine the current account liquidity wrt collateral requirements
* @return (possible error code,
account liquidity in excess of collateral requirements,
* account shortfall below collateral requirements)
*/
function getAccountLiquidityInternal(address account)
internal
view
returns (
Error,
uint256,
uint256
)
{
return
getHypotheticalAccountLiquidityInternal(
account,
CToken(address(0)),
0,
0
);
}
/**
* @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed
* @param cTokenModify The market to hypothetically redeem/borrow in
* @param account The account to determine liquidity for
* @param redeemTokens The number of tokens to hypothetically redeem
* @param borrowAmount The amount of underlying to hypothetically borrow
* @return (possible error code (semi-opaque),
hypothetical account liquidity in excess of collateral requirements,
* hypothetical account shortfall below collateral requirements)
*/
function getHypotheticalAccountLiquidity(
address account,
address cTokenModify,
uint256 redeemTokens,
uint256 borrowAmount
)
public
view
returns (
uint256,
uint256,
uint256
)
{
(
Error err,
uint256 liquidity,
uint256 shortfall
) = getHypotheticalAccountLiquidityInternal(
account,
CToken(cTokenModify),
redeemTokens,
borrowAmount
);
return (uint256(err), liquidity, shortfall);
}
/**
* @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed
* @param cTokenModify The market to hypothetically redeem/borrow in
* @param account The account to determine liquidity for
* @param redeemTokens The number of tokens to hypothetically redeem
* @param borrowAmount The amount of underlying to hypothetically borrow
* @dev Note that we calculate the exchangeRateStored for each collateral cToken using stored data,
* without calculating accumulated interest.
* @return (possible error code,
hypothetical account liquidity in excess of collateral requirements,
* hypothetical account shortfall below collateral requirements)
*/
function getHypotheticalAccountLiquidityInternal(
address account,
CToken cTokenModify,
uint256 redeemTokens,
uint256 borrowAmount
)
internal
view
returns (
Error,
uint256,
uint256
)
{
AccountLiquidityLocalVars memory vars; // Holds all our calculation results
uint256 oErr;
// For each asset the account is in
CToken[] memory assets = accountAssets[account];
for (uint256 i = 0; i < assets.length; i++) {
CToken asset = assets[i];
// Read the balances and exchange rate from the cToken
(
oErr,
vars.cTokenBalance,
vars.borrowBalance,
vars.exchangeRateMantissa
) = asset.getAccountSnapshot(account);
if (oErr != 0) {
// semi-opaque error code, we assume NO_ERROR == 0 is invariant between upgrades
return (Error.SNAPSHOT_ERROR, 0, 0);
}
vars.collateralFactor = Exp({
mantissa: markets[address(asset)].collateralFactorMantissa
});
vars.exchangeRate = Exp({mantissa: vars.exchangeRateMantissa});
// Get the normalized price of the asset
vars.oraclePriceMantissa = oracle.getUnderlyingPrice(asset);
if (vars.oraclePriceMantissa == 0) {
return (Error.PRICE_ERROR, 0, 0);
}
vars.oraclePrice = Exp({mantissa: vars.oraclePriceMantissa});
// Pre-compute a conversion factor from tokens -> ether (normalized price value)
vars.tokensToDenom = mul_(
mul_(vars.collateralFactor, vars.exchangeRate),
vars.oraclePrice
);
// sumCollateral += tokensToDenom * cTokenBalance
vars.sumCollateral = mul_ScalarTruncateAddUInt(
vars.tokensToDenom,
vars.cTokenBalance,
vars.sumCollateral
);
// sumBorrowPlusEffects += oraclePrice * borrowBalance
vars.sumBorrowPlusEffects = mul_ScalarTruncateAddUInt(
vars.oraclePrice,
vars.borrowBalance,
vars.sumBorrowPlusEffects
);
// Calculate effects of interacting with cTokenModify
if (asset == cTokenModify) {
// redeem effect
// sumBorrowPlusEffects += tokensToDenom * redeemTokens
vars.sumBorrowPlusEffects = mul_ScalarTruncateAddUInt(
vars.tokensToDenom,
redeemTokens,
vars.sumBorrowPlusEffects
);
// borrow effect
// sumBorrowPlusEffects += oraclePrice * borrowAmount
vars.sumBorrowPlusEffects = mul_ScalarTruncateAddUInt(
vars.oraclePrice,
borrowAmount,
vars.sumBorrowPlusEffects
);
}
}
// These are safe, as the underflow condition is checked first
if (vars.sumCollateral > vars.sumBorrowPlusEffects) {
return (
Error.NO_ERROR,
vars.sumCollateral - vars.sumBorrowPlusEffects,
0
);
} else {
return (
Error.NO_ERROR,
0,
vars.sumBorrowPlusEffects - vars.sumCollateral
);
}
}
/**
* @notice Calculate number of tokens of collateral asset to seize given an underlying amount
* @dev Used in liquidation (called in cToken.liquidateBorrowFresh)
* @param cTokenBorrowed The address of the borrowed cToken
* @param cTokenCollateral The address of the collateral cToken
* @param actualRepayAmount The amount of cTokenBorrowed underlying to convert into cTokenCollateral tokens
* @return (errorCode, number of cTokenCollateral tokens to be seized in a liquidation)
*/
function liquidateCalculateSeizeTokens(
address cTokenBorrowed,
address cTokenCollateral,
uint256 actualRepayAmount
) external view override returns (uint256, uint256) {
/* Read oracle prices for borrowed and collateral markets */
uint256 priceBorrowedMantissa = oracle.getUnderlyingPrice(
CToken(cTokenBorrowed)
);
uint256 priceCollateralMantissa = oracle.getUnderlyingPrice(
CToken(cTokenCollateral)
);
if (priceBorrowedMantissa == 0 || priceCollateralMantissa == 0) {
return (uint256(Error.PRICE_ERROR), 0);
}
/*
* Get the exchange rate and calculate the number of collateral tokens to seize:
* seizeAmount = actualRepayAmount * liquidationIncentive * priceBorrowed / priceCollateral
* seizeTokens = seizeAmount / exchangeRate
* = actualRepayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate)
*/
uint256 exchangeRateMantissa = CToken(cTokenCollateral)
.exchangeRateStored(); // Note: reverts on error
uint256 seizeTokens;
Exp memory numerator;
Exp memory denominator;
Exp memory ratio;
numerator = mul_(
Exp({mantissa: liquidationIncentiveMantissa}),
Exp({mantissa: priceBorrowedMantissa})
);
denominator = mul_(
Exp({mantissa: priceCollateralMantissa}),
Exp({mantissa: exchangeRateMantissa})
);
ratio = div_(numerator, denominator);
seizeTokens = mul_ScalarTruncate(ratio, actualRepayAmount);
return (uint256(Error.NO_ERROR), seizeTokens);
}
/*** Admin Functions ***/
/**
* @notice Sets a new price oracle for the comptroller
* @dev Admin function to set a new price oracle
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/
function _setPriceOracle(PriceOracle newOracle) public returns (uint256) {
// Check caller is admin
if (msg.sender != admin) {
return
fail(
Error.UNAUTHORIZED,
FailureInfo.SET_PRICE_ORACLE_OWNER_CHECK
);
}
// Track the old oracle for the comptroller
PriceOracle oldOracle = oracle;
// Set comptroller's oracle to newOracle
oracle = newOracle;
// Emit NewPriceOracle(oldOracle, newOracle)
emit NewPriceOracle(oldOracle, newOracle);
return uint256(Error.NO_ERROR);
}
/**
* @notice Sets a new incentive for the comptroller
* @dev Admin function to set a new incentive
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/
function _setIncentive(IncentiveInterface newIncentive)
public
returns (uint256)
{
// Check caller is admin
if (msg.sender != admin) {
return
fail(Error.UNAUTHORIZED, FailureInfo.SET_INCENTIVE_OWNER_CHECK);
}
// Track the old incentive for the comptroller
IncentiveInterface oldIncentive = incentive;
// Set comptroller's incentive to newIncentive
incentive = newIncentive;
// Emit NewIncentive(oldIncentive, newIncentive)
emit NewIncentive(oldIncentive, newIncentive);
return uint256(Error.NO_ERROR);
}
/**
* @notice Sets the closeFactor used when liquidating borrows
* @dev Admin function to set closeFactor
* @param newCloseFactorMantissa New close factor, scaled by 1e18
* @return uint 0=success, otherwise a failure
*/
function _setCloseFactor(uint256 newCloseFactorMantissa)
external
returns (uint256)
{
// Check caller is admin
require(msg.sender == admin, "only admin can set close factor");
uint256 oldCloseFactorMantissa = closeFactorMantissa;
closeFactorMantissa = newCloseFactorMantissa;
emit NewCloseFactor(oldCloseFactorMantissa, closeFactorMantissa);
return uint256(Error.NO_ERROR);
}
/**
* @notice Sets the collateralFactor for a market
* @dev Admin function to set per-market collateralFactor
* @param cToken The market to set the factor on
* @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18
* @return uint 0=success, otherwise a failure. (See ErrorReporter for details)
*/
function _setCollateralFactor(
CToken cToken,
uint256 newCollateralFactorMantissa
) external returns (uint256) {
// Check caller is admin
if (msg.sender != admin) {
return
fail(
Error.UNAUTHORIZED,
FailureInfo.SET_COLLATERAL_FACTOR_OWNER_CHECK
);
}
// Verify market is listed
Market storage market = markets[address(cToken)];
if (!market.isListed) {
return
fail(
Error.MARKET_NOT_LISTED,
FailureInfo.SET_COLLATERAL_FACTOR_NO_EXISTS
);
}
Exp memory newCollateralFactorExp = Exp({
mantissa: newCollateralFactorMantissa
});
// Check collateral factor <= 0.9
Exp memory highLimit = Exp({mantissa: collateralFactorMaxMantissa});
if (lessThanExp(highLimit, newCollateralFactorExp)) {
return
fail(
Error.INVALID_COLLATERAL_FACTOR,
FailureInfo.SET_COLLATERAL_FACTOR_VALIDATION
);
}
// If collateral factor != 0, fail if price == 0
if (
newCollateralFactorMantissa != 0 &&
oracle.getUnderlyingPrice(cToken) == 0
) {
return
fail(
Error.PRICE_ERROR,
FailureInfo.SET_COLLATERAL_FACTOR_WITHOUT_PRICE
);
}
// Set market's collateral factor to new collateral factor, remember old value
uint256 oldCollateralFactorMantissa = market.collateralFactorMantissa;
market.collateralFactorMantissa = newCollateralFactorMantissa;
// Emit event with asset, old collateral factor, and new collateral factor
emit NewCollateralFactor(
cToken,
oldCollateralFactorMantissa,
newCollateralFactorMantissa
);
return uint256(Error.NO_ERROR);
}
/**
* @notice Sets liquidationIncentive
* @dev Admin function to set liquidationIncentive
* @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18
* @return uint 0=success, otherwise a failure. (See ErrorReporter for details)
*/
function _setLiquidationIncentive(uint256 newLiquidationIncentiveMantissa)
external
returns (uint256)
{
// Check caller is admin
if (msg.sender != admin) {
return
fail(
Error.UNAUTHORIZED,
FailureInfo.SET_LIQUIDATION_INCENTIVE_OWNER_CHECK
);
}
// Save current value for use in log
uint256 oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa;
// Set liquidation incentive to new incentive
liquidationIncentiveMantissa = newLiquidationIncentiveMantissa;
// Emit event with old incentive, new incentive
emit NewLiquidationIncentive(
oldLiquidationIncentiveMantissa,
newLiquidationIncentiveMantissa
);
return uint256(Error.NO_ERROR);
}
/**
* @notice Add the market to the markets mapping and set it as listed
* @dev Admin function to set isListed and add support for the market
* @param cToken The address of the market (token) to list
* @return uint 0=success, otherwise a failure. (See enum Error for details)
*/
function _supportMarket(CToken cToken) external returns (uint256) {
if (msg.sender != admin) {
return
fail(
Error.UNAUTHORIZED,
FailureInfo.SUPPORT_MARKET_OWNER_CHECK
);
}
if (markets[address(cToken)].isListed) {
return
fail(
Error.MARKET_ALREADY_LISTED,
FailureInfo.SUPPORT_MARKET_EXISTS
);
}
cToken.isCToken(); // Sanity check to make sure its really a CToken
// Note that isComped is not in active use anymore
Market storage newMarket = markets[address(cToken)];
newMarket.isListed = true;
newMarket.isComped = false;
newMarket.collateralFactorMantissa = 0;
_addMarketInternal(address(cToken));
_initializeMarket(address(cToken));
emit MarketListed(cToken);
return uint256(Error.NO_ERROR);
}
function _addMarketInternal(address cToken) internal {
for (uint256 i = 0; i < allMarkets.length; i++) {
require(allMarkets[i] != CToken(cToken), "market already added");
}
allMarkets.push(CToken(cToken));
}
function _initializeMarket(address cToken) internal {
uint32 blockNumber = safe32(
getBlockNumber(),
"block number exceeds 32 bits"
);
CompMarketState storage supplyState = compSupplyState[cToken];
CompMarketState storage borrowState = compBorrowState[cToken];
/*
* Update market state indices
*/
if (supplyState.index == 0) {
// Initialize supply state index with default value
supplyState.index = compInitialIndex;
}
if (borrowState.index == 0) {
// Initialize borrow state index with default value
borrowState.index = compInitialIndex;
}
/*
* Update market state block numbers
*/
supplyState.block = borrowState.block = blockNumber;
}
/**
* @notice Set the given borrow caps for the given cToken markets. Borrowing that brings total borrows to or above borrow cap will revert.
* @dev Admin or borrowCapGuardian function to set the borrow caps. A borrow cap of 0 corresponds to unlimited borrowing.
* @param cTokens The addresses of the markets (tokens) to change the borrow caps for
* @param newBorrowCaps The new borrow cap values in underlying to be set. A value of 0 corresponds to unlimited borrowing.
*/
function _setMarketBorrowCaps(
CToken[] calldata cTokens,
uint256[] calldata newBorrowCaps
) external {
require(
msg.sender == admin || msg.sender == borrowCapGuardian,
"only admin or borrow cap guardian can set borrow caps"
);
uint256 numMarkets = cTokens.length;
uint256 numBorrowCaps = newBorrowCaps.length;
require(
numMarkets != 0 && numMarkets == numBorrowCaps,
"invalid input"
);
for (uint256 i = 0; i < numMarkets; i++) {
borrowCaps[address(cTokens[i])] = newBorrowCaps[i];
emit NewBorrowCap(cTokens[i], newBorrowCaps[i]);
}
}
/**
* @notice Admin function to change the Borrow Cap Guardian
* @param newBorrowCapGuardian The address of the new Borrow Cap Guardian
*/
function _setBorrowCapGuardian(address newBorrowCapGuardian) external {
require(msg.sender == admin, "only admin can set borrow cap guardian");
// Save current value for inclusion in log
address oldBorrowCapGuardian = borrowCapGuardian;
// Store borrowCapGuardian with value newBorrowCapGuardian
borrowCapGuardian = newBorrowCapGuardian;
// Emit NewBorrowCapGuardian(OldBorrowCapGuardian, NewBorrowCapGuardian)
emit NewBorrowCapGuardian(oldBorrowCapGuardian, newBorrowCapGuardian);
}
/**
* @notice Admin function to change the Pause Guardian
* @param newPauseGuardian The address of the new Pause Guardian
* @return uint 0=success, otherwise a failure. (See enum Error for details)
*/
function _setPauseGuardian(address newPauseGuardian)
public
returns (uint256)
{
if (msg.sender != admin) {
return
fail(
Error.UNAUTHORIZED,
FailureInfo.SET_PAUSE_GUARDIAN_OWNER_CHECK
);
}
// Save current value for inclusion in log
address oldPauseGuardian = pauseGuardian;
// Store pauseGuardian with value newPauseGuardian
pauseGuardian = newPauseGuardian;
// Emit NewPauseGuardian(OldPauseGuardian, NewPauseGuardian)
emit NewPauseGuardian(oldPauseGuardian, pauseGuardian);
return uint256(Error.NO_ERROR);
}
function _setMintPaused(CToken cToken, bool state) public returns (bool) {
require(
markets[address(cToken)].isListed,
"cannot pause a market that is not listed"
);
require(
msg.sender == pauseGuardian || msg.sender == admin,
"only pause guardian and admin can pause"
);
require(msg.sender == admin || state == true, "only admin can unpause");
mintGuardianPaused[address(cToken)] = state;
emit ActionPaused(cToken, "Mint", state);
return state;
}
function _setBorrowPaused(CToken cToken, bool state) public returns (bool) {
require(
markets[address(cToken)].isListed,
"cannot pause a market that is not listed"
);
require(
msg.sender == pauseGuardian || msg.sender == admin,
"only pause guardian and admin can pause"
);
require(msg.sender == admin || state == true, "only admin can unpause");
borrowGuardianPaused[address(cToken)] = state;
emit ActionPaused(cToken, "Borrow", state);
return state;
}
function _setTransferPaused(bool state) public returns (bool) {
require(
msg.sender == pauseGuardian || msg.sender == admin,
"only pause guardian and admin can pause"
);
require(msg.sender == admin || state == true, "only admin can unpause");
transferGuardianPaused = state;
emit ActionPaused("Transfer", state);
return state;
}
function _setSeizePaused(bool state) public returns (bool) {
require(
msg.sender == pauseGuardian || msg.sender == admin,
"only pause guardian and admin can pause"
);
require(msg.sender == admin || state == true, "only admin can unpause");
seizeGuardianPaused = state;
emit ActionPaused("Seize", state);
return state;
}
function _become(Unitroller unitroller) public {
require(
msg.sender == unitroller.admin(),
"only unitroller admin can change brains"
);
require(
unitroller._acceptImplementation() == 0,
"change not authorized"
);
}
/// @notice Delete this function after proposal 65 is executed
function fixBadAccruals(
address[] calldata affectedUsers,
uint256[] calldata amounts
) external {
require(msg.sender == admin, "Only admin can call this function"); // Only the timelock can call this function
require(
!proposal65FixExecuted,
"Already executed this one-off function"
); // Require that this function is only called once
require(affectedUsers.length == amounts.length, "Invalid input");
// Loop variables
address user;
uint256 currentAccrual;
uint256 amountToSubtract;
uint256 newAccrual;
// Iterate through all affected users
for (uint256 i = 0; i < affectedUsers.length; ++i) {
user = affectedUsers[i];
currentAccrual = compAccrued[user];
amountToSubtract = amounts[i];
// The case where the user has claimed and received an incorrect amount of COMP.
// The user has less currently accrued than the amount they incorrectly received.
if (amountToSubtract > currentAccrual) {
// Amount of COMP the user owes the protocol
uint256 accountReceivable = amountToSubtract - currentAccrual; // Underflow safe since amountToSubtract > currentAccrual
uint256 oldReceivable = compReceivable[user];
uint256 newReceivable = add_(oldReceivable, accountReceivable);
// Accounting: record the COMP debt for the user
compReceivable[user] = newReceivable;
emit CompReceivableUpdated(user, oldReceivable, newReceivable);
amountToSubtract = currentAccrual;
}
if (amountToSubtract > 0) {
// Subtract the bad accrual amount from what they have accrued.
// Users will keep whatever they have correctly accrued.
compAccrued[user] = newAccrual = sub_(
currentAccrual,
amountToSubtract
);
emit CompAccruedAdjusted(user, currentAccrual, newAccrual);
}
}
proposal65FixExecuted = true; // Makes it so that this function cannot be called again
}
/**
* @notice Checks caller is admin, or this contract is becoming the new implementation
*/
function adminOrInitializing() internal view returns (bool) {
return msg.sender == admin || msg.sender == comptrollerImplementation;
}
/*** Comp Distribution ***/
/**
* @notice Set COMP speed for a single market
* @param cToken The market whose COMP speed to update
* @param supplySpeed New supply-side COMP speed for market
* @param borrowSpeed New borrow-side COMP speed for market
*/
function setCompSpeedInternal(
CToken cToken,
uint256 supplySpeed,
uint256 borrowSpeed
) internal {
Market storage market = markets[address(cToken)];
require(market.isListed, "comp market is not listed");
if (compSupplySpeeds[address(cToken)] != supplySpeed) {
// Supply speed updated so let's update supply state to ensure that
// 1. COMP accrued properly for the old speed, and
// 2. COMP accrued at the new speed starts after this block.
updateCompSupplyIndex(address(cToken));
// Update speed and emit event
compSupplySpeeds[address(cToken)] = supplySpeed;
emit CompSupplySpeedUpdated(cToken, supplySpeed);
}
if (compBorrowSpeeds[address(cToken)] != borrowSpeed) {
// Borrow speed updated so let's update borrow state to ensure that
// 1. COMP accrued properly for the old speed, and
// 2. COMP accrued at the new speed starts after this block.
Exp memory borrowIndex = Exp({mantissa: cToken.borrowIndex()});
updateCompBorrowIndex(address(cToken), borrowIndex);
// Update speed and emit event
compBorrowSpeeds[address(cToken)] = borrowSpeed;
emit CompBorrowSpeedUpdated(cToken, borrowSpeed);
}
}
/**
* @notice Accrue COMP to the market by updating the supply index
* @param cToken The market whose supply index to update
* @dev Index is a cumulative sum of the COMP per cToken accrued.
*/
function updateCompSupplyIndex(address cToken) internal {
CompMarketState storage supplyState = compSupplyState[cToken];
uint256 supplySpeed = compSupplySpeeds[cToken];
uint32 blockNumber = safe32(
getBlockNumber(),
"block number exceeds 32 bits"
);
uint256 deltaBlocks = sub_(
uint256(blockNumber),
uint256(supplyState.block)
);
if (deltaBlocks > 0 && supplySpeed > 0) {
uint256 supplyTokens = CToken(cToken).totalSupply();
uint256 compAccrued = mul_(deltaBlocks, supplySpeed);
Double memory ratio = supplyTokens > 0
? fraction(compAccrued, supplyTokens)
: Double({mantissa: 0});
supplyState.index = safe224(
add_(Double({mantissa: supplyState.index}), ratio).mantissa,
"new index exceeds 224 bits"
);
supplyState.block = blockNumber;
} else if (deltaBlocks > 0) {
supplyState.block = blockNumber;
}
}
/**
* @notice Accrue COMP to the market by updating the borrow index
* @param cToken The market whose borrow index to update
* @dev Index is a cumulative sum of the COMP per cToken accrued.
*/
function updateCompBorrowIndex(address cToken, Exp memory marketBorrowIndex)
internal
{
CompMarketState storage borrowState = compBorrowState[cToken];
uint256 borrowSpeed = compBorrowSpeeds[cToken];
uint32 blockNumber = safe32(
getBlockNumber(),
"block number exceeds 32 bits"
);
uint256 deltaBlocks = sub_(
uint256(blockNumber),
uint256(borrowState.block)
);
if (deltaBlocks > 0 && borrowSpeed > 0) {
uint256 borrowAmount = div_(
CToken(cToken).totalBorrows(),
marketBorrowIndex
);
uint256 compAccrued = mul_(deltaBlocks, borrowSpeed);
Double memory ratio = borrowAmount > 0
? fraction(compAccrued, borrowAmount)
: Double({mantissa: 0});
borrowState.index = safe224(
add_(Double({mantissa: borrowState.index}), ratio).mantissa,
"new index exceeds 224 bits"
);
borrowState.block = blockNumber;
} else if (deltaBlocks > 0) {
borrowState.block = blockNumber;
}
}
/**
* @notice Calculate COMP accrued by a supplier and possibly transfer it to them
* @param cToken The market in which the supplier is interacting
* @param supplier The address of the supplier to distribute COMP to
*/
function distributeSupplierComp(address cToken, address supplier) internal {
// TODO: Don't distribute supplier COMP if the user is not in the supplier market.
// This check should be as gas efficient as possible as distributeSupplierComp is called in many places.
// - We really don't want to call an external contract as that's quite expensive.
CompMarketState storage supplyState = compSupplyState[cToken];
uint256 supplyIndex = supplyState.index;
uint256 supplierIndex = compSupplierIndex[cToken][supplier];
// Update supplier's index to the current index since we are distributing accrued COMP
compSupplierIndex[cToken][supplier] = supplyIndex;
if (supplierIndex == 0 && supplyIndex >= compInitialIndex) {
// Covers the case where users supplied tokens before the market's supply state index was set.
// Rewards the user with COMP accrued from the start of when supplier rewards were first
// set for the market.
supplierIndex = compInitialIndex;
}
// Calculate change in the cumulative sum of the COMP per cToken accrued
Double memory deltaIndex = Double({
mantissa: sub_(supplyIndex, supplierIndex)
});
uint256 supplierTokens = CToken(cToken).balanceOf(supplier);
// Calculate COMP accrued: cTokenAmount * accruedPerCToken
uint256 supplierDelta = mul_(supplierTokens, deltaIndex);
uint256 supplierAccrued = add_(compAccrued[supplier], supplierDelta);
compAccrued[supplier] = supplierAccrued;
emit DistributedSupplierComp(
CToken(cToken),
supplier,
supplierDelta,
supplyIndex
);
}
/**
* @notice Calculate COMP accrued by a borrower and possibly transfer it to them
* @dev Borrowers will not begin to accrue until after the first interaction with the protocol.
* @param cToken The market in which the borrower is interacting
* @param borrower The address of the borrower to distribute COMP to
*/
function distributeBorrowerComp(
address cToken,
address borrower,
Exp memory marketBorrowIndex
) internal {
// TODO: Don't distribute supplier COMP if the user is not in the borrower market.
// This check should be as gas efficient as possible as distributeBorrowerComp is called in many places.
// - We really don't want to call an external contract as that's quite expensive.
CompMarketState storage borrowState = compBorrowState[cToken];
uint256 borrowIndex = borrowState.index;
uint256 borrowerIndex = compBorrowerIndex[cToken][borrower];
// Update borrowers's index to the current index since we are distributing accrued COMP
compBorrowerIndex[cToken][borrower] = borrowIndex;
if (borrowerIndex == 0 && borrowIndex >= compInitialIndex) {
// Covers the case where users borrowed tokens before the market's borrow state index was set.
// Rewards the user with COMP accrued from the start of when borrower rewards were first
// set for the market.
borrowerIndex = compInitialIndex;
}
// Calculate change in the cumulative sum of the COMP per borrowed unit accrued
Double memory deltaIndex = Double({
mantissa: sub_(borrowIndex, borrowerIndex)
});
uint256 borrowerAmount = div_(
CToken(cToken).borrowBalanceStored(borrower),
marketBorrowIndex
);
// Calculate COMP accrued: cTokenAmount * accruedPerBorrowedUnit
uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);
uint256 borrowerAccrued = add_(compAccrued[borrower], borrowerDelta);
compAccrued[borrower] = borrowerAccrued;
emit DistributedBorrowerComp(
CToken(cToken),
borrower,
borrowerDelta,
borrowIndex
);
}
/**
* @notice Calculate additional accrued COMP for a contributor since last accrual
* @param contributor The address to calculate contributor rewards for
*/
function updateContributorRewards(address contributor) public {
uint256 compSpeed = compContributorSpeeds[contributor];
uint256 blockNumber = getBlockNumber();
uint256 deltaBlocks = sub_(
blockNumber,
lastContributorBlock[contributor]
);
if (deltaBlocks > 0 && compSpeed > 0) {
uint256 newAccrued = mul_(deltaBlocks, compSpeed);
uint256 contributorAccrued = add_(
compAccrued[contributor],
newAccrued
);
compAccrued[contributor] = contributorAccrued;
lastContributorBlock[contributor] = blockNumber;
}
}
/**
* @notice Claim all the comp accrued by holder in all markets
* @param holder The address to claim COMP for
*/
function claimComp(address holder) public {
return claimComp(holder, allMarkets);
}
/**
* @notice Claim all the comp accrued by holder in the specified markets
* @param holder The address to claim COMP for
* @param cTokens The list of markets to claim COMP in
*/
function claimComp(address holder, CToken[] memory cTokens) public {
address[] memory holders = new address[](1);
holders[0] = holder;
claimComp(holders, cTokens, true, true);
}
/**
* @notice Claim all comp accrued by the holders
* @param holders The addresses to claim COMP for
* @param cTokens The list of markets to claim COMP in
* @param borrowers Whether or not to claim COMP earned by borrowing
* @param suppliers Whether or not to claim COMP earned by supplying
*/
function claimComp(
address[] memory holders,
CToken[] memory cTokens,
bool borrowers,
bool suppliers
) public {
for (uint256 i = 0; i < cTokens.length; i++) {
CToken cToken = cTokens[i];
require(markets[address(cToken)].isListed, "market must be listed");
if (borrowers == true) {
Exp memory borrowIndex = Exp({mantissa: cToken.borrowIndex()});
updateCompBorrowIndex(address(cToken), borrowIndex);
for (uint256 j = 0; j < holders.length; j++) {
distributeBorrowerComp(
address(cToken),
holders[j],
borrowIndex
);
}
}
if (suppliers == true) {
updateCompSupplyIndex(address(cToken));
for (uint256 j = 0; j < holders.length; j++) {
distributeSupplierComp(address(cToken), holders[j]);
}
}
}
for (uint256 j = 0; j < holders.length; j++) {
compAccrued[holders[j]] = grantCompInternal(
holders[j],
compAccrued[holders[j]]
);
}
}
/**
* @notice Transfer COMP to the user
* @dev Note: If there is not enough COMP, we do not perform the transfer all.
* @param user The address of the user to transfer COMP to
* @param amount The amount of COMP to (possibly) transfer
* @return The amount of COMP which was NOT transferred to the user
*/
function grantCompInternal(address user, uint256 amount)
internal
returns (uint256)
{
OrbiterInterface Orbit = OrbiterInterface(ORBITER);
uint256 compRemaining = Orbit.balanceOf(address(this));
if (amount > 0 && amount <= compRemaining) {
Orbit.transfer(user, amount);
return 0;
}
return amount;
}
/*** Comp Distribution Admin ***/
/**
* @notice Transfer COMP to the recipient
* @dev Note: If there is not enough COMP, we do not perform the transfer all.
* @param recipient The address of the recipient to transfer COMP to
* @param amount The amount of COMP to (possibly) transfer
*/
function _grantComp(address recipient, uint256 amount) public {
require(adminOrInitializing(), "only admin can grant comp");
uint256 amountLeft = grantCompInternal(recipient, amount);
require(amountLeft == 0, "insufficient comp for grant");
emit CompGranted(recipient, amount);
}
/**
* @notice Set COMP borrow and supply speeds for the specified markets.
* @param cTokens The markets whose COMP speed to update.
* @param supplySpeeds New supply-side COMP speed for the corresponding market.
* @param borrowSpeeds New borrow-side COMP speed for the corresponding market.
*/
function _setCompSpeeds(
CToken[] memory cTokens,
uint256[] memory supplySpeeds,
uint256[] memory borrowSpeeds
) public {
require(adminOrInitializing(), "only admin can set comp speed");
uint256 numTokens = cTokens.length;
require(
numTokens == supplySpeeds.length &&
numTokens == borrowSpeeds.length,
"Comptroller::_setCompSpeeds invalid input"
);
for (uint256 i = 0; i < numTokens; ++i) {
setCompSpeedInternal(cTokens[i], supplySpeeds[i], borrowSpeeds[i]);
}
}
/**
* @notice Set COMP speed for a single contributor
* @param contributor The contributor whose COMP speed to update
* @param compSpeed New COMP speed for contributor
*/
function _setContributorCompSpeed(address contributor, uint256 compSpeed)
public
{
require(adminOrInitializing(), "only admin can set comp speed");
// note that COMP speed could be set to 0 to halt liquidity rewards for a contributor
updateContributorRewards(contributor);
if (compSpeed == 0) {
// release storage
delete lastContributorBlock[contributor];
} else {
lastContributorBlock[contributor] = getBlockNumber();
}
compContributorSpeeds[contributor] = compSpeed;
emit ContributorCompSpeedUpdated(contributor, compSpeed);
}
/**
* @notice Return all of the markets
* @dev The automatic getter may be used to access an individual market.
* @return The list of market addresses
*/
function getAllMarkets() public view returns (CToken[] memory) {
return allMarkets;
}
/**
* @notice Returns true if the given cToken market has been deprecated
* @dev All borrows in a deprecated cToken market can be immediately liquidated
* @param cToken The market to check if deprecated
*/
function isDeprecated(CToken cToken) public view returns (bool) {
return
markets[address(cToken)].collateralFactorMantissa == 0 &&
borrowGuardianPaused[address(cToken)] == true &&
cToken.reserveFactorMantissa() == 1e18;
}
function getBlockNumber() public view virtual returns (uint256) {
return block.number;
}
/**
* @notice Return the address of the COMP token
* @return The address of COMP
*/
function getCompAddress() public view virtual returns (address) {
return ORBITER;
}
function setOrbiterContractAddress(address _address)
public
returns (uint256)
{
if (msg.sender != admin) {
return
fail(
Error.UNAUTHORIZED,
FailureInfo.SET_PRICE_ORACLE_OWNER_CHECK
);
}
ORBITER = _address;
return uint256(Error.NO_ERROR);
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"action","type":"string"},{"indexed":false,"internalType":"bool","name":"pauseState","type":"bool"}],"name":"ActionPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract CToken","name":"cToken","type":"address"},{"indexed":false,"internalType":"string","name":"action","type":"string"},{"indexed":false,"internalType":"bool","name":"pauseState","type":"bool"}],"name":"ActionPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"oldCompAccrued","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newCompAccrued","type":"uint256"}],"name":"CompAccruedAdjusted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract CToken","name":"cToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"newSpeed","type":"uint256"}],"name":"CompBorrowSpeedUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"CompGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"oldCompReceivable","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newCompReceivable","type":"uint256"}],"name":"CompReceivableUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract CToken","name":"cToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"newSpeed","type":"uint256"}],"name":"CompSupplySpeedUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"contributor","type":"address"},{"indexed":false,"internalType":"uint256","name":"newSpeed","type":"uint256"}],"name":"ContributorCompSpeedUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract CToken","name":"cToken","type":"address"},{"indexed":true,"internalType":"address","name":"borrower","type":"address"},{"indexed":false,"internalType":"uint256","name":"compDelta","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"compBorrowIndex","type":"uint256"}],"name":"DistributedBorrowerComp","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract CToken","name":"cToken","type":"address"},{"indexed":true,"internalType":"address","name":"supplier","type":"address"},{"indexed":false,"internalType":"uint256","name":"compDelta","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"compSupplyIndex","type":"uint256"}],"name":"DistributedSupplierComp","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"error","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"info","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"detail","type":"uint256"}],"name":"Failure","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract CToken","name":"cToken","type":"address"},{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"MarketEntered","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract CToken","name":"cToken","type":"address"},{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"MarketExited","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract CToken","name":"cToken","type":"address"}],"name":"MarketListed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract CToken","name":"cToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"newBorrowCap","type":"uint256"}],"name":"NewBorrowCap","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldBorrowCapGuardian","type":"address"},{"indexed":false,"internalType":"address","name":"newBorrowCapGuardian","type":"address"}],"name":"NewBorrowCapGuardian","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldCloseFactorMantissa","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newCloseFactorMantissa","type":"uint256"}],"name":"NewCloseFactor","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract CToken","name":"cToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"oldCollateralFactorMantissa","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newCollateralFactorMantissa","type":"uint256"}],"name":"NewCollateralFactor","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract IncentiveInterface","name":"oldInscentive","type":"address"},{"indexed":false,"internalType":"contract IncentiveInterface","name":"newInscentive","type":"address"}],"name":"NewIncentive","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldLiquidationIncentiveMantissa","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newLiquidationIncentiveMantissa","type":"uint256"}],"name":"NewLiquidationIncentive","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldPauseGuardian","type":"address"},{"indexed":false,"internalType":"address","name":"newPauseGuardian","type":"address"}],"name":"NewPauseGuardian","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract PriceOracle","name":"oldPriceOracle","type":"address"},{"indexed":false,"internalType":"contract PriceOracle","name":"newPriceOracle","type":"address"}],"name":"NewPriceOracle","type":"event"},{"inputs":[{"internalType":"contract Unitroller","name":"unitroller","type":"address"}],"name":"_become","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"_borrowGuardianPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"_grantComp","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"_mintGuardianPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newBorrowCapGuardian","type":"address"}],"name":"_setBorrowCapGuardian","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract CToken","name":"cToken","type":"address"},{"internalType":"bool","name":"state","type":"bool"}],"name":"_setBorrowPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newCloseFactorMantissa","type":"uint256"}],"name":"_setCloseFactor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract CToken","name":"cToken","type":"address"},{"internalType":"uint256","name":"newCollateralFactorMantissa","type":"uint256"}],"name":"_setCollateralFactor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract CToken[]","name":"cTokens","type":"address[]"},{"internalType":"uint256[]","name":"supplySpeeds","type":"uint256[]"},{"internalType":"uint256[]","name":"borrowSpeeds","type":"uint256[]"}],"name":"_setCompSpeeds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"contributor","type":"address"},{"internalType":"uint256","name":"compSpeed","type":"uint256"}],"name":"_setContributorCompSpeed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IncentiveInterface","name":"newIncentive","type":"address"}],"name":"_setIncentive","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newLiquidationIncentiveMantissa","type":"uint256"}],"name":"_setLiquidationIncentive","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract CToken[]","name":"cTokens","type":"address[]"},{"internalType":"uint256[]","name":"newBorrowCaps","type":"uint256[]"}],"name":"_setMarketBorrowCaps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract CToken","name":"cToken","type":"address"},{"internalType":"bool","name":"state","type":"bool"}],"name":"_setMintPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newPauseGuardian","type":"address"}],"name":"_setPauseGuardian","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract PriceOracle","name":"newOracle","type":"address"}],"name":"_setPriceOracle","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"state","type":"bool"}],"name":"_setSeizePaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"state","type":"bool"}],"name":"_setTransferPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract CToken","name":"cToken","type":"address"}],"name":"_supportMarket","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"accountAssets","outputs":[{"internalType":"contract CToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"allMarkets","outputs":[{"internalType":"contract CToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"cToken","type":"address"},{"internalType":"address","name":"borrower","type":"address"},{"internalType":"uint256","name":"borrowAmount","type":"uint256"}],"name":"borrowAllowed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"borrowCapGuardian","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"borrowCaps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"borrowGuardianPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"cToken","type":"address"},{"internalType":"address","name":"borrower","type":"address"},{"internalType":"uint256","name":"borrowAmount","type":"uint256"}],"name":"borrowVerify","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"contract CToken","name":"cToken","type":"address"}],"name":"checkMembership","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"holder","type":"address"},{"internalType":"contract CToken[]","name":"cTokens","type":"address[]"}],"name":"claimComp","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"holders","type":"address[]"},{"internalType":"contract CToken[]","name":"cTokens","type":"address[]"},{"internalType":"bool","name":"borrowers","type":"bool"},{"internalType":"bool","name":"suppliers","type":"bool"}],"name":"claimComp","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"holder","type":"address"}],"name":"claimComp","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"closeFactorMantissa","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"compAccrued","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"compBorrowSpeeds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"compBorrowState","outputs":[{"internalType":"uint224","name":"index","type":"uint224"},{"internalType":"uint32","name":"block","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"compBorrowerIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"compContributorSpeeds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"compInitialIndex","outputs":[{"internalType":"uint224","name":"","type":"uint224"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"compRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"compReceivable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"compSpeeds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"compSupplierIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"compSupplySpeeds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"compSupplyState","outputs":[{"internalType":"uint224","name":"index","type":"uint224"},{"internalType":"uint32","name":"block","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"comptrollerImplementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"cTokens","type":"address[]"}],"name":"enterMarkets","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"cTokenAddress","type":"address"}],"name":"exitMarket","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"affectedUsers","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"fixBadAccruals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getAccountLiquidity","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllMarkets","outputs":[{"internalType":"contract CToken[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getAssetsIn","outputs":[{"internalType":"contract CToken[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBlockNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCompAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"cTokenModify","type":"address"},{"internalType":"uint256","name":"redeemTokens","type":"uint256"},{"internalType":"uint256","name":"borrowAmount","type":"uint256"}],"name":"getHypotheticalAccountLiquidity","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"incentive","outputs":[{"internalType":"contract IncentiveInterface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isComptroller","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract CToken","name":"cToken","type":"address"}],"name":"isDeprecated","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"lastContributorBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"cTokenBorrowed","type":"address"},{"internalType":"address","name":"cTokenCollateral","type":"address"},{"internalType":"address","name":"liquidator","type":"address"},{"internalType":"address","name":"borrower","type":"address"},{"internalType":"uint256","name":"repayAmount","type":"uint256"}],"name":"liquidateBorrowAllowed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"cTokenBorrowed","type":"address"},{"internalType":"address","name":"cTokenCollateral","type":"address"},{"internalType":"address","name":"liquidator","type":"address"},{"internalType":"address","name":"borrower","type":"address"},{"internalType":"uint256","name":"actualRepayAmount","type":"uint256"},{"internalType":"uint256","name":"seizeTokens","type":"uint256"}],"name":"liquidateBorrowVerify","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"cTokenBorrowed","type":"address"},{"internalType":"address","name":"cTokenCollateral","type":"address"},{"internalType":"uint256","name":"actualRepayAmount","type":"uint256"}],"name":"liquidateCalculateSeizeTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"liquidationIncentiveMantissa","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"markets","outputs":[{"internalType":"bool","name":"isListed","type":"bool"},{"internalType":"uint256","name":"collateralFactorMantissa","type":"uint256"},{"internalType":"bool","name":"isComped","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"cToken","type":"address"},{"internalType":"address","name":"minter","type":"address"},{"internalType":"uint256","name":"mintAmount","type":"uint256"}],"name":"mintAllowed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"mintGuardianPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"cToken","type":"address"},{"internalType":"address","name":"minter","type":"address"},{"internalType":"uint256","name":"actualMintAmount","type":"uint256"},{"internalType":"uint256","name":"mintTokens","type":"uint256"}],"name":"mintVerify","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"oracle","outputs":[{"internalType":"contract PriceOracle","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pauseGuardian","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingComptrollerImplementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proposal65FixExecuted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"cToken","type":"address"},{"internalType":"address","name":"redeemer","type":"address"},{"internalType":"uint256","name":"redeemTokens","type":"uint256"}],"name":"redeemAllowed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"cToken","type":"address"},{"internalType":"address","name":"redeemer","type":"address"},{"internalType":"uint256","name":"redeemAmount","type":"uint256"},{"internalType":"uint256","name":"redeemTokens","type":"uint256"}],"name":"redeemVerify","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"cToken","type":"address"},{"internalType":"address","name":"payer","type":"address"},{"internalType":"address","name":"borrower","type":"address"},{"internalType":"uint256","name":"repayAmount","type":"uint256"}],"name":"repayBorrowAllowed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"cToken","type":"address"},{"internalType":"address","name":"payer","type":"address"},{"internalType":"address","name":"borrower","type":"address"},{"internalType":"uint256","name":"actualRepayAmount","type":"uint256"},{"internalType":"uint256","name":"borrowerIndex","type":"uint256"}],"name":"repayBorrowVerify","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"cTokenCollateral","type":"address"},{"internalType":"address","name":"cTokenBorrowed","type":"address"},{"internalType":"address","name":"liquidator","type":"address"},{"internalType":"address","name":"borrower","type":"address"},{"internalType":"uint256","name":"seizeTokens","type":"uint256"}],"name":"seizeAllowed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"seizeGuardianPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"cTokenCollateral","type":"address"},{"internalType":"address","name":"cTokenBorrowed","type":"address"},{"internalType":"address","name":"liquidator","type":"address"},{"internalType":"address","name":"borrower","type":"address"},{"internalType":"uint256","name":"seizeTokens","type":"uint256"}],"name":"seizeVerify","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"setOrbiterContractAddress","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"cToken","type":"address"},{"internalType":"address","name":"src","type":"address"},{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"transferTokens","type":"uint256"}],"name":"transferAllowed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"transferGuardianPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"cToken","type":"address"},{"internalType":"address","name":"src","type":"address"},{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"transferTokens","type":"uint256"}],"name":"transferVerify","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"contributor","type":"address"}],"name":"updateContributorRewards","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
6080604052601e80546001600160a01b03191673e5abf4fce02fbb3b47b5704e198f947433bfaeed17905534801561003657600080fd5b50600080546001600160a01b0319163317905561587980620000596000396000f3fe608060405234801561001057600080fd5b50600436106104ab5760003560e01c8063731f0c2b1161026d578063bb82aa5e11610151578063dce15449116100ce578063e9af029211610092578063e9af029214610c55578063eabe7d9114610c68578063ede4edd014610c7b578063f00a7a9214610c8e578063f4a433c014610c9b578063f851a44014610cbb57600080fd5b8063dce1544914610bff578063dcfbc0c714610c12578063e4028eee14610c25578063e6653f3d14610c38578063e875544614610c4c57600080fd5b8063ca0af04311610115578063ca0af04314610b7b578063cc7ebdc414610ba6578063cdd0404114610bc6578063d02f735114610bd9578063da3d454c14610bec57600080fd5b8063bb82aa5e14610aed578063bdcdc25814610b00578063bea6b8b814610b13578063c299823814610b33578063c488847b14610b5357600080fd5b806394b2294b116101ea578063a8b43948116101ae578063a8b4394814610a6a578063aa90075414610a7d578063abfceffc14610a86578063ac0b0bb714610aa6578063b0772d0b14610aba578063b21be7fd14610ac257600080fd5b806394b2294b146109f0578063986ab838146109f95780639d1b5a0a14610a19578063a76b3fda14610a2a578063a7f0e23114610a3d57600080fd5b80638c57804e116102315780638c57804e146108fe5780638e8f294b146109365780638ebf636414610989578063929fe9a11461099c57806394543c15146109dd57600080fd5b8063731f0c2b14610881578063741b2525146108a45780637dc0d1d0146108b757806385b7beb8146108ca57806387f76303146108ea57600080fd5b80634a584432116103945780635e2c2a3b116103115780636810dfa6116102d55780636810dfa6146107b35780636a56947e146107c65780636aa875b5146107d45780636b79c38d146107f45780636d154ea5146108505780636d35bf911461087357600080fd5b80635e2c2a3b146107545780635ec88c79146107675780635f5af1aa1461077a5780635fc7e71e1461078d578063607ef6c1146107a057600080fd5b806351dff9891161035857806351dff989146106f557806352d84d1e1461070857806355ee1fe11461071b578063598ee1cb1461072e5780635c7786051461074157600080fd5b80634a584432146106785780634ada90af146106985780634e79238f146106a15780634ef4c3e1146106cf5780634fd42e17146106e257600080fd5b806324a3d6221161042d578063391957d7116103f1578063391957d71461060e5780633bcf7ec1146106215780633c94786f1461063457806341c728b91461064857806342cbb15c1461065c57806347ef3b3b1461066257600080fd5b806324a3d622146105af57806326782247146105c257806327efe3cb146105d55780632d70db78146105e8578063317b0b77146105fb57600080fd5b80631d504dc6116104745780631d504dc6146105335780631d7b33d7146105465780631ededc911461057457806321af45691461058957806324008a621461059c57600080fd5b80627e3dd2146104b057806316b95e8f146104cd57806318c882a5146104e25780631c3db2e0146104f55780631d4632ac14610508575b600080fd5b6104b8600181565b60405190151581526020015b60405180910390f35b6104e06104db366004614e60565b610cce565b005b6104b86104f0366004614eef565b610f77565b6104e0610503366004615007565b6110b0565b60055461051b906001600160a01b031681565b6040516001600160a01b0390911681526020016104c4565b6104e0610541366004615057565b611113565b610566610554366004615057565b60106020526000908152604090205481565b6040519081526020016104c4565b6104e0610582366004615074565b5050505050565b60165461051b906001600160a01b031681565b6105666105aa3660046150cf565b611291565b600b5461051b906001600160a01b031681565b60015461051b906001600160a01b031681565b6104e06105e3366004615120565b6113c5565b6104b86105f636600461514c565b6114bc565b610566610609366004615169565b6115ac565b6104e061061c366004615057565b611653565b6104b861062f366004614eef565b61171b565b600b546104b890600160a01b900460ff1681565b6104e0610656366004615182565b50505050565b43610566565b6104e06106703660046151c8565b505050505050565b610566610686366004615057565b60176020526000908152604090205481565b61056660075481565b6106b46106af366004615182565b611845565b604080519384526020840192909252908201526060016104c4565b6105666106dd366004615236565b611885565b6105666106f0366004615169565b61199c565b6104e0610703366004615182565b6119f9565b61051b610716366004615169565b611a48565b610566610729366004615057565b611a72565b6104e061073c366004615120565b611ae4565b6104e061074f366004615236565b505050565b610566610762366004615057565b611bd8565b6106b4610775366004615057565b611c4a565b610566610788366004615057565b611c85565b61056661079b366004615277565b611cf6565b6104e06107ae366004614e60565b611ec5565b6104e06107c136600461533f565b6120a3565b6104e06106563660046150cf565b6105666107e2366004615057565b601b6020526000908152604090205481565b61082c610802366004615057565b6011602052600090815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff9091166020830152016104c4565b6104b861085e366004615057565b600d6020526000908152604090205460ff1681565b6104e0610582366004615277565b6104b861088f366004615057565b600c6020526000908152604090205460ff1681565b6104e06108b2366004615057565b61232d565b60045461051b906001600160a01b031681565b6105666108d8366004615057565b601d6020526000908152604090205481565b600b546104b890600160b01b900460ff1681565b61082c61090c366004615057565b6012602052600090815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b61096a610944366004615057565b600a6020526000908152604090208054600182015460039092015460ff91821692911683565b60408051931515845260208401929092521515908201526060016104c4565b6104b861099736600461514c565b6123d9565b6104b86109aa3660046153c8565b6001600160a01b038082166000908152600a60209081526040808320938616835260029093019052205460ff1692915050565b6104b86109eb366004615057565b6124c0565b61056660085481565b610566610a07366004615057565b60186020526000908152604090205481565b601e546001600160a01b031661051b565b610566610a38366004615057565b61257f565b610a526a0c097ce7bc90715b34b9f160241b81565b6040516001600160e01b0390911681526020016104c4565b6104e0610a78366004615451565b6126b1565b610566600f5481565b610a99610a94366004615057565b6127e6565b6040516104c491906154d9565b600b546104b890600160b81b900460ff1681565b610a9961285c565b610566610ad03660046153c8565b601360209081526000928352604080842090915290825290205481565b60025461051b906001600160a01b031681565b610566610b0e3660046150cf565b6128be565b610566610b21366004615057565b60196020526000908152604090205481565b610b46610b41366004615526565b6129f0565b6040516104c4919061555b565b610b66610b61366004615236565b612ab8565b604080519283526020830191909152016104c4565b610566610b893660046153c8565b601460209081526000928352604080842090915290825290205481565b610566610bb4366004615057565b60156020526000908152604090205481565b610566610bd4366004615057565b612cd6565b610566610be7366004615277565b612d17565b610566610bfa366004615236565b612f98565b61051b610c0d366004615120565b6133de565b60035461051b906001600160a01b031681565b610566610c33366004615120565b613416565b600b546104b890600160a81b900460ff1681565b61056660065481565b6104e0610c63366004615057565b6135a8565b610566610c76366004615236565b61360c565b610566610c89366004615057565b6136bd565b601c546104b89060ff1681565b610566610ca9366004615057565b601a6020526000908152604090205481565b60005461051b906001600160a01b031681565b6000546001600160a01b03163314610d375760405162461bcd60e51b815260206004820152602160248201527f4f6e6c792061646d696e2063616e2063616c6c20746869732066756e6374696f6044820152603760f91b60648201526084015b60405180910390fd5b601c5460ff1615610d995760405162461bcd60e51b815260206004820152602660248201527f416c72656164792065786563757465642074686973206f6e652d6f66662066756044820152653731ba34b7b760d11b6064820152608401610d2e565b828114610dd85760405162461bcd60e51b815260206004820152600d60248201526c125b9d985b1a59081a5b9c1d5d609a1b6044820152606401610d2e565b60008060008060005b87811015610f5f57888882818110610dfb57610dfb615593565b9050602002016020810190610e109190615057565b6001600160a01b0381166000908152601560205260409020549095509350868682818110610e4057610e40615593565b90506020020135925083831115610ee4576000610e5d85856155bf565b6001600160a01b0387166000908152601d6020526040812054919250610e838284613a0e565b6001600160a01b0389166000818152601d6020908152604091829020849055815186815290810184905292935090917f17fea09d9a7ca41b2f9f9118f18f44848a62e9c70d55dd4385131eb2cf1b7e47910160405180910390a28695505050505b8215610f4f57610ef48484613a1a565b6001600160a01b038616600081815260156020908152604091829020849055815188815290810184905292945090917f4a5c134e28b537a76546993ea37f3b60d9190476df7356d3842aa40902e20f04910160405180910390a25b610f58816155d6565b9050610de1565b5050601c805460ff1916600117905550505050505050565b6001600160a01b0382166000908152600a602052604081205460ff16610faf5760405162461bcd60e51b8152600401610d2e906155f1565b600b546001600160a01b0316331480610fd257506000546001600160a01b031633145b610fee5760405162461bcd60e51b8152600401610d2e90615639565b6000546001600160a01b031633148061100957506001821515145b6110255760405162461bcd60e51b8152600401610d2e90615680565b6001600160a01b0383166000818152600d6020908152604091829020805460ff19168615159081179091558251938452606091840182905260069184019190915265426f72726f7760d01b6080840152908201527f71aec636243f9709bb0007ae15e9afb8150ab01716d75fd7573be5cc096e03b09060a0015b60405180910390a150805b92915050565b6040805160018082528183019092526000916020808301908036833701905050905082816000815181106110e6576110e6615593565b60200260200101906001600160a01b031690816001600160a01b03168152505061074f81836001806120a3565b806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa158015611151573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061117591906156b0565b6001600160a01b0316336001600160a01b0316146111e55760405162461bcd60e51b815260206004820152602760248201527f6f6e6c7920756e6974726f6c6c65722061646d696e2063616e206368616e676560448201526620627261696e7360c81b6064820152608401610d2e565b806001600160a01b031663c1e803346040518163ffffffff1660e01b81526004016020604051808303816000875af1158015611225573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061124991906156cd565b1561128e5760405162461bcd60e51b815260206004820152601560248201527418da185b99d9481b9bdd08185d5d1a1bdc9a5e9959605a1b6044820152606401610d2e565b50565b6001600160a01b0384166000908152600a602052604081205460ff166112b9575060096113bd565b60006040518060200160405280876001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611304573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061132891906156cd565b905290506113368682613a26565b611341868583613c19565b6005546001600160a01b0316156113b75760055460405163623eb01b60e11b81526001600160a01b039091169063c47d60369061138490899088906004016156fc565b600060405180830381600087803b15801561139e57600080fd5b505af11580156113b2573d6000803e3d6000fd5b505050505b60009150505b949350505050565b6113cd613d99565b6114195760405162461bcd60e51b815260206004820152601960248201527f6f6e6c792061646d696e2063616e206772616e7420636f6d70000000000000006044820152606401610d2e565b60006114258383613dc2565b905080156114755760405162461bcd60e51b815260206004820152601b60248201527f696e73756666696369656e7420636f6d7020666f72206772616e7400000000006044820152606401610d2e565b604080516001600160a01b0385168152602081018490527f98b2f82a3a07f223a0be64b3d0f47711c64dccd1feafb94aa28156b38cd9695c910160405180910390a1505050565b600b546000906001600160a01b03163314806114e257506000546001600160a01b031633145b6114fe5760405162461bcd60e51b8152600401610d2e90615639565b6000546001600160a01b031633148061151957506001821515145b6115355760405162461bcd60e51b8152600401610d2e90615680565b600b8054831515600160b81b0260ff60b81b199091161790556040517fef159d9a32b2472e32b098f954f3ce62d232939f1c207070b584df1814de2de0906115a09084906040808252600590820152645365697a6560d81b6060820152901515602082015260800190565b60405180910390a15090565b600080546001600160a01b031633146116075760405162461bcd60e51b815260206004820152601f60248201527f6f6e6c792061646d696e2063616e2073657420636c6f736520666163746f72006044820152606401610d2e565b600680549083905560408051828152602081018590527f3b9670cf975d26958e754b57098eaa2ac914d8d2a31b83257997b9f346110fd991015b60405180910390a160005b9392505050565b6000546001600160a01b031633146116bc5760405162461bcd60e51b815260206004820152602660248201527f6f6e6c792061646d696e2063616e2073657420626f72726f772063617020677560448201526530b93234b0b760d11b6064820152608401610d2e565b601680546001600160a01b038381166001600160a01b03198316179092556040519116907feda98690e518e9a05f8ec6837663e188211b2da8f4906648b323f2c1d4434e299061170f90839085906156fc565b60405180910390a15050565b6001600160a01b0382166000908152600a602052604081205460ff166117535760405162461bcd60e51b8152600401610d2e906155f1565b600b546001600160a01b031633148061177657506000546001600160a01b031633145b6117925760405162461bcd60e51b8152600401610d2e90615639565b6000546001600160a01b03163314806117ad57506001821515145b6117c95760405162461bcd60e51b8152600401610d2e90615680565b6001600160a01b0383166000818152600c6020908152604091829020805460ff19168615159081179091558251938452606091840182905260049184019190915263135a5b9d60e21b6080840152908201527f71aec636243f9709bb0007ae15e9afb8150ab01716d75fd7573be5cc096e03b09060a00161109f565b60008060008060008061185a8a8a8a8a613ed2565b925092509250826011811115611872576118726156e6565b95509093509150505b9450945094915050565b6001600160a01b0383166000908152600c602052604081205460ff16156118df5760405162461bcd60e51b815260206004820152600e60248201526d1b5a5b9d081a5cc81c185d5cd95960921b6044820152606401610d2e565b6001600160a01b0384166000908152600a602052604090205460ff166119095760095b905061164c565b61191284614200565b61191c8484614378565b6005546001600160a01b03161561199257600554604051631f916ef560e11b81526001600160a01b0390911690633f22ddea9061195f90879087906004016156fc565b600060405180830381600087803b15801561197957600080fd5b505af115801561198d573d6000803e3d6000fd5b505050505b6000949350505050565b600080546001600160a01b031633146119bb576110aa6001600b614516565b600780549083905560408051828152602081018590527faeba5a6c40a8ac138134bff1aaa65debf25971188a58804bad717f82f0ec13169101611641565b80158015611a075750600082115b156106565760405162461bcd60e51b815260206004820152601160248201527072656465656d546f6b656e73207a65726f60781b6044820152606401610d2e565b600e8181548110611a5857600080fd5b6000918252602090912001546001600160a01b0316905081565b600080546001600160a01b03163314611a91576110aa60016010614516565b600480546001600160a01b038481166001600160a01b03198316179092556040519116907fd52b2b9b7e9ee655fcb95d2e5b9e0c9f69e7ef2b8e9d2d0ea78402d576d22e229061164190839086906156fc565b611aec613d99565b611b385760405162461bcd60e51b815260206004820152601d60248201527f6f6e6c792061646d696e2063616e2073657420636f6d702073706565640000006044820152606401610d2e565b611b418261232d565b80611b64576001600160a01b038216600090815260196020526040812055611b7f565b436001600160a01b0383166000908152601960205260409020555b6001600160a01b03821660008181526018602052604090819020839055517f386537fa92edc3319af95f1f904dcf1900021e4f3f4e08169a577a09076e66b390611bcc9084815260200190565b60405180910390a25050565b600080546001600160a01b03163314611bf7576110aa60016014614516565b600580546001600160a01b038481166001600160a01b03198316179092556040519116907fbd182757c0006b9842c613e7591cf5a9ea286903d8bca3413df7299b7f43517e9061164190839086906156fc565b600080600080600080611c61876000806000613ed2565b925092509250826011811115611c7957611c796156e6565b97919650945092505050565b600080546001600160a01b03163314611ca4576110aa60016013614516565b600b80546001600160a01b038481166001600160a01b0319831681179093556040519116917f0613b6ee6a04f0d09f390e4d9318894b9f6ac7fd83897cd8d18896ba579c401e916116419184916156fc565b6001600160a01b0385166000908152600a602052604081205460ff161580611d3757506001600160a01b0385166000908152600a602052604090205460ff16155b15611d465760095b9050611ebc565b6040516395dd919360e01b81526001600160a01b038481166004830152600091908816906395dd919390602401602060405180830381865afa158015611d90573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611db491906156cd565b9050611dbf876124c0565b15611e2a5782811015611e255760405162461bcd60e51b815260206004820152602860248201527f43616e206e6f74207265706179206d6f7265207468616e2074686520746f74616044820152676c20626f72726f7760c01b6064820152608401610d2e565b611eb6565b600080611e368661458f565b91935090915060009050826011811115611e5257611e526156e6565b14611e7357816011811115611e6957611e696156e6565b9350505050611ebc565b80611e7f576003611e69565b6000611e9b6040518060200160405280600654815250856145af565b905080861115611eb2576011945050505050611ebc565b5050505b60009150505b95945050505050565b6000546001600160a01b0316331480611ee857506016546001600160a01b031633145b611f525760405162461bcd60e51b815260206004820152603560248201527f6f6e6c792061646d696e206f7220626f72726f772063617020677561726469616044820152746e2063616e2073657420626f72726f77206361707360581b6064820152608401610d2e565b82818115801590611f6257508082145b611f9e5760405162461bcd60e51b815260206004820152600d60248201526c1a5b9d985b1a59081a5b9c1d5d609a1b6044820152606401610d2e565b60005b8281101561209a57848482818110611fbb57611fbb615593565b9050602002013560176000898985818110611fd857611fd8615593565b9050602002016020810190611fed9190615057565b6001600160a01b0316815260208101919091526040016000205586868281811061201957612019615593565b905060200201602081019061202e9190615057565b6001600160a01b03167f6f1951b2aad10f3fc81b86d91105b413a5b3f847a34bbc5ce1904201b14438f686868481811061206a5761206a615593565b9050602002013560405161208091815260200190565b60405180910390a280612092816155d6565b915050611fa1565b50505050505050565b60005b835181101561226a5760008482815181106120c3576120c3615593565b6020908102919091018101516001600160a01b0381166000908152600a90925260409091205490915060ff166121335760405162461bcd60e51b81526020600482015260156024820152741b585c9ad95d081b5d5cdd081899481b1a5cdd1959605a1b6044820152606401610d2e565b600184151514156122005760006040518060200160405280836001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612189573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ad91906156cd565b905290506121bb8282613a26565b60005b87518110156121fd576121eb838983815181106121dd576121dd615593565b602002602001015184613c19565b806121f5816155d6565b9150506121be565b50505b600183151514156122575761221481614200565b60005b8651811015612255576122438288838151811061223657612236615593565b6020026020010151614378565b8061224d816155d6565b915050612217565b505b5080612262816155d6565b9150506120a6565b5060005b8451811015610582576122d885828151811061228c5761228c615593565b6020026020010151601560008885815181106122aa576122aa615593565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054613dc2565b601560008784815181106122ee576122ee615593565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020819055508080612325906155d6565b91505061226e565b6001600160a01b038116600090815260186020908152604080832054601990925282205490914391612360908390613a1a565b90506000811180156123725750600083115b1561065657600061238382856145c7565b6001600160a01b038616600090815260156020526040812054919250906123aa9083613a0e565b6001600160a01b0387166000908152601560209081526040808320939093556019905220849055505050505050565b600b546000906001600160a01b03163314806123ff57506000546001600160a01b031633145b61241b5760405162461bcd60e51b8152600401610d2e90615639565b6000546001600160a01b031633148061243657506001821515145b6124525760405162461bcd60e51b8152600401610d2e90615680565b600b8054831515600160b01b0260ff60b01b199091161790556040517fef159d9a32b2472e32b098f954f3ce62d232939f1c207070b584df1814de2de0906115a09084906040808252600890820152672a3930b739b332b960c11b6060820152901515602082015260800190565b6001600160a01b0381166000908152600a602052604081206001015415801561250657506001600160a01b0382166000908152600d602052604090205460ff1615156001145b80156110aa5750816001600160a01b031663173b99046040518163ffffffff1660e01b8152600401602060405180830381865afa15801561254b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061256f91906156cd565b670de0b6b3a76400001492915050565b600080546001600160a01b0316331461259e576110aa60016012614516565b6001600160a01b0382166000908152600a602052604090205460ff16156125cb576110aa600a6011614516565b816001600160a01b031663fe9c44ae6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612609573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061262d9190615716565b506001600160a01b0382166000908152600a602052604081208054600160ff199182168117835560038301805490921690915581019190915561266f836145d3565b612678836146bc565b6040516001600160a01b03841681527fcf583bb0c569eb967f806b11601c4cb93c10310485c67add5f8362c2f212321f90602001611641565b6126b9613d99565b6127055760405162461bcd60e51b815260206004820152601d60248201527f6f6e6c792061646d696e2063616e2073657420636f6d702073706565640000006044820152606401610d2e565b82518251811480156127175750815181145b6127755760405162461bcd60e51b815260206004820152602960248201527f436f6d7074726f6c6c65723a3a5f736574436f6d7053706565647320696e76616044820152681b1a59081a5b9c1d5d60ba1b6064820152608401610d2e565b60005b81811015610582576127d685828151811061279557612795615593565b60200260200101518583815181106127af576127af615593565b60200260200101518584815181106127c9576127c9615593565b6020026020010151614778565b6127df816155d6565b9050612778565b6001600160a01b038116600090815260096020908152604080832080548251818502810185019093528083526060949383018282801561284f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612831575b5093979650505050505050565b6060600e8054806020026020016040519081016040528092919081815260200182805480156128b457602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612896575b5050505050905090565b600b54600090600160b01b900460ff16156129105760405162461bcd60e51b81526020600482015260126024820152711d1c985b9cd9995c881a5cc81c185d5cd95960721b6044820152606401610d2e565b600061291d868685614957565b9050801561292c5790506113bd565b61293586614200565b61293f8686614378565b6129498685614378565b6005546001600160a01b0316156113b757600554604051631f916ef560e11b81526001600160a01b0390911690633f22ddea9061298c90899089906004016156fc565b600060405180830381600087803b1580156129a657600080fd5b505af11580156129ba573d6000803e3d6000fd5b5050600554604051631f916ef560e11b81526001600160a01b039091169250633f22ddea915061138490899088906004016156fc565b805160609060008167ffffffffffffffff811115612a1057612a10614f28565b604051908082528060200260200182016040528015612a39578160200160208202803683370190505b50905060005b82811015612ab0576000858281518110612a5b57612a5b615593565b60200260200101519050612a6f8133614a0f565b6011811115612a8057612a806156e6565b838381518110612a9257612a92615593565b60209081029190910101525080612aa8816155d6565b915050612a3f565b509392505050565b6004805460405163fc57d4df60e01b81526001600160a01b03868116938201939093526000928392839291169063fc57d4df90602401602060405180830381865afa158015612b0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b2f91906156cd565b6004805460405163fc57d4df60e01b81526001600160a01b038981169382019390935292935060009291169063fc57d4df90602401602060405180830381865afa158015612b81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ba591906156cd565b9050811580612bb2575080155b15612bc657600d6000935093505050612cce565b6000866001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c06573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c2a91906156cd565b90506000612c446040518060200160405280600081525090565b604080516020808201835260008083528351808301855290815283518083018552600754815284519283019094528882529192612c8091614b06565b9250612ca8604051806020016040528088815250604051806020016040528088815250614b06565b9150612cb48383614b4e565b9050612cc0818b6145af565b600099509750505050505050505b935093915050565b600080546001600160a01b03163314612cf5576110aa60016010614516565b601e80546001600160a01b0319166001600160a01b03841617905560006110aa565b600b54600090600160b81b900460ff1615612d665760405162461bcd60e51b815260206004820152600f60248201526e1cd95a5e99481a5cc81c185d5cd959608a1b6044820152606401610d2e565b6001600160a01b0386166000908152600a602052604090205460ff161580612da757506001600160a01b0385166000908152600a602052604090205460ff16155b15612db3576009611d3f565b846001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612df1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e1591906156b0565b6001600160a01b0316866001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612e5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e8091906156b0565b6001600160a01b031614612e95576002611d3f565b612e9e86614200565b612ea88684614378565b612eb28685614378565b6005546001600160a01b031615612f8c57600554604051631f916ef560e11b81526001600160a01b0390911690633f22ddea90612ef590899087906004016156fc565b600060405180830381600087803b158015612f0f57600080fd5b505af1158015612f23573d6000803e3d6000fd5b5050600554604051631f916ef560e11b81526001600160a01b039091169250633f22ddea9150612f5990899088906004016156fc565b600060405180830381600087803b158015612f7357600080fd5b505af1158015612f87573d6000803e3d6000fd5b505050505b60009695505050505050565b6001600160a01b0383166000908152600d602052604081205460ff1615612ff45760405162461bcd60e51b815260206004820152601060248201526f189bdc9c9bddc81a5cc81c185d5cd95960821b6044820152606401610d2e565b6001600160a01b0384166000908152600a602052604090205460ff1661301b576009611902565b6001600160a01b038085166000908152600a60209081526040808320938716835260029093019052205460ff1661311857336001600160a01b0385161461309c5760405162461bcd60e51b815260206004820152601560248201527439b2b73232b91036bab9ba1031329031aa37b5b2b760591b6044820152606401610d2e565b60006130a83385614a0f565b905060008160118111156130be576130be6156e6565b146130dd578060118111156130d5576130d56156e6565b91505061164c565b6001600160a01b038086166000908152600a60209081526040808320938816835260029093019052205460ff1661311657613116615733565b505b6004805460405163fc57d4df60e01b81526001600160a01b038781169382019390935291169063fc57d4df90602401602060405180830381865afa158015613164573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061318891906156cd565b61319357600d611902565b6001600160a01b0384166000908152601760205260409020548015613278576000856001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa1580156131f2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061321691906156cd565b905060006132248286613a0e565b90508281106132755760405162461bcd60e51b815260206004820152601960248201527f6d61726b657420626f72726f77206361702072656163686564000000000000006044820152606401610d2e565b50505b6000806132888688600088613ed2565b919350909150600090508260118111156132a4576132a46156e6565b146132c5578160118111156132bb576132bb6156e6565b935050505061164c565b80156132d25760046132bb565b60006040518060200160405280896001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561331d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061334191906156cd565b9052905061334f8882613a26565b61335a888883613c19565b6005546001600160a01b0316156133d05760055460405163623eb01b60e11b81526001600160a01b039091169063c47d60369061339d908b908b906004016156fc565b600060405180830381600087803b1580156133b757600080fd5b505af11580156133cb573d6000803e3d6000fd5b505050505b600098975050505050505050565b600960205281600052604060002081815481106133fa57600080fd5b6000918252602090912001546001600160a01b03169150829050565b600080546001600160a01b0316331461343c5761343560016006614516565b90506110aa565b6001600160a01b0383166000908152600a60205260409020805460ff166134715761346960096007614516565b9150506110aa565b60408051602080820183528582528251908101909252670c7d713b49da000082529061349f81835190511090565b156134ba576134b060066008614516565b93505050506110aa565b841580159061353657506004805460405163fc57d4df60e01b81526001600160a01b038981169382019390935291169063fc57d4df90602401602060405180830381865afa158015613510573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061353491906156cd565b155b15613547576134b0600d6009614516565b60018301805490869055604080516001600160a01b0389168152602081018390529081018790527f70483e6592cd5182d45ac970e05bc62cdcc90e9d8ef2c2dbe686cf383bcd7fc59060600160405180910390a16000979650505050505050565b61128e81600e80548060200260200160405190810160405280929190818152602001828054801561360257602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116135e4575b50505050506110b0565b60008061361a858585614957565b9050801561362957905061164c565b61363285614200565b61363c8585614378565b6005546001600160a01b0316156136b257600554604051631f916ef560e11b81526001600160a01b0390911690633f22ddea9061367f90889088906004016156fc565b600060405180830381600087803b15801561369957600080fd5b505af11580156136ad573d6000803e3d6000fd5b505050505b600095945050505050565b6040516361bfb47160e11b815233600482015260009082908290819081906001600160a01b0385169063c37f68e290602401608060405180830381865afa15801561370c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137309190615749565b50925092509250826000146137955760405162461bcd60e51b815260206004820152602560248201527f657869744d61726b65743a206765744163636f756e74536e617073686f742066604482015264185a5b195960da1b6064820152608401610d2e565b80156137b1576137a7600c6002614516565b9695505050505050565b60006137be873385614957565b905080156137de576137d3600e600383614b88565b979650505050505050565b6001600160a01b0385166000908152600a60209081526040808320338452600281019092529091205460ff1661381c57600098975050505050505050565b3360009081526002820160209081526040808320805460ff19169055600982528083208054825181850281018501909352808352919290919083018282801561388e57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311613870575b5050835193945083925060009150505b828110156138f357896001600160a01b03168482815181106138c2576138c2615593565b60200260200101516001600160a01b031614156138e1578091506138f3565b806138eb816155d6565b91505061389e565b5081811061390357613903615733565b33600090815260096020526040902080548190613922906001906155bf565b8154811061393257613932615593565b9060005260206000200160009054906101000a90046001600160a01b031681838154811061396257613962615593565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550808054806139a0576139a061577f565b600082815260209020810160001990810180546001600160a01b03191690550190556040517fe699a64c18b07ac5b7301aa273f36a2287239eb9501d81950672794afba29a0d906139f4908c9033906156fc565b60405180910390a160009c9b505050505050505050505050565b600061164c8284615795565b600061164c82846155bf565b6001600160a01b0382166000908152601260209081526040808320601a9092528220549091613a8b435b6040518060400160405280601c81526020017f626c6f636b206e756d6265722065786365656473203332206269747300000000815250614c00565b8354909150600090613aad9063ffffffff80851691600160e01b900416613a1a565b9050600081118015613abf5750600083115b15613bee576000613b31876001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa158015613b07573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b2b91906156cd565b87614c30565b90506000613b3f83866145c7565b90506000808311613b5f5760405180602001604052806000815250613b69565b613b698284614c4e565b604080516020810190915288546001600160e01b03168152909150613bcc90613b929083614c89565b5160408051808201909152601a81527f6e657720696e64657820657863656564732032323420626974730000000000006020820152614cb5565b6001600160e01b0316600160e01b63ffffffff87160217875550610670915050565b801561067057835463ffffffff8316600160e01b026001600160e01b03909116178455505050505050565b6001600160a01b03838116600090815260126020908152604080832080546014845282852095881685529490925290912080546001600160e01b0390931690819055909180158015613c7957506a0c097ce7bc90715b34b9f160241b8210155b15613c8f57506a0c097ce7bc90715b34b9f160241b5b60006040518060200160405280613ca68585613a1a565b90526040516395dd919360e01b81526001600160a01b038881166004830152919250600091613cf991908a16906395dd919390602401602060405180830381865afa158015613b07573d6000803e3d6000fd5b90506000613d078284614cdc565b6001600160a01b03891660009081526015602052604081205491925090613d2e9083613a0e565b6001600160a01b038a811660008181526015602090815260409182902085905581518781529081018b90529394509092918d16917f1fc3ecc087d8d2d15e23d0032af5a47059c3892d003d8e139fdcb6bb327c99a6910160405180910390a350505050505050505050565b600080546001600160a01b0316331480613dbd57506002546001600160a01b031633145b905090565b601e546040516370a0823160e01b81523060048201526000916001600160a01b031690829082906370a0823190602401602060405180830381865afa158015613e0f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e3391906156cd565b9050600084118015613e455750808411155b15613ec95760405163a9059cbb60e01b81526001600160a01b0386811660048301526024820186905283169063a9059cbb906044016020604051808303816000875af1158015613e99573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ebd9190615716565b506000925050506110aa565b50919392505050565b6000806000613edf614d72565b6001600160a01b038816600090815260096020908152604080832080548251818502810185019093528083528493830182828015613f4657602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311613f28575b5050505050905060005b81518110156141aa576000828281518110613f6d57613f6d615593565b60209081029190910101516040516361bfb47160e11b81526001600160a01b038e811660048301529192509082169063c37f68e290602401608060405180830381865afa158015613fc2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613fe69190615749565b6080890152606088015260408701529350831561401257600f600080975097509750505050505061187b565b60408051602080820183526001600160a01b038481166000818152600a845285902060010154845260c08a01939093528351808301855260808a0151815260e08a015260048054855163fc57d4df60e01b815291820194909452935192169263fc57d4df92602480830193928290030181865afa158015614097573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140bb91906156cd565b60a086018190526140db57600d600080975097509750505050505061187b565b604080516020810190915260a0860151815261010086015260c085015160e08601516141159161410a91614b06565b866101000151614b06565b61012086018190526040860151865161412f929190614d05565b85526101008501516060860151602087015161414c929190614d05565b60208601526001600160a01b03818116908c161415614197576141798561012001518b8760200151614d05565b60208601819052610100860151614191918b90614d05565b60208601525b50806141a2816155d6565b915050613f50565b506020830151835111156141db57602083015183516000916141cb916155bf565b600095509550955050505061187b565b600080846000015185602001516141f291906155bf565b95509550955050505061187b565b6001600160a01b0381166000908152601160209081526040808320601b909252822054909161422e43613a50565b83549091506000906142509063ffffffff80851691600160e01b900416613a1a565b90506000811180156142625750600083115b1561434e576000856001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156142a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142cb91906156cd565b905060006142d983866145c7565b905060008083116142f95760405180602001604052806000815250614303565b6143038284614c4e565b604080516020810190915288546001600160e01b0316815290915061432c90613b929083614c89565b6001600160e01b0316600160e01b63ffffffff87160217875550610582915050565b801561058257835463ffffffff8316600160e01b026001600160e01b039091161784555050505050565b6001600160a01b03828116600090815260116020908152604080832080546013845282852095871685529490925290912080546001600160e01b03909316908190559091801580156143d857506a0c097ce7bc90715b34b9f160241b8210155b156143ee57506a0c097ce7bc90715b34b9f160241b5b600060405180602001604052806144058585613a1a565b90526040516370a0823160e01b81526001600160a01b0387811660048301529192506000918816906370a0823190602401602060405180830381865afa158015614453573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061447791906156cd565b905060006144858284614cdc565b6001600160a01b038816600090815260156020526040812054919250906144ac9083613a0e565b6001600160a01b0389811660008181526015602090815260409182902085905581518781529081018b90529394509092918c16917f2caecd17d02f56fa897705dcc740da2d237c373f70686f4e0d9bd3bf0400ea7a910160405180910390a3505050505050505050565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa083601181111561454b5761454b6156e6565b83601481111561455d5761455d6156e6565b60408051928352602083019190915260009082015260600160405180910390a182601181111561164c5761164c6156e6565b60008060006145a2846000806000613ed2565b9250925092509193909250565b6000806145bc8484614d26565b90506113bd81614d4e565b600061164c82846157ad565b60005b600e5481101561466957816001600160a01b0316600e82815481106145fd576145fd615593565b6000918252602090912001546001600160a01b031614156146575760405162461bcd60e51b81526020600482015260146024820152731b585c9ad95d08185b1c9958591e48185919195960621b6044820152606401610d2e565b80614661816155d6565b9150506145d6565b50600e80546001810182556000919091527fbb7b4a454dc3493923482f07822329ed19e8244eff582cc204f8554c3620c3fd0180546001600160a01b0319166001600160a01b0392909216919091179055565b60006146c743613a50565b6001600160a01b03831660009081526011602090815260408083206012909252909120815492935090916001600160e01b031661471d5781546001600160e01b0319166a0c097ce7bc90715b34b9f160241b1782555b80546001600160e01b031661474b5780546001600160e01b0319166a0c097ce7bc90715b34b9f160241b1781555b805463ffffffff909316600160e01b026001600160e01b0393841681179091558154909216909117905550565b6001600160a01b0383166000908152600a60205260409020805460ff166147e15760405162461bcd60e51b815260206004820152601960248201527f636f6d70206d61726b6574206973206e6f74206c6973746564000000000000006044820152606401610d2e565b6001600160a01b0384166000908152601b6020526040902054831461485f5761480984614200565b6001600160a01b0384166000818152601b602052604090819020859055517fdeafccd0c0b768b2529f7dcbbe58e155d6023059150b7490ed4535cc3744b92d906148569086815260200190565b60405180910390a25b6001600160a01b0384166000908152601a602052604090205482146106565760006040518060200160405280866001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156148c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148ed91906156cd565b905290506148fb8582613a26565b6001600160a01b0385166000818152601a602052604090819020859055517f20af8e791cc98f74b2d7a391c80980ca8e5aebf3d4060bf581997b6acae2e537906149489086815260200190565b60405180910390a25050505050565b6001600160a01b0383166000908152600a602052604081205460ff1661497e576009611902565b6001600160a01b038085166000908152600a60209081526040808320938716835260029093019052205460ff166149b6576000611902565b6000806149c68587866000613ed2565b919350909150600090508260118111156149e2576149e26156e6565b14614a02578160118111156149f9576149f96156e6565b9250505061164c565b8015612f8c5760046149f9565b6001600160a01b0382166000908152600a60205260408120805460ff16614a3a5760099150506110aa565b6001600160a01b038316600090815260028201602052604090205460ff16151560011415614a6c5760009150506110aa565b6001600160a01b03838116600090815260028301602090815260408083208054600160ff19909116811790915560098352818420805491820181558452919092200180546001600160a01b03191692871692909217909155517f3ab23ab0d51cccc0c3085aec51f99228625aa1a922b3a8ca89a26b0f2027a1a590614af490869086906156fc565b60405180910390a15060009392505050565b6040805160208101909152600081526040518060200160405280670de0b6b3a7640000614b3b866000015186600001516145c7565b614b4591906157cc565b90529392505050565b6040805160208101909152600081526040518060200160405280614b45614b818660000151670de0b6b3a76400006145c7565b8551614d66565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0846011811115614bbd57614bbd6156e6565b846014811115614bcf57614bcf6156e6565b604080519283526020830191909152810184905260600160405180910390a18360118111156113bd576113bd6156e6565b6000816401000000008410614c285760405162461bcd60e51b8152600401610d2e91906157ee565b509192915050565b600061164c614c4784670de0b6b3a76400006145c7565b8351614d66565b6040805160208101909152600081526040518060200160405280614b45614c83866a0c097ce7bc90715b34b9f160241b6145c7565b85614d66565b6040805160208101909152600081526040518060200160405280614b4585600001518560000151613a0e565b600081600160e01b8410614c285760405162461bcd60e51b8152600401610d2e91906157ee565b60006a0c097ce7bc90715b34b9f160241b614cfb8484600001516145c7565b61164c91906157cc565b600080614d128585614d26565b9050611ebc614d2082614d4e565b84613a0e565b6040805160208101909152600081526040518060200160405280614b458560000151856145c7565b80516000906110aa90670de0b6b3a7640000906157cc565b600061164c82846157cc565b604051806101400160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001614dbe6040518060200160405280600081525090565b8152602001614dd96040518060200160405280600081525090565b8152602001614df46040518060200160405280600081525090565b8152602001614e0f6040518060200160405280600081525090565b905290565b60008083601f840112614e2657600080fd5b50813567ffffffffffffffff811115614e3e57600080fd5b6020830191508360208260051b8501011115614e5957600080fd5b9250929050565b60008060008060408587031215614e7657600080fd5b843567ffffffffffffffff80821115614e8e57600080fd5b614e9a88838901614e14565b90965094506020870135915080821115614eb357600080fd5b50614ec087828801614e14565b95989497509550505050565b6001600160a01b038116811461128e57600080fd5b801515811461128e57600080fd5b60008060408385031215614f0257600080fd5b8235614f0d81614ecc565b91506020830135614f1d81614ee1565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614f6757614f67614f28565b604052919050565b600067ffffffffffffffff821115614f8957614f89614f28565b5060051b60200190565b600082601f830112614fa457600080fd5b81356020614fb9614fb483614f6f565b614f3e565b82815260059290921b84018101918181019086841115614fd857600080fd5b8286015b84811015614ffc578035614fef81614ecc565b8352918301918301614fdc565b509695505050505050565b6000806040838503121561501a57600080fd5b823561502581614ecc565b9150602083013567ffffffffffffffff81111561504157600080fd5b61504d85828601614f93565b9150509250929050565b60006020828403121561506957600080fd5b813561164c81614ecc565b600080600080600060a0868803121561508c57600080fd5b853561509781614ecc565b945060208601356150a781614ecc565b935060408601356150b781614ecc565b94979396509394606081013594506080013592915050565b600080600080608085870312156150e557600080fd5b84356150f081614ecc565b9350602085013561510081614ecc565b9250604085013561511081614ecc565b9396929550929360600135925050565b6000806040838503121561513357600080fd5b823561513e81614ecc565b946020939093013593505050565b60006020828403121561515e57600080fd5b813561164c81614ee1565b60006020828403121561517b57600080fd5b5035919050565b6000806000806080858703121561519857600080fd5b84356151a381614ecc565b935060208501356151b381614ecc565b93969395505050506040820135916060013590565b60008060008060008060c087890312156151e157600080fd5b86356151ec81614ecc565b955060208701356151fc81614ecc565b9450604087013561520c81614ecc565b9350606087013561521c81614ecc565b9598949750929560808101359460a0909101359350915050565b60008060006060848603121561524b57600080fd5b833561525681614ecc565b9250602084013561526681614ecc565b929592945050506040919091013590565b600080600080600060a0868803121561528f57600080fd5b853561529a81614ecc565b945060208601356152aa81614ecc565b935060408601356152ba81614ecc565b925060608601356152ca81614ecc565b949793965091946080013592915050565b600082601f8301126152ec57600080fd5b813560206152fc614fb483614f6f565b82815260059290921b8401810191818101908684111561531b57600080fd5b8286015b84811015614ffc57803561533281614ecc565b835291830191830161531f565b6000806000806080858703121561535557600080fd5b843567ffffffffffffffff8082111561536d57600080fd5b615379888389016152db565b9550602087013591508082111561538f57600080fd5b5061539c87828801614f93565b93505060408501356153ad81614ee1565b915060608501356153bd81614ee1565b939692955090935050565b600080604083850312156153db57600080fd5b82356153e681614ecc565b91506020830135614f1d81614ecc565b600082601f83011261540757600080fd5b81356020615417614fb483614f6f565b82815260059290921b8401810191818101908684111561543657600080fd5b8286015b84811015614ffc578035835291830191830161543a565b60008060006060848603121561546657600080fd5b833567ffffffffffffffff8082111561547e57600080fd5b61548a87838801614f93565b945060208601359150808211156154a057600080fd5b6154ac878388016153f6565b935060408601359150808211156154c257600080fd5b506154cf868287016153f6565b9150509250925092565b6020808252825182820181905260009190848201906040850190845b8181101561551a5783516001600160a01b0316835292840192918401916001016154f5565b50909695505050505050565b60006020828403121561553857600080fd5b813567ffffffffffffffff81111561554f57600080fd5b6113bd848285016152db565b6020808252825182820181905260009190848201906040850190845b8181101561551a57835183529284019291840191600101615577565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000828210156155d1576155d16155a9565b500390565b60006000198214156155ea576155ea6155a9565b5060010190565b60208082526028908201527f63616e6e6f742070617573652061206d61726b65742074686174206973206e6f6040820152671d081b1a5cdd195960c21b606082015260800190565b60208082526027908201527f6f6e6c7920706175736520677561726469616e20616e642061646d696e2063616040820152666e20706175736560c81b606082015260800190565b6020808252601690820152756f6e6c792061646d696e2063616e20756e706175736560501b604082015260600190565b6000602082840312156156c257600080fd5b815161164c81614ecc565b6000602082840312156156df57600080fd5b5051919050565b634e487b7160e01b600052602160045260246000fd5b6001600160a01b0392831681529116602082015260400190565b60006020828403121561572857600080fd5b815161164c81614ee1565b634e487b7160e01b600052600160045260246000fd5b6000806000806080858703121561575f57600080fd5b505082516020840151604085015160609095015191969095509092509050565b634e487b7160e01b600052603160045260246000fd5b600082198211156157a8576157a86155a9565b500190565b60008160001904831182151516156157c7576157c76155a9565b500290565b6000826157e957634e487b7160e01b600052601260045260246000fd5b500490565b600060208083528351808285015260005b8181101561581b578581018301518582016040015282016157ff565b8181111561582d576000604083870101525b50601f01601f191692909201604001939250505056fea26469706673582212201f07597c60bee14114bc41513326bc40568abb29280b70a84ac674455c23b3ff64736f6c634300080a0033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106104ab5760003560e01c8063731f0c2b1161026d578063bb82aa5e11610151578063dce15449116100ce578063e9af029211610092578063e9af029214610c55578063eabe7d9114610c68578063ede4edd014610c7b578063f00a7a9214610c8e578063f4a433c014610c9b578063f851a44014610cbb57600080fd5b8063dce1544914610bff578063dcfbc0c714610c12578063e4028eee14610c25578063e6653f3d14610c38578063e875544614610c4c57600080fd5b8063ca0af04311610115578063ca0af04314610b7b578063cc7ebdc414610ba6578063cdd0404114610bc6578063d02f735114610bd9578063da3d454c14610bec57600080fd5b8063bb82aa5e14610aed578063bdcdc25814610b00578063bea6b8b814610b13578063c299823814610b33578063c488847b14610b5357600080fd5b806394b2294b116101ea578063a8b43948116101ae578063a8b4394814610a6a578063aa90075414610a7d578063abfceffc14610a86578063ac0b0bb714610aa6578063b0772d0b14610aba578063b21be7fd14610ac257600080fd5b806394b2294b146109f0578063986ab838146109f95780639d1b5a0a14610a19578063a76b3fda14610a2a578063a7f0e23114610a3d57600080fd5b80638c57804e116102315780638c57804e146108fe5780638e8f294b146109365780638ebf636414610989578063929fe9a11461099c57806394543c15146109dd57600080fd5b8063731f0c2b14610881578063741b2525146108a45780637dc0d1d0146108b757806385b7beb8146108ca57806387f76303146108ea57600080fd5b80634a584432116103945780635e2c2a3b116103115780636810dfa6116102d55780636810dfa6146107b35780636a56947e146107c65780636aa875b5146107d45780636b79c38d146107f45780636d154ea5146108505780636d35bf911461087357600080fd5b80635e2c2a3b146107545780635ec88c79146107675780635f5af1aa1461077a5780635fc7e71e1461078d578063607ef6c1146107a057600080fd5b806351dff9891161035857806351dff989146106f557806352d84d1e1461070857806355ee1fe11461071b578063598ee1cb1461072e5780635c7786051461074157600080fd5b80634a584432146106785780634ada90af146106985780634e79238f146106a15780634ef4c3e1146106cf5780634fd42e17146106e257600080fd5b806324a3d6221161042d578063391957d7116103f1578063391957d71461060e5780633bcf7ec1146106215780633c94786f1461063457806341c728b91461064857806342cbb15c1461065c57806347ef3b3b1461066257600080fd5b806324a3d622146105af57806326782247146105c257806327efe3cb146105d55780632d70db78146105e8578063317b0b77146105fb57600080fd5b80631d504dc6116104745780631d504dc6146105335780631d7b33d7146105465780631ededc911461057457806321af45691461058957806324008a621461059c57600080fd5b80627e3dd2146104b057806316b95e8f146104cd57806318c882a5146104e25780631c3db2e0146104f55780631d4632ac14610508575b600080fd5b6104b8600181565b60405190151581526020015b60405180910390f35b6104e06104db366004614e60565b610cce565b005b6104b86104f0366004614eef565b610f77565b6104e0610503366004615007565b6110b0565b60055461051b906001600160a01b031681565b6040516001600160a01b0390911681526020016104c4565b6104e0610541366004615057565b611113565b610566610554366004615057565b60106020526000908152604090205481565b6040519081526020016104c4565b6104e0610582366004615074565b5050505050565b60165461051b906001600160a01b031681565b6105666105aa3660046150cf565b611291565b600b5461051b906001600160a01b031681565b60015461051b906001600160a01b031681565b6104e06105e3366004615120565b6113c5565b6104b86105f636600461514c565b6114bc565b610566610609366004615169565b6115ac565b6104e061061c366004615057565b611653565b6104b861062f366004614eef565b61171b565b600b546104b890600160a01b900460ff1681565b6104e0610656366004615182565b50505050565b43610566565b6104e06106703660046151c8565b505050505050565b610566610686366004615057565b60176020526000908152604090205481565b61056660075481565b6106b46106af366004615182565b611845565b604080519384526020840192909252908201526060016104c4565b6105666106dd366004615236565b611885565b6105666106f0366004615169565b61199c565b6104e0610703366004615182565b6119f9565b61051b610716366004615169565b611a48565b610566610729366004615057565b611a72565b6104e061073c366004615120565b611ae4565b6104e061074f366004615236565b505050565b610566610762366004615057565b611bd8565b6106b4610775366004615057565b611c4a565b610566610788366004615057565b611c85565b61056661079b366004615277565b611cf6565b6104e06107ae366004614e60565b611ec5565b6104e06107c136600461533f565b6120a3565b6104e06106563660046150cf565b6105666107e2366004615057565b601b6020526000908152604090205481565b61082c610802366004615057565b6011602052600090815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff9091166020830152016104c4565b6104b861085e366004615057565b600d6020526000908152604090205460ff1681565b6104e0610582366004615277565b6104b861088f366004615057565b600c6020526000908152604090205460ff1681565b6104e06108b2366004615057565b61232d565b60045461051b906001600160a01b031681565b6105666108d8366004615057565b601d6020526000908152604090205481565b600b546104b890600160b01b900460ff1681565b61082c61090c366004615057565b6012602052600090815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b61096a610944366004615057565b600a6020526000908152604090208054600182015460039092015460ff91821692911683565b60408051931515845260208401929092521515908201526060016104c4565b6104b861099736600461514c565b6123d9565b6104b86109aa3660046153c8565b6001600160a01b038082166000908152600a60209081526040808320938616835260029093019052205460ff1692915050565b6104b86109eb366004615057565b6124c0565b61056660085481565b610566610a07366004615057565b60186020526000908152604090205481565b601e546001600160a01b031661051b565b610566610a38366004615057565b61257f565b610a526a0c097ce7bc90715b34b9f160241b81565b6040516001600160e01b0390911681526020016104c4565b6104e0610a78366004615451565b6126b1565b610566600f5481565b610a99610a94366004615057565b6127e6565b6040516104c491906154d9565b600b546104b890600160b81b900460ff1681565b610a9961285c565b610566610ad03660046153c8565b601360209081526000928352604080842090915290825290205481565b60025461051b906001600160a01b031681565b610566610b0e3660046150cf565b6128be565b610566610b21366004615057565b60196020526000908152604090205481565b610b46610b41366004615526565b6129f0565b6040516104c4919061555b565b610b66610b61366004615236565b612ab8565b604080519283526020830191909152016104c4565b610566610b893660046153c8565b601460209081526000928352604080842090915290825290205481565b610566610bb4366004615057565b60156020526000908152604090205481565b610566610bd4366004615057565b612cd6565b610566610be7366004615277565b612d17565b610566610bfa366004615236565b612f98565b61051b610c0d366004615120565b6133de565b60035461051b906001600160a01b031681565b610566610c33366004615120565b613416565b600b546104b890600160a81b900460ff1681565b61056660065481565b6104e0610c63366004615057565b6135a8565b610566610c76366004615236565b61360c565b610566610c89366004615057565b6136bd565b601c546104b89060ff1681565b610566610ca9366004615057565b601a6020526000908152604090205481565b60005461051b906001600160a01b031681565b6000546001600160a01b03163314610d375760405162461bcd60e51b815260206004820152602160248201527f4f6e6c792061646d696e2063616e2063616c6c20746869732066756e6374696f6044820152603760f91b60648201526084015b60405180910390fd5b601c5460ff1615610d995760405162461bcd60e51b815260206004820152602660248201527f416c72656164792065786563757465642074686973206f6e652d6f66662066756044820152653731ba34b7b760d11b6064820152608401610d2e565b828114610dd85760405162461bcd60e51b815260206004820152600d60248201526c125b9d985b1a59081a5b9c1d5d609a1b6044820152606401610d2e565b60008060008060005b87811015610f5f57888882818110610dfb57610dfb615593565b9050602002016020810190610e109190615057565b6001600160a01b0381166000908152601560205260409020549095509350868682818110610e4057610e40615593565b90506020020135925083831115610ee4576000610e5d85856155bf565b6001600160a01b0387166000908152601d6020526040812054919250610e838284613a0e565b6001600160a01b0389166000818152601d6020908152604091829020849055815186815290810184905292935090917f17fea09d9a7ca41b2f9f9118f18f44848a62e9c70d55dd4385131eb2cf1b7e47910160405180910390a28695505050505b8215610f4f57610ef48484613a1a565b6001600160a01b038616600081815260156020908152604091829020849055815188815290810184905292945090917f4a5c134e28b537a76546993ea37f3b60d9190476df7356d3842aa40902e20f04910160405180910390a25b610f58816155d6565b9050610de1565b5050601c805460ff1916600117905550505050505050565b6001600160a01b0382166000908152600a602052604081205460ff16610faf5760405162461bcd60e51b8152600401610d2e906155f1565b600b546001600160a01b0316331480610fd257506000546001600160a01b031633145b610fee5760405162461bcd60e51b8152600401610d2e90615639565b6000546001600160a01b031633148061100957506001821515145b6110255760405162461bcd60e51b8152600401610d2e90615680565b6001600160a01b0383166000818152600d6020908152604091829020805460ff19168615159081179091558251938452606091840182905260069184019190915265426f72726f7760d01b6080840152908201527f71aec636243f9709bb0007ae15e9afb8150ab01716d75fd7573be5cc096e03b09060a0015b60405180910390a150805b92915050565b6040805160018082528183019092526000916020808301908036833701905050905082816000815181106110e6576110e6615593565b60200260200101906001600160a01b031690816001600160a01b03168152505061074f81836001806120a3565b806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa158015611151573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061117591906156b0565b6001600160a01b0316336001600160a01b0316146111e55760405162461bcd60e51b815260206004820152602760248201527f6f6e6c7920756e6974726f6c6c65722061646d696e2063616e206368616e676560448201526620627261696e7360c81b6064820152608401610d2e565b806001600160a01b031663c1e803346040518163ffffffff1660e01b81526004016020604051808303816000875af1158015611225573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061124991906156cd565b1561128e5760405162461bcd60e51b815260206004820152601560248201527418da185b99d9481b9bdd08185d5d1a1bdc9a5e9959605a1b6044820152606401610d2e565b50565b6001600160a01b0384166000908152600a602052604081205460ff166112b9575060096113bd565b60006040518060200160405280876001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611304573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061132891906156cd565b905290506113368682613a26565b611341868583613c19565b6005546001600160a01b0316156113b75760055460405163623eb01b60e11b81526001600160a01b039091169063c47d60369061138490899088906004016156fc565b600060405180830381600087803b15801561139e57600080fd5b505af11580156113b2573d6000803e3d6000fd5b505050505b60009150505b949350505050565b6113cd613d99565b6114195760405162461bcd60e51b815260206004820152601960248201527f6f6e6c792061646d696e2063616e206772616e7420636f6d70000000000000006044820152606401610d2e565b60006114258383613dc2565b905080156114755760405162461bcd60e51b815260206004820152601b60248201527f696e73756666696369656e7420636f6d7020666f72206772616e7400000000006044820152606401610d2e565b604080516001600160a01b0385168152602081018490527f98b2f82a3a07f223a0be64b3d0f47711c64dccd1feafb94aa28156b38cd9695c910160405180910390a1505050565b600b546000906001600160a01b03163314806114e257506000546001600160a01b031633145b6114fe5760405162461bcd60e51b8152600401610d2e90615639565b6000546001600160a01b031633148061151957506001821515145b6115355760405162461bcd60e51b8152600401610d2e90615680565b600b8054831515600160b81b0260ff60b81b199091161790556040517fef159d9a32b2472e32b098f954f3ce62d232939f1c207070b584df1814de2de0906115a09084906040808252600590820152645365697a6560d81b6060820152901515602082015260800190565b60405180910390a15090565b600080546001600160a01b031633146116075760405162461bcd60e51b815260206004820152601f60248201527f6f6e6c792061646d696e2063616e2073657420636c6f736520666163746f72006044820152606401610d2e565b600680549083905560408051828152602081018590527f3b9670cf975d26958e754b57098eaa2ac914d8d2a31b83257997b9f346110fd991015b60405180910390a160005b9392505050565b6000546001600160a01b031633146116bc5760405162461bcd60e51b815260206004820152602660248201527f6f6e6c792061646d696e2063616e2073657420626f72726f772063617020677560448201526530b93234b0b760d11b6064820152608401610d2e565b601680546001600160a01b038381166001600160a01b03198316179092556040519116907feda98690e518e9a05f8ec6837663e188211b2da8f4906648b323f2c1d4434e299061170f90839085906156fc565b60405180910390a15050565b6001600160a01b0382166000908152600a602052604081205460ff166117535760405162461bcd60e51b8152600401610d2e906155f1565b600b546001600160a01b031633148061177657506000546001600160a01b031633145b6117925760405162461bcd60e51b8152600401610d2e90615639565b6000546001600160a01b03163314806117ad57506001821515145b6117c95760405162461bcd60e51b8152600401610d2e90615680565b6001600160a01b0383166000818152600c6020908152604091829020805460ff19168615159081179091558251938452606091840182905260049184019190915263135a5b9d60e21b6080840152908201527f71aec636243f9709bb0007ae15e9afb8150ab01716d75fd7573be5cc096e03b09060a00161109f565b60008060008060008061185a8a8a8a8a613ed2565b925092509250826011811115611872576118726156e6565b95509093509150505b9450945094915050565b6001600160a01b0383166000908152600c602052604081205460ff16156118df5760405162461bcd60e51b815260206004820152600e60248201526d1b5a5b9d081a5cc81c185d5cd95960921b6044820152606401610d2e565b6001600160a01b0384166000908152600a602052604090205460ff166119095760095b905061164c565b61191284614200565b61191c8484614378565b6005546001600160a01b03161561199257600554604051631f916ef560e11b81526001600160a01b0390911690633f22ddea9061195f90879087906004016156fc565b600060405180830381600087803b15801561197957600080fd5b505af115801561198d573d6000803e3d6000fd5b505050505b6000949350505050565b600080546001600160a01b031633146119bb576110aa6001600b614516565b600780549083905560408051828152602081018590527faeba5a6c40a8ac138134bff1aaa65debf25971188a58804bad717f82f0ec13169101611641565b80158015611a075750600082115b156106565760405162461bcd60e51b815260206004820152601160248201527072656465656d546f6b656e73207a65726f60781b6044820152606401610d2e565b600e8181548110611a5857600080fd5b6000918252602090912001546001600160a01b0316905081565b600080546001600160a01b03163314611a91576110aa60016010614516565b600480546001600160a01b038481166001600160a01b03198316179092556040519116907fd52b2b9b7e9ee655fcb95d2e5b9e0c9f69e7ef2b8e9d2d0ea78402d576d22e229061164190839086906156fc565b611aec613d99565b611b385760405162461bcd60e51b815260206004820152601d60248201527f6f6e6c792061646d696e2063616e2073657420636f6d702073706565640000006044820152606401610d2e565b611b418261232d565b80611b64576001600160a01b038216600090815260196020526040812055611b7f565b436001600160a01b0383166000908152601960205260409020555b6001600160a01b03821660008181526018602052604090819020839055517f386537fa92edc3319af95f1f904dcf1900021e4f3f4e08169a577a09076e66b390611bcc9084815260200190565b60405180910390a25050565b600080546001600160a01b03163314611bf7576110aa60016014614516565b600580546001600160a01b038481166001600160a01b03198316179092556040519116907fbd182757c0006b9842c613e7591cf5a9ea286903d8bca3413df7299b7f43517e9061164190839086906156fc565b600080600080600080611c61876000806000613ed2565b925092509250826011811115611c7957611c796156e6565b97919650945092505050565b600080546001600160a01b03163314611ca4576110aa60016013614516565b600b80546001600160a01b038481166001600160a01b0319831681179093556040519116917f0613b6ee6a04f0d09f390e4d9318894b9f6ac7fd83897cd8d18896ba579c401e916116419184916156fc565b6001600160a01b0385166000908152600a602052604081205460ff161580611d3757506001600160a01b0385166000908152600a602052604090205460ff16155b15611d465760095b9050611ebc565b6040516395dd919360e01b81526001600160a01b038481166004830152600091908816906395dd919390602401602060405180830381865afa158015611d90573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611db491906156cd565b9050611dbf876124c0565b15611e2a5782811015611e255760405162461bcd60e51b815260206004820152602860248201527f43616e206e6f74207265706179206d6f7265207468616e2074686520746f74616044820152676c20626f72726f7760c01b6064820152608401610d2e565b611eb6565b600080611e368661458f565b91935090915060009050826011811115611e5257611e526156e6565b14611e7357816011811115611e6957611e696156e6565b9350505050611ebc565b80611e7f576003611e69565b6000611e9b6040518060200160405280600654815250856145af565b905080861115611eb2576011945050505050611ebc565b5050505b60009150505b95945050505050565b6000546001600160a01b0316331480611ee857506016546001600160a01b031633145b611f525760405162461bcd60e51b815260206004820152603560248201527f6f6e6c792061646d696e206f7220626f72726f772063617020677561726469616044820152746e2063616e2073657420626f72726f77206361707360581b6064820152608401610d2e565b82818115801590611f6257508082145b611f9e5760405162461bcd60e51b815260206004820152600d60248201526c1a5b9d985b1a59081a5b9c1d5d609a1b6044820152606401610d2e565b60005b8281101561209a57848482818110611fbb57611fbb615593565b9050602002013560176000898985818110611fd857611fd8615593565b9050602002016020810190611fed9190615057565b6001600160a01b0316815260208101919091526040016000205586868281811061201957612019615593565b905060200201602081019061202e9190615057565b6001600160a01b03167f6f1951b2aad10f3fc81b86d91105b413a5b3f847a34bbc5ce1904201b14438f686868481811061206a5761206a615593565b9050602002013560405161208091815260200190565b60405180910390a280612092816155d6565b915050611fa1565b50505050505050565b60005b835181101561226a5760008482815181106120c3576120c3615593565b6020908102919091018101516001600160a01b0381166000908152600a90925260409091205490915060ff166121335760405162461bcd60e51b81526020600482015260156024820152741b585c9ad95d081b5d5cdd081899481b1a5cdd1959605a1b6044820152606401610d2e565b600184151514156122005760006040518060200160405280836001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612189573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ad91906156cd565b905290506121bb8282613a26565b60005b87518110156121fd576121eb838983815181106121dd576121dd615593565b602002602001015184613c19565b806121f5816155d6565b9150506121be565b50505b600183151514156122575761221481614200565b60005b8651811015612255576122438288838151811061223657612236615593565b6020026020010151614378565b8061224d816155d6565b915050612217565b505b5080612262816155d6565b9150506120a6565b5060005b8451811015610582576122d885828151811061228c5761228c615593565b6020026020010151601560008885815181106122aa576122aa615593565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054613dc2565b601560008784815181106122ee576122ee615593565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020819055508080612325906155d6565b91505061226e565b6001600160a01b038116600090815260186020908152604080832054601990925282205490914391612360908390613a1a565b90506000811180156123725750600083115b1561065657600061238382856145c7565b6001600160a01b038616600090815260156020526040812054919250906123aa9083613a0e565b6001600160a01b0387166000908152601560209081526040808320939093556019905220849055505050505050565b600b546000906001600160a01b03163314806123ff57506000546001600160a01b031633145b61241b5760405162461bcd60e51b8152600401610d2e90615639565b6000546001600160a01b031633148061243657506001821515145b6124525760405162461bcd60e51b8152600401610d2e90615680565b600b8054831515600160b01b0260ff60b01b199091161790556040517fef159d9a32b2472e32b098f954f3ce62d232939f1c207070b584df1814de2de0906115a09084906040808252600890820152672a3930b739b332b960c11b6060820152901515602082015260800190565b6001600160a01b0381166000908152600a602052604081206001015415801561250657506001600160a01b0382166000908152600d602052604090205460ff1615156001145b80156110aa5750816001600160a01b031663173b99046040518163ffffffff1660e01b8152600401602060405180830381865afa15801561254b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061256f91906156cd565b670de0b6b3a76400001492915050565b600080546001600160a01b0316331461259e576110aa60016012614516565b6001600160a01b0382166000908152600a602052604090205460ff16156125cb576110aa600a6011614516565b816001600160a01b031663fe9c44ae6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612609573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061262d9190615716565b506001600160a01b0382166000908152600a602052604081208054600160ff199182168117835560038301805490921690915581019190915561266f836145d3565b612678836146bc565b6040516001600160a01b03841681527fcf583bb0c569eb967f806b11601c4cb93c10310485c67add5f8362c2f212321f90602001611641565b6126b9613d99565b6127055760405162461bcd60e51b815260206004820152601d60248201527f6f6e6c792061646d696e2063616e2073657420636f6d702073706565640000006044820152606401610d2e565b82518251811480156127175750815181145b6127755760405162461bcd60e51b815260206004820152602960248201527f436f6d7074726f6c6c65723a3a5f736574436f6d7053706565647320696e76616044820152681b1a59081a5b9c1d5d60ba1b6064820152608401610d2e565b60005b81811015610582576127d685828151811061279557612795615593565b60200260200101518583815181106127af576127af615593565b60200260200101518584815181106127c9576127c9615593565b6020026020010151614778565b6127df816155d6565b9050612778565b6001600160a01b038116600090815260096020908152604080832080548251818502810185019093528083526060949383018282801561284f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612831575b5093979650505050505050565b6060600e8054806020026020016040519081016040528092919081815260200182805480156128b457602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612896575b5050505050905090565b600b54600090600160b01b900460ff16156129105760405162461bcd60e51b81526020600482015260126024820152711d1c985b9cd9995c881a5cc81c185d5cd95960721b6044820152606401610d2e565b600061291d868685614957565b9050801561292c5790506113bd565b61293586614200565b61293f8686614378565b6129498685614378565b6005546001600160a01b0316156113b757600554604051631f916ef560e11b81526001600160a01b0390911690633f22ddea9061298c90899089906004016156fc565b600060405180830381600087803b1580156129a657600080fd5b505af11580156129ba573d6000803e3d6000fd5b5050600554604051631f916ef560e11b81526001600160a01b039091169250633f22ddea915061138490899088906004016156fc565b805160609060008167ffffffffffffffff811115612a1057612a10614f28565b604051908082528060200260200182016040528015612a39578160200160208202803683370190505b50905060005b82811015612ab0576000858281518110612a5b57612a5b615593565b60200260200101519050612a6f8133614a0f565b6011811115612a8057612a806156e6565b838381518110612a9257612a92615593565b60209081029190910101525080612aa8816155d6565b915050612a3f565b509392505050565b6004805460405163fc57d4df60e01b81526001600160a01b03868116938201939093526000928392839291169063fc57d4df90602401602060405180830381865afa158015612b0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b2f91906156cd565b6004805460405163fc57d4df60e01b81526001600160a01b038981169382019390935292935060009291169063fc57d4df90602401602060405180830381865afa158015612b81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ba591906156cd565b9050811580612bb2575080155b15612bc657600d6000935093505050612cce565b6000866001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c06573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c2a91906156cd565b90506000612c446040518060200160405280600081525090565b604080516020808201835260008083528351808301855290815283518083018552600754815284519283019094528882529192612c8091614b06565b9250612ca8604051806020016040528088815250604051806020016040528088815250614b06565b9150612cb48383614b4e565b9050612cc0818b6145af565b600099509750505050505050505b935093915050565b600080546001600160a01b03163314612cf5576110aa60016010614516565b601e80546001600160a01b0319166001600160a01b03841617905560006110aa565b600b54600090600160b81b900460ff1615612d665760405162461bcd60e51b815260206004820152600f60248201526e1cd95a5e99481a5cc81c185d5cd959608a1b6044820152606401610d2e565b6001600160a01b0386166000908152600a602052604090205460ff161580612da757506001600160a01b0385166000908152600a602052604090205460ff16155b15612db3576009611d3f565b846001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612df1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e1591906156b0565b6001600160a01b0316866001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612e5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e8091906156b0565b6001600160a01b031614612e95576002611d3f565b612e9e86614200565b612ea88684614378565b612eb28685614378565b6005546001600160a01b031615612f8c57600554604051631f916ef560e11b81526001600160a01b0390911690633f22ddea90612ef590899087906004016156fc565b600060405180830381600087803b158015612f0f57600080fd5b505af1158015612f23573d6000803e3d6000fd5b5050600554604051631f916ef560e11b81526001600160a01b039091169250633f22ddea9150612f5990899088906004016156fc565b600060405180830381600087803b158015612f7357600080fd5b505af1158015612f87573d6000803e3d6000fd5b505050505b60009695505050505050565b6001600160a01b0383166000908152600d602052604081205460ff1615612ff45760405162461bcd60e51b815260206004820152601060248201526f189bdc9c9bddc81a5cc81c185d5cd95960821b6044820152606401610d2e565b6001600160a01b0384166000908152600a602052604090205460ff1661301b576009611902565b6001600160a01b038085166000908152600a60209081526040808320938716835260029093019052205460ff1661311857336001600160a01b0385161461309c5760405162461bcd60e51b815260206004820152601560248201527439b2b73232b91036bab9ba1031329031aa37b5b2b760591b6044820152606401610d2e565b60006130a83385614a0f565b905060008160118111156130be576130be6156e6565b146130dd578060118111156130d5576130d56156e6565b91505061164c565b6001600160a01b038086166000908152600a60209081526040808320938816835260029093019052205460ff1661311657613116615733565b505b6004805460405163fc57d4df60e01b81526001600160a01b038781169382019390935291169063fc57d4df90602401602060405180830381865afa158015613164573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061318891906156cd565b61319357600d611902565b6001600160a01b0384166000908152601760205260409020548015613278576000856001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa1580156131f2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061321691906156cd565b905060006132248286613a0e565b90508281106132755760405162461bcd60e51b815260206004820152601960248201527f6d61726b657420626f72726f77206361702072656163686564000000000000006044820152606401610d2e565b50505b6000806132888688600088613ed2565b919350909150600090508260118111156132a4576132a46156e6565b146132c5578160118111156132bb576132bb6156e6565b935050505061164c565b80156132d25760046132bb565b60006040518060200160405280896001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561331d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061334191906156cd565b9052905061334f8882613a26565b61335a888883613c19565b6005546001600160a01b0316156133d05760055460405163623eb01b60e11b81526001600160a01b039091169063c47d60369061339d908b908b906004016156fc565b600060405180830381600087803b1580156133b757600080fd5b505af11580156133cb573d6000803e3d6000fd5b505050505b600098975050505050505050565b600960205281600052604060002081815481106133fa57600080fd5b6000918252602090912001546001600160a01b03169150829050565b600080546001600160a01b0316331461343c5761343560016006614516565b90506110aa565b6001600160a01b0383166000908152600a60205260409020805460ff166134715761346960096007614516565b9150506110aa565b60408051602080820183528582528251908101909252670c7d713b49da000082529061349f81835190511090565b156134ba576134b060066008614516565b93505050506110aa565b841580159061353657506004805460405163fc57d4df60e01b81526001600160a01b038981169382019390935291169063fc57d4df90602401602060405180830381865afa158015613510573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061353491906156cd565b155b15613547576134b0600d6009614516565b60018301805490869055604080516001600160a01b0389168152602081018390529081018790527f70483e6592cd5182d45ac970e05bc62cdcc90e9d8ef2c2dbe686cf383bcd7fc59060600160405180910390a16000979650505050505050565b61128e81600e80548060200260200160405190810160405280929190818152602001828054801561360257602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116135e4575b50505050506110b0565b60008061361a858585614957565b9050801561362957905061164c565b61363285614200565b61363c8585614378565b6005546001600160a01b0316156136b257600554604051631f916ef560e11b81526001600160a01b0390911690633f22ddea9061367f90889088906004016156fc565b600060405180830381600087803b15801561369957600080fd5b505af11580156136ad573d6000803e3d6000fd5b505050505b600095945050505050565b6040516361bfb47160e11b815233600482015260009082908290819081906001600160a01b0385169063c37f68e290602401608060405180830381865afa15801561370c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137309190615749565b50925092509250826000146137955760405162461bcd60e51b815260206004820152602560248201527f657869744d61726b65743a206765744163636f756e74536e617073686f742066604482015264185a5b195960da1b6064820152608401610d2e565b80156137b1576137a7600c6002614516565b9695505050505050565b60006137be873385614957565b905080156137de576137d3600e600383614b88565b979650505050505050565b6001600160a01b0385166000908152600a60209081526040808320338452600281019092529091205460ff1661381c57600098975050505050505050565b3360009081526002820160209081526040808320805460ff19169055600982528083208054825181850281018501909352808352919290919083018282801561388e57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311613870575b5050835193945083925060009150505b828110156138f357896001600160a01b03168482815181106138c2576138c2615593565b60200260200101516001600160a01b031614156138e1578091506138f3565b806138eb816155d6565b91505061389e565b5081811061390357613903615733565b33600090815260096020526040902080548190613922906001906155bf565b8154811061393257613932615593565b9060005260206000200160009054906101000a90046001600160a01b031681838154811061396257613962615593565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550808054806139a0576139a061577f565b600082815260209020810160001990810180546001600160a01b03191690550190556040517fe699a64c18b07ac5b7301aa273f36a2287239eb9501d81950672794afba29a0d906139f4908c9033906156fc565b60405180910390a160009c9b505050505050505050505050565b600061164c8284615795565b600061164c82846155bf565b6001600160a01b0382166000908152601260209081526040808320601a9092528220549091613a8b435b6040518060400160405280601c81526020017f626c6f636b206e756d6265722065786365656473203332206269747300000000815250614c00565b8354909150600090613aad9063ffffffff80851691600160e01b900416613a1a565b9050600081118015613abf5750600083115b15613bee576000613b31876001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa158015613b07573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b2b91906156cd565b87614c30565b90506000613b3f83866145c7565b90506000808311613b5f5760405180602001604052806000815250613b69565b613b698284614c4e565b604080516020810190915288546001600160e01b03168152909150613bcc90613b929083614c89565b5160408051808201909152601a81527f6e657720696e64657820657863656564732032323420626974730000000000006020820152614cb5565b6001600160e01b0316600160e01b63ffffffff87160217875550610670915050565b801561067057835463ffffffff8316600160e01b026001600160e01b03909116178455505050505050565b6001600160a01b03838116600090815260126020908152604080832080546014845282852095881685529490925290912080546001600160e01b0390931690819055909180158015613c7957506a0c097ce7bc90715b34b9f160241b8210155b15613c8f57506a0c097ce7bc90715b34b9f160241b5b60006040518060200160405280613ca68585613a1a565b90526040516395dd919360e01b81526001600160a01b038881166004830152919250600091613cf991908a16906395dd919390602401602060405180830381865afa158015613b07573d6000803e3d6000fd5b90506000613d078284614cdc565b6001600160a01b03891660009081526015602052604081205491925090613d2e9083613a0e565b6001600160a01b038a811660008181526015602090815260409182902085905581518781529081018b90529394509092918d16917f1fc3ecc087d8d2d15e23d0032af5a47059c3892d003d8e139fdcb6bb327c99a6910160405180910390a350505050505050505050565b600080546001600160a01b0316331480613dbd57506002546001600160a01b031633145b905090565b601e546040516370a0823160e01b81523060048201526000916001600160a01b031690829082906370a0823190602401602060405180830381865afa158015613e0f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e3391906156cd565b9050600084118015613e455750808411155b15613ec95760405163a9059cbb60e01b81526001600160a01b0386811660048301526024820186905283169063a9059cbb906044016020604051808303816000875af1158015613e99573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ebd9190615716565b506000925050506110aa565b50919392505050565b6000806000613edf614d72565b6001600160a01b038816600090815260096020908152604080832080548251818502810185019093528083528493830182828015613f4657602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311613f28575b5050505050905060005b81518110156141aa576000828281518110613f6d57613f6d615593565b60209081029190910101516040516361bfb47160e11b81526001600160a01b038e811660048301529192509082169063c37f68e290602401608060405180830381865afa158015613fc2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613fe69190615749565b6080890152606088015260408701529350831561401257600f600080975097509750505050505061187b565b60408051602080820183526001600160a01b038481166000818152600a845285902060010154845260c08a01939093528351808301855260808a0151815260e08a015260048054855163fc57d4df60e01b815291820194909452935192169263fc57d4df92602480830193928290030181865afa158015614097573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140bb91906156cd565b60a086018190526140db57600d600080975097509750505050505061187b565b604080516020810190915260a0860151815261010086015260c085015160e08601516141159161410a91614b06565b866101000151614b06565b61012086018190526040860151865161412f929190614d05565b85526101008501516060860151602087015161414c929190614d05565b60208601526001600160a01b03818116908c161415614197576141798561012001518b8760200151614d05565b60208601819052610100860151614191918b90614d05565b60208601525b50806141a2816155d6565b915050613f50565b506020830151835111156141db57602083015183516000916141cb916155bf565b600095509550955050505061187b565b600080846000015185602001516141f291906155bf565b95509550955050505061187b565b6001600160a01b0381166000908152601160209081526040808320601b909252822054909161422e43613a50565b83549091506000906142509063ffffffff80851691600160e01b900416613a1a565b90506000811180156142625750600083115b1561434e576000856001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156142a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142cb91906156cd565b905060006142d983866145c7565b905060008083116142f95760405180602001604052806000815250614303565b6143038284614c4e565b604080516020810190915288546001600160e01b0316815290915061432c90613b929083614c89565b6001600160e01b0316600160e01b63ffffffff87160217875550610582915050565b801561058257835463ffffffff8316600160e01b026001600160e01b039091161784555050505050565b6001600160a01b03828116600090815260116020908152604080832080546013845282852095871685529490925290912080546001600160e01b03909316908190559091801580156143d857506a0c097ce7bc90715b34b9f160241b8210155b156143ee57506a0c097ce7bc90715b34b9f160241b5b600060405180602001604052806144058585613a1a565b90526040516370a0823160e01b81526001600160a01b0387811660048301529192506000918816906370a0823190602401602060405180830381865afa158015614453573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061447791906156cd565b905060006144858284614cdc565b6001600160a01b038816600090815260156020526040812054919250906144ac9083613a0e565b6001600160a01b0389811660008181526015602090815260409182902085905581518781529081018b90529394509092918c16917f2caecd17d02f56fa897705dcc740da2d237c373f70686f4e0d9bd3bf0400ea7a910160405180910390a3505050505050505050565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa083601181111561454b5761454b6156e6565b83601481111561455d5761455d6156e6565b60408051928352602083019190915260009082015260600160405180910390a182601181111561164c5761164c6156e6565b60008060006145a2846000806000613ed2565b9250925092509193909250565b6000806145bc8484614d26565b90506113bd81614d4e565b600061164c82846157ad565b60005b600e5481101561466957816001600160a01b0316600e82815481106145fd576145fd615593565b6000918252602090912001546001600160a01b031614156146575760405162461bcd60e51b81526020600482015260146024820152731b585c9ad95d08185b1c9958591e48185919195960621b6044820152606401610d2e565b80614661816155d6565b9150506145d6565b50600e80546001810182556000919091527fbb7b4a454dc3493923482f07822329ed19e8244eff582cc204f8554c3620c3fd0180546001600160a01b0319166001600160a01b0392909216919091179055565b60006146c743613a50565b6001600160a01b03831660009081526011602090815260408083206012909252909120815492935090916001600160e01b031661471d5781546001600160e01b0319166a0c097ce7bc90715b34b9f160241b1782555b80546001600160e01b031661474b5780546001600160e01b0319166a0c097ce7bc90715b34b9f160241b1781555b805463ffffffff909316600160e01b026001600160e01b0393841681179091558154909216909117905550565b6001600160a01b0383166000908152600a60205260409020805460ff166147e15760405162461bcd60e51b815260206004820152601960248201527f636f6d70206d61726b6574206973206e6f74206c6973746564000000000000006044820152606401610d2e565b6001600160a01b0384166000908152601b6020526040902054831461485f5761480984614200565b6001600160a01b0384166000818152601b602052604090819020859055517fdeafccd0c0b768b2529f7dcbbe58e155d6023059150b7490ed4535cc3744b92d906148569086815260200190565b60405180910390a25b6001600160a01b0384166000908152601a602052604090205482146106565760006040518060200160405280866001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156148c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148ed91906156cd565b905290506148fb8582613a26565b6001600160a01b0385166000818152601a602052604090819020859055517f20af8e791cc98f74b2d7a391c80980ca8e5aebf3d4060bf581997b6acae2e537906149489086815260200190565b60405180910390a25050505050565b6001600160a01b0383166000908152600a602052604081205460ff1661497e576009611902565b6001600160a01b038085166000908152600a60209081526040808320938716835260029093019052205460ff166149b6576000611902565b6000806149c68587866000613ed2565b919350909150600090508260118111156149e2576149e26156e6565b14614a02578160118111156149f9576149f96156e6565b9250505061164c565b8015612f8c5760046149f9565b6001600160a01b0382166000908152600a60205260408120805460ff16614a3a5760099150506110aa565b6001600160a01b038316600090815260028201602052604090205460ff16151560011415614a6c5760009150506110aa565b6001600160a01b03838116600090815260028301602090815260408083208054600160ff19909116811790915560098352818420805491820181558452919092200180546001600160a01b03191692871692909217909155517f3ab23ab0d51cccc0c3085aec51f99228625aa1a922b3a8ca89a26b0f2027a1a590614af490869086906156fc565b60405180910390a15060009392505050565b6040805160208101909152600081526040518060200160405280670de0b6b3a7640000614b3b866000015186600001516145c7565b614b4591906157cc565b90529392505050565b6040805160208101909152600081526040518060200160405280614b45614b818660000151670de0b6b3a76400006145c7565b8551614d66565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0846011811115614bbd57614bbd6156e6565b846014811115614bcf57614bcf6156e6565b604080519283526020830191909152810184905260600160405180910390a18360118111156113bd576113bd6156e6565b6000816401000000008410614c285760405162461bcd60e51b8152600401610d2e91906157ee565b509192915050565b600061164c614c4784670de0b6b3a76400006145c7565b8351614d66565b6040805160208101909152600081526040518060200160405280614b45614c83866a0c097ce7bc90715b34b9f160241b6145c7565b85614d66565b6040805160208101909152600081526040518060200160405280614b4585600001518560000151613a0e565b600081600160e01b8410614c285760405162461bcd60e51b8152600401610d2e91906157ee565b60006a0c097ce7bc90715b34b9f160241b614cfb8484600001516145c7565b61164c91906157cc565b600080614d128585614d26565b9050611ebc614d2082614d4e565b84613a0e565b6040805160208101909152600081526040518060200160405280614b458560000151856145c7565b80516000906110aa90670de0b6b3a7640000906157cc565b600061164c82846157cc565b604051806101400160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001614dbe6040518060200160405280600081525090565b8152602001614dd96040518060200160405280600081525090565b8152602001614df46040518060200160405280600081525090565b8152602001614e0f6040518060200160405280600081525090565b905290565b60008083601f840112614e2657600080fd5b50813567ffffffffffffffff811115614e3e57600080fd5b6020830191508360208260051b8501011115614e5957600080fd5b9250929050565b60008060008060408587031215614e7657600080fd5b843567ffffffffffffffff80821115614e8e57600080fd5b614e9a88838901614e14565b90965094506020870135915080821115614eb357600080fd5b50614ec087828801614e14565b95989497509550505050565b6001600160a01b038116811461128e57600080fd5b801515811461128e57600080fd5b60008060408385031215614f0257600080fd5b8235614f0d81614ecc565b91506020830135614f1d81614ee1565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614f6757614f67614f28565b604052919050565b600067ffffffffffffffff821115614f8957614f89614f28565b5060051b60200190565b600082601f830112614fa457600080fd5b81356020614fb9614fb483614f6f565b614f3e565b82815260059290921b84018101918181019086841115614fd857600080fd5b8286015b84811015614ffc578035614fef81614ecc565b8352918301918301614fdc565b509695505050505050565b6000806040838503121561501a57600080fd5b823561502581614ecc565b9150602083013567ffffffffffffffff81111561504157600080fd5b61504d85828601614f93565b9150509250929050565b60006020828403121561506957600080fd5b813561164c81614ecc565b600080600080600060a0868803121561508c57600080fd5b853561509781614ecc565b945060208601356150a781614ecc565b935060408601356150b781614ecc565b94979396509394606081013594506080013592915050565b600080600080608085870312156150e557600080fd5b84356150f081614ecc565b9350602085013561510081614ecc565b9250604085013561511081614ecc565b9396929550929360600135925050565b6000806040838503121561513357600080fd5b823561513e81614ecc565b946020939093013593505050565b60006020828403121561515e57600080fd5b813561164c81614ee1565b60006020828403121561517b57600080fd5b5035919050565b6000806000806080858703121561519857600080fd5b84356151a381614ecc565b935060208501356151b381614ecc565b93969395505050506040820135916060013590565b60008060008060008060c087890312156151e157600080fd5b86356151ec81614ecc565b955060208701356151fc81614ecc565b9450604087013561520c81614ecc565b9350606087013561521c81614ecc565b9598949750929560808101359460a0909101359350915050565b60008060006060848603121561524b57600080fd5b833561525681614ecc565b9250602084013561526681614ecc565b929592945050506040919091013590565b600080600080600060a0868803121561528f57600080fd5b853561529a81614ecc565b945060208601356152aa81614ecc565b935060408601356152ba81614ecc565b925060608601356152ca81614ecc565b949793965091946080013592915050565b600082601f8301126152ec57600080fd5b813560206152fc614fb483614f6f565b82815260059290921b8401810191818101908684111561531b57600080fd5b8286015b84811015614ffc57803561533281614ecc565b835291830191830161531f565b6000806000806080858703121561535557600080fd5b843567ffffffffffffffff8082111561536d57600080fd5b615379888389016152db565b9550602087013591508082111561538f57600080fd5b5061539c87828801614f93565b93505060408501356153ad81614ee1565b915060608501356153bd81614ee1565b939692955090935050565b600080604083850312156153db57600080fd5b82356153e681614ecc565b91506020830135614f1d81614ecc565b600082601f83011261540757600080fd5b81356020615417614fb483614f6f565b82815260059290921b8401810191818101908684111561543657600080fd5b8286015b84811015614ffc578035835291830191830161543a565b60008060006060848603121561546657600080fd5b833567ffffffffffffffff8082111561547e57600080fd5b61548a87838801614f93565b945060208601359150808211156154a057600080fd5b6154ac878388016153f6565b935060408601359150808211156154c257600080fd5b506154cf868287016153f6565b9150509250925092565b6020808252825182820181905260009190848201906040850190845b8181101561551a5783516001600160a01b0316835292840192918401916001016154f5565b50909695505050505050565b60006020828403121561553857600080fd5b813567ffffffffffffffff81111561554f57600080fd5b6113bd848285016152db565b6020808252825182820181905260009190848201906040850190845b8181101561551a57835183529284019291840191600101615577565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000828210156155d1576155d16155a9565b500390565b60006000198214156155ea576155ea6155a9565b5060010190565b60208082526028908201527f63616e6e6f742070617573652061206d61726b65742074686174206973206e6f6040820152671d081b1a5cdd195960c21b606082015260800190565b60208082526027908201527f6f6e6c7920706175736520677561726469616e20616e642061646d696e2063616040820152666e20706175736560c81b606082015260800190565b6020808252601690820152756f6e6c792061646d696e2063616e20756e706175736560501b604082015260600190565b6000602082840312156156c257600080fd5b815161164c81614ecc565b6000602082840312156156df57600080fd5b5051919050565b634e487b7160e01b600052602160045260246000fd5b6001600160a01b0392831681529116602082015260400190565b60006020828403121561572857600080fd5b815161164c81614ee1565b634e487b7160e01b600052600160045260246000fd5b6000806000806080858703121561575f57600080fd5b505082516020840151604085015160609095015191969095509092509050565b634e487b7160e01b600052603160045260246000fd5b600082198211156157a8576157a86155a9565b500190565b60008160001904831182151516156157c7576157c76155a9565b500290565b6000826157e957634e487b7160e01b600052601260045260246000fd5b500490565b600060208083528351808285015260005b8181101561581b578581018301518582016040015282016157ff565b8181111561582d576000604083870101525b50601f01601f191692909201604001939250505056fea26469706673582212201f07597c60bee14114bc41513326bc40568abb29280b70a84ac674455c23b3ff64736f6c634300080a0033
Deployed Bytecode Sourcemap
94730:72274:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19250:41;;19287:4;19250:41;;;;;179:14:1;;172:22;154:41;;142:2;127:18;19250:41:0;;;;;;;;147639:2305;;;;;;:::i;:::-;;:::i;:::-;;145827:583;;;;;;:::i;:::-;;:::i;160394:209::-;;;;;;:::i;:::-;;:::i;83808:35::-;;;;;-1:-1:-1;;;;;83808:35:0;;;;;;-1:-1:-1;;;;;4115:32:1;;;4097:51;;4085:2;4070:18;83808:35:0;3926:228:1;147255:308:0;;;;;;:::i;:::-;;:::i;86422:42::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;4844:25:1;;;4832:2;4817:18;86422:42:0;4698:177:1;114874:479:0;;;;;;:::i;:::-;;;;;;;87448:32;;;;;-1:-1:-1;;;;;87448:32:0;;;113765:787;;;;;;:::i;:::-;;:::i;85576:28::-;;;;;-1:-1:-1;;;;;85576:28:0;;;83321:27;;;;;-1:-1:-1;;;;;83321:27:0;;;163331:320;;;;;;:::i;:::-;;:::i;146841:406::-;;;;;;:::i;:::-;;:::i;135732:461::-;;;;;;:::i;:::-;;:::i;143725:557::-;;;;;;:::i;:::-;;:::i;145242:577::-;;;;;;:::i;:::-;;:::i;85611:31::-;;;;;-1:-1:-1;;;85611:31:0;;;;;;106485:420;;;;;;:::i;:::-;;;;;;166285:102;166367:12;166285:102;;117996:567;;;;;;:::i;:::-;;;;;;;;87627:42;;;;;;:::i;:::-;;;;;;;;;;;;;;84117:40;;;;;;126287:653;;;;;;:::i;:::-;;:::i;:::-;;;;8764:25:1;;;8820:2;8805:18;;8798:34;;;;8848:18;;;8841:34;8752:2;8737:18;126287:653:0;8562:319:1;105383:770:0;;;;;;:::i;:::-;;:::i;138956:892::-;;;;;;:::i;:::-;;:::i;109392:407::-;;;;;;:::i;:::-;;:::i;86205:26::-;;;;;;:::i;:::-;;:::i;133932:656::-;;;;;;:::i;:::-;;:::i;164808:662::-;;;;;;:::i;:::-;;:::i;112900:368::-;;;;;;:::i;:::-;160461:142;160394:209;;;134810:659;;;;;;:::i;:::-;;:::i;124473:510::-;;;;;;:::i;:::-;;:::i;144520:714::-;;;;;;:::i;:::-;;:::i;115807:1715::-;;;;;;:::i;:::-;;:::i;142837:718::-;;;;;;:::i;:::-;;:::i;160946:1300::-;;;;;;:::i;:::-;;:::i;123055:400::-;;;;;;:::i;88346:48::-;;;;;;:::i;:::-;;;;;;;;;;;;;;86535:58;;;;;;:::i;:::-;;;;;;;;;;;;-1:-1:-1;;;;;86535:58:0;;;-1:-1:-1;;;86535:58:0;;;;;;;;;;-1:-1:-1;;;;;13557:32:1;;;13539:51;;13638:10;13626:23;;;13621:2;13606:18;;13599:51;13512:18;86535:58:0;13367:289:1;85825:52:0;;;;;;:::i;:::-;;;;;;;;;;;;;;;;120767:493;;;;;;:::i;85768:50::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;159246:689;;;;;;:::i;:::-;;:::i;83729:25::-;;;;;-1:-1:-1;;;;;83729:25:0;;;88722:46;;;;;;:::i;:::-;;;;;;;;;;;;;;85689:34;;;;;-1:-1:-1;;;85689:34:0;;;;;;86664:58;;;;;;:::i;:::-;;;;;;;;;;;;-1:-1:-1;;;;;86664:58:0;;;-1:-1:-1;;;86664:58:0;;;;;;85256:41;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14104:14:1;;14097:22;14079:41;;14151:2;14136:18;;14129:34;;;;14206:14;14199:22;14179:18;;;14172:50;14067:2;14052:18;85256:41:0;13889:339:1;146418:415:0;;;;;;:::i;:::-;;:::i;99799:195::-;;;;;;:::i;:::-;-1:-1:-1;;;;;99935:24:0;;;99906:4;99935:24;;;:7;:24;;;;;;;;:51;;;;;:42;;;;:51;;;;;;99799:195;;;;;166003:274;;;;;;:::i;:::-;;:::i;84287:21::-;;;;;;87816:53;;;;;;:::i;:::-;;;;;;;;;;;;;;166502:97;166584:7;;-1:-1:-1;;;;;166584:7:0;166502:97;;140170:1015;;;;;;:::i;:::-;;:::i;98473:47::-;;-1:-1:-1;;;98473:47:0;;;;;-1:-1:-1;;;;;15096:32:1;;;15078:51;;15066:2;15051:18;98473:47:0;14932:203:1;163987:613:0;;;;;;:::i;:::-;;:::i;86316:20::-;;;;;;99316:206;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;85730:31::-;;;;;-1:-1:-1;;;85730:31:0;;;;;;165661:99;;;:::i;86842:69::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;83417:40;;;;;-1:-1:-1;;;;;83417:40:0;;;121727:1003;;;;;;:::i;:::-;;:::i;87964:52::-;;;;;;:::i;:::-;;;;;;;;;;;;;;100260:438;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;131911:1760::-;;;;;;:::i;:::-;;:::i;:::-;;;;18915:25:1;;;18971:2;18956:18;;18949:34;;;;18888:18;131911:1760:0;18741:248:1;87031:69:0;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;87180:43;;;;;;:::i;:::-;;;;;;;;;;;;;;166607:394;;;;;;:::i;:::-;;:::i;119026:1280::-;;;;;;:::i;:::-;;:::i;110240:2353::-;;;;;;:::i;:::-;;:::i;84415:49::-;;;;;;:::i;:::-;;:::i;83527:47::-;;;;;-1:-1:-1;;;;;83527:47:0;;;136561:2099;;;;;;:::i;:::-;;:::i;85649:33::-;;;;;-1:-1:-1;;;85649:33:0;;;;;;83965:31;;;;;;160081:97;;;;;;:::i;:::-;;:::i;107356:624::-;;;;;;:::i;:::-;;:::i;102418:2486::-;;;;;;:::i;:::-;;:::i;88578:33::-;;;;;;;;;88187:48;;;;;;:::i;:::-;;;;;;;;;;;;;;83220:20;;;;;-1:-1:-1;;;;;83220:20:0;;;147639:2305;147792:5;;-1:-1:-1;;;;;147792:5:0;147778:10;:19;147770:65;;;;-1:-1:-1;;;147770:65:0;;19539:2:1;147770:65:0;;;19521:21:1;19578:2;19558:18;;;19551:30;19617:34;19597:18;;;19590:62;-1:-1:-1;;;19668:18:1;;;19661:31;19709:19;;147770:65:0;;;;;;;;;147913:21;;;;147912:22;147890:110;;;;-1:-1:-1;;;147890:110:0;;19941:2:1;147890:110:0;;;19923:21:1;19980:2;19960:18;;;19953:30;20019:34;19999:18;;;19992:62;-1:-1:-1;;;20070:18:1;;;20063:36;20116:19;;147890:110:0;19739:402:1;147890:110:0;148069:38;;;148061:64;;;;-1:-1:-1;;;148061:64:0;;20348:2:1;148061:64:0;;;20330:21:1;20387:2;20367:18;;;20360:30;-1:-1:-1;;;20406:18:1;;;20399:43;20459:18;;148061:64:0;20146:337:1;148061:64:0;148165:12;148188:22;148221:24;148256:18;148339:9;148334:1505;148354:24;;;148334:1505;;;148407:13;;148421:1;148407:16;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;148455:17:0;;;;;;:11;:17;;;;;;148400:23;;-1:-1:-1;148455:17:0;-1:-1:-1;148508:7:0;;148516:1;148508:10;;;;;;;:::i;:::-;;;;;;;148489:29;;148747:14;148728:16;:33;148724:661;;;148844:25;148872:33;148891:14;148872:16;:33;:::i;:::-;-1:-1:-1;;;;;149008:20:0;;148984:21;149008:20;;;:14;:20;;;;;;148844:61;;-1:-1:-1;149071:38:0;149008:20;148844:61;149071:4;:38::i;:::-;-1:-1:-1;;;;;149196:20:0;;;;;;:14;:20;;;;;;;;;:36;;;149258:57;;18915:25:1;;;18956:18;;;18949:34;;;149196:36:0;;-1:-1:-1;149196:20:0;;149258:57;;18888:18:1;149258:57:0;;;;;;;149355:14;149336:33;;148763:622;;;148724:661;149405:20;;149401:427;;149634:99;149661:14;149698:16;149634:4;:99::i;:::-;-1:-1:-1;;;;;149601:17:0;;;;;;:11;:17;;;;;;;;;:132;;;149759:53;;18915:25:1;;;18956:18;;;18949:34;;;149601:132:0;;-1:-1:-1;149601:17:0;;149759:53;;18888:18:1;149759:53:0;;;;;;;149401:427;148380:3;;;:::i;:::-;;;148334:1505;;;-1:-1:-1;;149851:21:0;:28;;-1:-1:-1;;149851:28:0;149875:4;149851:28;;;-1:-1:-1;;;;;;;147639:2305:0:o;145827:583::-;-1:-1:-1;;;;;145935:24:0;;145896:4;145935:24;;;:7;:24;;;;;:33;;;145913:123;;;;-1:-1:-1;;;145913:123:0;;;;;;;:::i;:::-;146083:13;;-1:-1:-1;;;;;146083:13:0;146069:10;:27;;:50;;-1:-1:-1;146114:5:0;;-1:-1:-1;;;;;146114:5:0;146100:10;:19;146069:50;146047:139;;;;-1:-1:-1;;;146047:139:0;;;;;;;:::i;:::-;146219:5;;-1:-1:-1;;;;;146219:5:0;146205:10;:19;;:36;;-1:-1:-1;146237:4:0;146228:13;;;;146205:36;146197:71;;;;-1:-1:-1;;;146197:71:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;146281:37:0;;;;;;:20;:37;;;;;;;;;:45;;-1:-1:-1;;146281:45:0;;;;;;;;;;146342:37;;22439:51:1;;;22526:2;22506:18;;;22499:30;;;22565:1;22545:18;;;22538:29;;;;-1:-1:-1;;;22598:3:1;22583:19;;22576:37;22665:18;;;22658:50;146342:37:0;;22477:3:1;22630:19;146342:37:0;;;;;;;;-1:-1:-1;146397:5:0;145827:583;;;;;:::o;160394:209::-;160499:16;;;160513:1;160499:16;;;;;;;;;160472:24;;160499:16;;;;;;;;;;;-1:-1:-1;160499:16:0;160472:43;;160539:6;160526:7;160534:1;160526:10;;;;;;;;:::i;:::-;;;;;;:19;-1:-1:-1;;;;;160526:19:0;;;-1:-1:-1;;;;;160526:19:0;;;;;160556:39;160566:7;160575;160584:4;160590;160556:9;:39::i;147255:308::-;147349:10;-1:-1:-1;;;;;147349:16:0;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;147335:32:0;:10;-1:-1:-1;;;;;147335:32:0;;147313:121;;;;-1:-1:-1;;;147313:121:0;;23185:2:1;147313:121:0;;;23167:21:1;23224:2;23204:18;;;23197:30;23263:34;23243:18;;;23236:62;-1:-1:-1;;;23314:18:1;;;23307:37;23361:19;;147313:121:0;22983:403:1;147313:121:0;147467:10;-1:-1:-1;;;;;147467:32:0;;:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:39;147445:110;;;;-1:-1:-1;;;147445:110:0;;23782:2:1;147445:110:0;;;23764:21:1;23821:2;23801:18;;;23794:30;-1:-1:-1;;;23840:18:1;;;23833:51;23901:18;;147445:110:0;23580:345:1;147445:110:0;147255:308;:::o;113765:787::-;-1:-1:-1;;;;;114052:15:0;;113933:7;114052:15;;;:7;:15;;;;;:24;;;114047:97;;-1:-1:-1;114108:23:0;114093:39;;114047:97;114193:22;114218:45;;;;;;;;114240:6;-1:-1:-1;;;;;114233:26:0;;:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;114218:45;;114193:70;-1:-1:-1;114274:42:0;114296:6;114193:70;114274:21;:42::i;:::-;114327:53;114350:6;114358:8;114368:11;114327:22;:53::i;:::-;114403:9;;-1:-1:-1;;;;;114403:9:0;114395:32;114391:111;;114444:9;;:46;;-1:-1:-1;;;114444:46:0;;-1:-1:-1;;;;;114444:9:0;;;;:28;;:46;;114473:6;;114481:8;;114444:46;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;114391:111;114529:14;114514:30;;;113765:787;;;;;;;:::o;163331:320::-;163412:21;:19;:21::i;:::-;163404:59;;;;-1:-1:-1;;;163404:59:0;;24573:2:1;163404:59:0;;;24555:21:1;24612:2;24592:18;;;24585:30;24651:27;24631:18;;;24624:55;24696:18;;163404:59:0;24371:349:1;163404:59:0;163474:18;163495:36;163513:9;163524:6;163495:17;:36::i;:::-;163474:57;-1:-1:-1;163550:15:0;;163542:55;;;;-1:-1:-1;;;163542:55:0;;24927:2:1;163542:55:0;;;24909:21:1;24966:2;24946:18;;;24939:30;25005:29;24985:18;;;24978:57;25052:18;;163542:55:0;24725:351:1;163542:55:0;163613:30;;;-1:-1:-1;;;;;25273:32:1;;25255:51;;25337:2;25322:18;;25315:34;;;163613:30:0;;25228:18:1;163613:30:0;;;;;;;163393:258;163331:320;;:::o;146841:406::-;146947:13;;146894:4;;-1:-1:-1;;;;;146947:13:0;146933:10;:27;;:50;;-1:-1:-1;146978:5:0;;-1:-1:-1;;;;;146978:5:0;146964:10;:19;146933:50;146911:139;;;;-1:-1:-1;;;146911:139:0;;;;;;;:::i;:::-;147083:5;;-1:-1:-1;;;;;147083:5:0;147069:10;:19;;:36;;-1:-1:-1;147101:4:0;147092:13;;;;147069:36;147061:71;;;;-1:-1:-1;;;147061:71:0;;;;;;;:::i;:::-;147145:19;:27;;;;;-1:-1:-1;;;147145:27:0;-1:-1:-1;;;;147145:27:0;;;;;;147188:28;;;;;;147167:5;;25584:2:1;25566:21;;;25623:1;25603:18;;;25596:29;-1:-1:-1;;;25656:2:1;25641:18;;25634:35;25750:14;;25743:22;25736:4;25721:20;;25714:52;25701:3;25686:19;;25360:412;147188:28:0;;;;;;;;-1:-1:-1;147234:5:0;146841:406::o;135732:461::-;135825:7;135906:5;;-1:-1:-1;;;;;135906:5:0;135892:10;:19;135884:63;;;;-1:-1:-1;;;135884:63:0;;25979:2:1;135884:63:0;;;25961:21:1;26018:2;25998:18;;;25991:30;26057:33;26037:18;;;26030:61;26108:18;;135884:63:0;25777:355:1;135884:63:0;135993:19;;;136023:44;;;;136083:59;;;18915:25:1;;;18971:2;18956:18;;18949:34;;;136083:59:0;;18888:18:1;136083:59:0;;;;;;;;136170:14;136162:23;136155:30;135732:461;-1:-1:-1;;;135732:461:0:o;143725:557::-;143828:5;;-1:-1:-1;;;;;143828:5:0;143814:10;:19;143806:70;;;;-1:-1:-1;;;143806:70:0;;26339:2:1;143806:70:0;;;26321:21:1;26378:2;26358:18;;;26351:30;26417:34;26397:18;;;26390:62;-1:-1:-1;;;26468:18:1;;;26461:36;26514:19;;143806:70:0;26137:402:1;143806:70:0;143972:17;;;-1:-1:-1;;;;;144070:40:0;;;-1:-1:-1;;;;;;144070:40:0;;;;;;144210:64;;143972:17;;;144210:64;;;;143972:17;;144090:20;;144210:64;:::i;:::-;;;;;;;;143795:487;143725:557;:::o;145242:577::-;-1:-1:-1;;;;;145348:24:0;;145309:4;145348:24;;;:7;:24;;;;;:33;;;145326:123;;;;-1:-1:-1;;;145326:123:0;;;;;;;:::i;:::-;145496:13;;-1:-1:-1;;;;;145496:13:0;145482:10;:27;;:50;;-1:-1:-1;145527:5:0;;-1:-1:-1;;;;;145527:5:0;145513:10;:19;145482:50;145460:139;;;;-1:-1:-1;;;145460:139:0;;;;;;;:::i;:::-;145632:5;;-1:-1:-1;;;;;145632:5:0;145618:10;:19;;:36;;-1:-1:-1;145650:4:0;145641:13;;;;145618:36;145610:71;;;;-1:-1:-1;;;145610:71:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;145694:35:0;;;;;;:18;:35;;;;;;;;;:43;;-1:-1:-1;;145694:43:0;;;;;;;;;;145753:35;;26793:51:1;;;26880:2;26860:18;;;26853:30;;;26919:1;26899:18;;;26892:29;;;;-1:-1:-1;;;26952:3:1;26937:19;;26930:35;27017:18;;;27010:50;145753:35:0;;26831:3:1;26982:19;145753:35:0;26544:522:1;126287:653:0;126516:7;126538;126560;126610:9;126634:17;126666;126697:181;126755:7;126788:12;126820;126851;126697:39;:181::i;:::-;126595:283;;;;;;126905:3;126897:12;;;;;;;;:::i;:::-;126889:43;-1:-1:-1;126911:9:0;;-1:-1:-1;126922:9:0;-1:-1:-1;;126287:653:0;;;;;;;;;:::o;105383:770::-;-1:-1:-1;;;;;105626:26:0;;105517:7;105626:26;;;:18;:26;;;;;;;;105625:27;105617:54;;;;-1:-1:-1;;;105617:54:0;;27273:2:1;105617:54:0;;;27255:21:1;27312:2;27292:18;;;27285:30;-1:-1:-1;;;27331:18:1;;;27324:44;27385:18;;105617:54:0;27071:338:1;105617:54:0;-1:-1:-1;;;;;105764:15:0;;;;;;:7;:15;;;;;:24;;;105759:97;;105820:23;105812:32;105805:39;;;;105759:97;105905:29;105927:6;105905:21;:29::i;:::-;105945:38;105968:6;105976;105945:22;:38::i;:::-;106006:9;;-1:-1:-1;;;;;106006:9:0;105998:32;105994:109;;106047:9;;:44;;-1:-1:-1;;;106047:44:0;;-1:-1:-1;;;;;106047:9:0;;;;:28;;:44;;106076:6;;106084;;106047:44;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;105994:109;106130:14;106115:30;105383:770;-1:-1:-1;;;;105383:770:0:o;138956:892::-;139067:7;139144:5;;-1:-1:-1;;;;;139144:5:0;139130:10;:19;139126:212;;139190:136;139217:18;139258:49;139190:4;:136::i;139126:212::-;139438:28;;;139534:62;;;;139671:126;;;18915:25:1;;;18971:2;18956:18;;18949:34;;;139671:126:0;;18888:18:1;139671:126:0;18741:248:1;109392:407:0;109699:17;;:37;;;;;109735:1;109720:12;:16;109699:37;109695:97;;;109753:27;;-1:-1:-1;;;109753:27:0;;27616:2:1;109753:27:0;;;27598:21:1;27655:2;27635:18;;;27628:30;-1:-1:-1;;;27674:18:1;;;27667:47;27731:18;;109753:27:0;27414:341:1;86205:26:0;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;86205:26:0;;-1:-1:-1;86205:26:0;:::o;133932:656::-;133996:7;134068:5;;-1:-1:-1;;;;;134068:5:0;134054:10;:19;134050:203;;134114:127;134141:18;134182:40;134114:4;:127::i;134050:203::-;134342:6;;;-1:-1:-1;;;;;134411:18:0;;;-1:-1:-1;;;;;;134411:18:0;;;;;;134501:36;;134342:6;;;134501:36;;;;134342:6;;134420:9;;134501:36;:::i;164808:662::-;164922:21;:19;:21::i;:::-;164914:63;;;;-1:-1:-1;;;164914:63:0;;28311:2:1;164914:63:0;;;28293:21:1;28350:2;28330:18;;;28323:30;28389:31;28369:18;;;28362:59;28438:18;;164914:63:0;28109:353:1;164914:63:0;165085:37;165110:11;165085:24;:37::i;:::-;165137:14;165133:204;;-1:-1:-1;;;;;165207:33:0;;;;;;:20;:33;;;;;165200:40;165133:204;;;166367:12;-1:-1:-1;;;;;165273:33:0;;;;;;:20;:33;;;;;:52;165133:204;-1:-1:-1;;;;;165347:34:0;;;;;;:21;:34;;;;;;;:46;;;165411:51;;;;;165384:9;4844:25:1;;4832:2;4817:18;;4698:177;165411:51:0;;;;;;;;164808:662;;:::o;134810:659::-;134900:7;134977:5;;-1:-1:-1;;;;;134977:5:0;134963:10;:19;134959:139;;135023:63;135028:18;135048:37;135023:4;:63::i;134959:139::-;135200:9;;;-1:-1:-1;;;;;135278:24:0;;;-1:-1:-1;;;;;;135278:24:0;;;;;;135378:40;;135200:9;;;135378:40;;;;135200:9;;135290:12;;135378:40;:::i;124473:510::-;124581:7;124603;124625;124675:9;124699:17;124731;124762:157;124820:7;124861:1;124883;124903;124762:39;:157::i;:::-;124660:259;;;;;;124948:3;124940:12;;;;;;;;:::i;:::-;124932:43;124954:9;;-1:-1:-1;124954:9:0;-1:-1:-1;124473:510:0;-1:-1:-1;;;124473:510:0:o;144520:714::-;144607:7;144650:5;;-1:-1:-1;;;;;144650:5:0;144636:10;:19;144632:205;;144696:129;144723:18;144764:42;144696:4;:129::i;144632:205::-;144928:13;;;-1:-1:-1;;;;;145014:32:0;;;-1:-1:-1;;;;;;145014:32:0;;;;;;;145134:49;;144928:13;;;145134:49;;;;144928:13;;145134:49;:::i;115807:1715::-;-1:-1:-1;;;;;116124:23:0;;116027:7;116124:23;;;:7;:23;;;;;:32;;;116123:33;;:85;;-1:-1:-1;;;;;;116174:25:0;;;;;;:7;:25;;;;;:34;;;116173:35;116123:85;116105:181;;;116250:23;116242:32;116235:39;;;;116105:181;116322:76;;-1:-1:-1;;;116322:76:0;;-1:-1:-1;;;;;4115:32:1;;;116322:76:0;;;4097:51:1;116298:21:0;;116322:42;;;;;;4070:18:1;;116322:76:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;116298:100;;116490:36;116510:14;116490:12;:36::i;:::-;116486:988;;;116586:11;116569:13;:28;;116543:130;;;;-1:-1:-1;;;116543:130:0;;29028:2:1;116543:130:0;;;29010:21:1;29067:2;29047:18;;;29040:30;29106:34;29086:18;;;29079:62;-1:-1:-1;;;29157:18:1;;;29150:38;29205:19;;116543:130:0;28826:404:1;116543:130:0;116486:988;;;116787:9;116800:17;116821:69;116867:8;116821:27;:69::i;:::-;116786:104;;-1:-1:-1;116786:104:0;;-1:-1:-1;116916:14:0;;-1:-1:-1;116909:3:0;:21;;;;;;;;:::i;:::-;;116905:81;;116966:3;116958:12;;;;;;;;:::i;:::-;116951:19;;;;;;;116905:81;117006:14;117002:99;;117056:28;117048:37;;117002:99;117210:16;117229:120;117266:36;;;;;;;;117281:19;;117266:36;;;117321:13;117229:18;:120::i;:::-;117210:139;;117382:8;117368:11;:22;117364:99;;;117426:20;117411:36;;;;;;;;117364:99;116691:783;;;116486:988;117499:14;117484:30;;;115807:1715;;;;;;;;:::o;142837:718::-;143009:5;;-1:-1:-1;;;;;143009:5:0;142995:10;:19;;:54;;-1:-1:-1;143032:17:0;;-1:-1:-1;;;;;143032:17:0;143018:10;:31;142995:54;142973:157;;;;-1:-1:-1;;;142973:157:0;;29437:2:1;142973:157:0;;;29419:21:1;29476:2;29456:18;;;29449:30;29515:34;29495:18;;;29488:62;-1:-1:-1;;;29566:18:1;;;29559:51;29627:19;;142973:157:0;29235:417:1;142973:157:0;143164:7;143213:13;143268:15;;;;;:46;;;143301:13;143287:10;:27;143268:46;143246:109;;;;-1:-1:-1;;;143246:109:0;;29859:2:1;143246:109:0;;;29841:21:1;29898:2;29878:18;;;29871:30;-1:-1:-1;;;29917:18:1;;;29910:43;29970:18;;143246:109:0;29657:337:1;143246:109:0;143373:9;143368:180;143392:10;143388:1;:14;143368:180;;;143458:13;;143472:1;143458:16;;;;;;;:::i;:::-;;;;;;;143424:10;:31;143443:7;;143451:1;143443:10;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;143424:31:0;;;;;;;;;;;;-1:-1:-1;143424:31:0;:50;143507:7;;143515:1;143507:10;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;143494:42:0;;143519:13;;143533:1;143519:16;;;;;;;:::i;:::-;;;;;;;143494:42;;;;4844:25:1;;4832:2;4817:18;;4698:177;143494:42:0;;;;;;;;143404:3;;;;:::i;:::-;;;;143368:180;;;;142962:593;;142837:718;;;;:::o;160946:1300::-;161114:9;161109:919;161133:7;:14;161129:1;:18;161109:919;;;161169:13;161185:7;161193:1;161185:10;;;;;;;;:::i;:::-;;;;;;;;;;;;-1:-1:-1;;;;;161218:24:0;;;;;;:7;:24;;;;;;;:33;161185:10;;-1:-1:-1;161218:33:0;;161210:67;;;;-1:-1:-1;;;161210:67:0;;30201:2:1;161210:67:0;;;30183:21:1;30240:2;30220:18;;;30213:30;-1:-1:-1;;;30259:18:1;;;30252:51;30320:18;;161210:67:0;29999:345:1;161210:67:0;161309:4;161296:17;;;;161292:458;;;161334:22;161359:37;;;;;;;;161374:6;-1:-1:-1;;;;;161374:18:0;;:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;161359:37;;161334:62;-1:-1:-1;161415:51:0;161445:6;161334:62;161415:21;:51::i;:::-;161490:9;161485:250;161509:7;:14;161505:1;:18;161485:250;;;161553:162;161610:6;161644:7;161652:1;161644:10;;;;;;;;:::i;:::-;;;;;;;161681:11;161553:22;:162::i;:::-;161525:3;;;;:::i;:::-;;;;161485:250;;;;161315:435;161292:458;161781:4;161768:17;;;;161764:253;;;161806:38;161836:6;161806:21;:38::i;:::-;161868:9;161863:139;161887:7;:14;161883:1;:18;161863:139;;;161931:51;161962:6;161971:7;161979:1;161971:10;;;;;;;;:::i;:::-;;;;;;;161931:22;:51::i;:::-;161903:3;;;;:::i;:::-;;;;161863:139;;;;161764:253;-1:-1:-1;161149:3:0;;;;:::i;:::-;;;;161109:919;;;;162043:9;162038:201;162062:7;:14;162058:1;:18;162038:201;;;162124:103;162160:7;162168:1;162160:10;;;;;;;;:::i;:::-;;;;;;;162189:11;:23;162201:7;162209:1;162201:10;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1;;;;;162189:23:0;-1:-1:-1;;;;;162189:23:0;;;;;;;;;;;;;162124:17;:103::i;:::-;162098:11;:23;162110:7;162118:1;162110:10;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1;;;;;162098:23:0;-1:-1:-1;;;;;162098:23:0;;;;;;;;;;;;:129;;;;162078:3;;;;;:::i;:::-;;;;162038:201;;159246:689;-1:-1:-1;;;;;159339:34:0;;159319:17;159339:34;;;:21;:34;;;;;;;;;159500:20;:33;;;;;;159339:34;;166367:12;;159455:89;;166367:12;;159455:4;:89::i;:::-;159433:111;;159573:1;159559:11;:15;:32;;;;;159590:1;159578:9;:13;159559:32;159555:373;;;159608:18;159629:28;159634:11;159647:9;159629:4;:28::i;:::-;-1:-1:-1;;;;;159724:24:0;;159672:26;159724:24;;;:11;:24;;;;;;159608:49;;-1:-1:-1;159672:26:0;159701:91;;159608:49;159701:4;:91::i;:::-;-1:-1:-1;;;;;159809:24:0;;;;;;:11;:24;;;;;;;;:45;;;;159869:20;:33;;;:47;;;-1:-1:-1;;159308:627:0;;;159246:689;:::o;146418:415::-;146527:13;;146474:4;;-1:-1:-1;;;;;146527:13:0;146513:10;:27;;:50;;-1:-1:-1;146558:5:0;;-1:-1:-1;;;;;146558:5:0;146544:10;:19;146513:50;146491:139;;;;-1:-1:-1;;;146491:139:0;;;;;;;:::i;:::-;146663:5;;-1:-1:-1;;;;;146663:5:0;146649:10;:19;;:36;;-1:-1:-1;146681:4:0;146672:13;;;;146649:36;146641:71;;;;-1:-1:-1;;;146641:71:0;;;;;;;:::i;:::-;146725:22;:30;;;;;-1:-1:-1;;;146725:30:0;-1:-1:-1;;;;146725:30:0;;;;;;146771:31;;;;;;146750:5;;30573:2:1;30555:21;;;30612:1;30592:18;;;30585:29;-1:-1:-1;;;30645:2:1;30630:18;;30623:38;30742:14;;30735:22;30728:4;30713:20;;30706:52;30693:3;30678:19;;30349:415;166003:274:0;-1:-1:-1;;;;;166098:24:0;;166061:4;166098:24;;;:7;:24;;;;;:49;;;:54;:116;;;;-1:-1:-1;;;;;;166169:37:0;;;;;;:20;:37;;;;;;;;:45;;:37;:45;166098:116;:171;;;;;166231:6;-1:-1:-1;;;;;166231:28:0;;:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;166265:4;166231:38;166078:191;166003:274;-1:-1:-1;;166003:274:0:o;140170:1015::-;140227:7;140265:5;;-1:-1:-1;;;;;140265:5:0;140251:10;:19;140247:201;;140311:125;140338:18;140379:38;140311:4;:125::i;140247:201::-;-1:-1:-1;;;;;140464:24:0;;;;;;:7;:24;;;;;:33;;;140460:219;;;140538:129;140565:27;140615:33;140538:4;:129::i;140460:219::-;140691:6;-1:-1:-1;;;;;140691:15:0;;:17;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;;140857:24:0;;140830;140857;;;:7;:24;;;;;140892:25;;140913:4;-1:-1:-1;;140892:25:0;;;;;;;140928:18;;;:26;;;;;;;;140965:34;;:38;;;;141016:35;140857:24;141016:18;:35::i;:::-;141062:34;141088:6;141062:17;:34::i;:::-;141114:20;;-1:-1:-1;;;;;4115:32:1;;4097:51;;141114:20:0;;4085:2:1;4070:18;141114:20:0;3926:228:1;163987:613:0;164158:21;:19;:21::i;:::-;164150:63;;;;-1:-1:-1;;;164150:63:0;;28311:2:1;164150:63:0;;;28293:21:1;28350:2;28330:18;;;28323:30;28389:31;28369:18;;;28362:59;28438:18;;164150:63:0;28109:353:1;164150:63:0;164246:14;;164306:19;;164293:32;;:85;;;;;164359:12;:19;164346:9;:32;164293:85;164271:176;;;;-1:-1:-1;;;164271:176:0;;31221:2:1;164271:176:0;;;31203:21:1;31260:2;31240:18;;;31233:30;31299:34;31279:18;;;31272:62;-1:-1:-1;;;31350:18:1;;;31343:39;31399:19;;164271:176:0;31019:405:1;164271:176:0;164465:9;164460:133;164484:9;164480:1;:13;164460:133;;;164515:66;164536:7;164544:1;164536:10;;;;;;;;:::i;:::-;;;;;;;164548:12;164561:1;164548:15;;;;;;;;:::i;:::-;;;;;;;164565:12;164578:1;164565:15;;;;;;;;:::i;:::-;;;;;;;164515:20;:66::i;:::-;164495:3;;;:::i;:::-;;;164460:133;;99316:206;-1:-1:-1;;;;;99464:22:0;;99437:24;99464:22;;;:13;:22;;;;;;;;99437:49;;;;;;;;;;;;;;;;;99404:15;;99437:24;:49;;99464:22;99437:49;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;99437:49:0;;;;;;;;;;;;;;;;-1:-1:-1;99437:49:0;;99316:206;-1:-1:-1;;;;;;;99316:206:0:o;165661:99::-;165707:15;165742:10;165735:17;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;165735:17:0;;;;;;;;;;;;;;;;;;;;;;;165661:99;:::o;121727:1003::-;121997:22;;121888:7;;-1:-1:-1;;;121997:22:0;;;;121996:23;121988:54;;;;-1:-1:-1;;;121988:54:0;;31631:2:1;121988:54:0;;;31613:21:1;31670:2;31650:18;;;31643:30;-1:-1:-1;;;31689:18:1;;;31682:48;31747:18;;121988:54:0;31429:342:1;121988:54:0;122177:15;122195:50;122217:6;122225:3;122230:14;122195:21;:50::i;:::-;122177:68;-1:-1:-1;122260:34:0;;122256:81;;122318:7;-1:-1:-1;122311:14:0;;122256:81;122386:29;122408:6;122386:21;:29::i;:::-;122426:35;122449:6;122457:3;122426:22;:35::i;:::-;122472;122495:6;122503:3;122472:22;:35::i;:::-;122530:9;;-1:-1:-1;;;;;122530:9:0;122522:32;122518:162;;122571:9;;:41;;-1:-1:-1;;;122571:41:0;;-1:-1:-1;;;;;122571:9:0;;;;:28;;:41;;122600:6;;122608:3;;122571:41;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;122627:9:0;;:41;;-1:-1:-1;;;122627:41:0;;-1:-1:-1;;;;;122627:9:0;;;;-1:-1:-1;122627:28:0;;-1:-1:-1;122627:41:0;;122656:6;;122664:3;;122627:41;;;:::i;100260:438::-;100408:14;;100360:16;;100394:11;100408:14;100462:18;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;100462:18:0;;100435:45;;100496:9;100491:173;100515:3;100511:1;:7;100491:173;;;100540:13;100563:7;100571:1;100563:10;;;;;;;;:::i;:::-;;;;;;;100540:34;;100612:39;100632:6;100640:10;100612:19;:39::i;:::-;100604:48;;;;;;;;:::i;:::-;100591:7;100599:1;100591:10;;;;;;;;:::i;:::-;;;;;;;;;;:61;-1:-1:-1;100520:3:0;;;;:::i;:::-;;;;100491:173;;;-1:-1:-1;100683:7:0;100260:438;-1:-1:-1;;;100260:438:0:o;131911:1760::-;132224:6;;;:73;;-1:-1:-1;;;132224:73:0;;-1:-1:-1;;;;;4115:32:1;;;132224:73:0;;;4097:51:1;;;;132093:7:0;;;;;;132224:6;;;:25;;4070:18:1;;132224:73:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;132342:6;;;:75;;-1:-1:-1;;;132342:75:0;;-1:-1:-1;;;;;4115:32:1;;;132342:75:0;;;4097:51:1;;;;132192:105:0;;-1:-1:-1;132308:31:0;;132342:6;;;:25;;4070:18:1;;132342:75:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;132308:109;-1:-1:-1;132432:26:0;;;:58;;-1:-1:-1;132462:28:0;;132432:58;132428:129;;;132523:17;132543:1;132507:38;;;;;;;;132428:129;132950:28;132988:16;-1:-1:-1;;;;;132981:57:0;;:59;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;132950:90;;133077:19;133107:20;-1:-1:-1;;;;;;;;;;;;;;133107:20:0;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;133231:45:0;;;;;;;133246:28;;133231:45;;133291:38;;;;;;;;;;;-1:-1:-1;;133212:128:0;;:4;:128::i;:::-;133200:140;;133365:122;133384:40;;;;;;;;133399:23;133384:40;;;133439:37;;;;;;;;133454:20;133439:37;;;133365:4;:122::i;:::-;133351:136;;133506:28;133511:9;133522:11;133506:4;:28::i;:::-;133498:36;;133561:44;133580:5;133587:17;133561:18;:44::i;:::-;133634:14;;-1:-1:-1;133547:58:0;-1:-1:-1;;;;;;;;131911:1760:0;;;;;;;:::o;166607:394::-;166694:7;166737:5;;-1:-1:-1;;;;;166737:5:0;166723:10;:19;166719:203;;166783:127;166810:18;166851:40;166783:4;:127::i;166719:203::-;166932:7;:18;;-1:-1:-1;;;;;;166932:18:0;-1:-1:-1;;;;;166932:18:0;;;;;-1:-1:-1;166970:23:0;;119026:1280;119345:19;;119236:7;;-1:-1:-1;;;119345:19:0;;;;119344:20;119336:48;;;;-1:-1:-1;;;119336:48:0;;31978:2:1;119336:48:0;;;31960:21:1;32017:2;31997:18;;;31990:30;-1:-1:-1;;;32036:18:1;;;32029:45;32091:18;;119336:48:0;31776:339:1;119336:48:0;-1:-1:-1;;;;;119475:25:0;;;;;;:7;:25;;;;;:34;;;119474:35;;:85;;-1:-1:-1;;;;;;119527:23:0;;;;;;:7;:23;;;;;:32;;;119526:33;119474:85;119456:181;;;119601:23;119593:32;;119456:181;119729:14;-1:-1:-1;;;;;119722:34:0;;:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;119667:91:0;119674:16;-1:-1:-1;;;;;119667:36:0;;:38;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;119667:91:0;;119649:190;;119800:26;119792:35;;119649:190;119888:39;119910:16;119888:21;:39::i;:::-;119938:50;119961:16;119979:8;119938:22;:50::i;:::-;119999:52;120022:16;120040:10;119999:22;:52::i;:::-;120074:9;;-1:-1:-1;;;;;120074:9:0;120066:32;120062:194;;120115:9;;:56;;-1:-1:-1;;;120115:56:0;;-1:-1:-1;;;;;120115:9:0;;;;:28;;:56;;120144:16;;120162:8;;120115:56;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;120186:9:0;;:58;;-1:-1:-1;;;120186:58:0;;-1:-1:-1;;;;;120186:9:0;;;;-1:-1:-1;120186:28:0;;-1:-1:-1;120186:58:0;;120215:16;;120233:10;;120186:58;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;120062:194;120283:14;120268:30;119026:1280;-1:-1:-1;;;;;;119026:1280:0:o;110240:2353::-;-1:-1:-1;;;;;110489:28:0;;110380:7;110489:28;;;:20;:28;;;;;;;;110488:29;110480:58;;;;-1:-1:-1;;;110480:58:0;;32615:2:1;110480:58:0;;;32597:21:1;32654:2;32634:18;;;32627:30;-1:-1:-1;;;32673:18:1;;;32666:46;32729:18;;110480:58:0;32413:340:1;110480:58:0;-1:-1:-1;;;;;110556:15:0;;;;;;:7;:15;;;;;:24;;;110551:97;;110612:23;110604:32;;110551:97;-1:-1:-1;;;;;110665:15:0;;;;;;;:7;:15;;;;;;;;:43;;;;;:33;;;;:43;;;;;;110660:577;;110811:10;-1:-1:-1;;;;;110811:20:0;;;110803:54;;;;-1:-1:-1;;;110803:54:0;;32960:2:1;110803:54:0;;;32942:21:1;32999:2;32979:18;;;32972:30;-1:-1:-1;;;33018:18:1;;;33011:51;33079:18;;110803:54:0;32758:345:1;110803:54:0;110928:9;110940:49;110967:10;110980:8;110940:19;:49::i;:::-;110928:61;-1:-1:-1;111015:14:0;111008:3;:21;;;;;;;;:::i;:::-;;111004:81;;111065:3;111057:12;;;;;;;;:::i;:::-;111050:19;;;;;111004:81;-1:-1:-1;;;;;111181:15:0;;;;;;;:7;:15;;;;;;;;:43;;;;;:33;;;;:43;;;;;;111174:51;;;;:::i;:::-;110710:527;110660:577;111253:6;;;:41;;-1:-1:-1;;;111253:41:0;;-1:-1:-1;;;;;4115:32:1;;;111253:41:0;;;4097:51:1;;;;111253:6:0;;;:25;;4070:18:1;;111253:41:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;111249:112;;111331:17;111323:26;;111249:112;-1:-1:-1;;;;;111393:18:0;;111373:17;111393:18;;;:10;:18;;;;;;111489:14;;111485:254;;111520:20;111550:6;-1:-1:-1;;;;;111543:27:0;;:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;111520:52;;111587:24;111614:32;111619:12;111633;111614:4;:32::i;:::-;111587:59;;111688:9;111669:16;:28;111661:66;;;;-1:-1:-1;;;111661:66:0;;33442:2:1;111661:66:0;;;33424:21:1;33481:2;33461:18;;;33454:30;33520:27;33500:18;;;33493:55;33565:18;;111661:66:0;33240:349:1;111661:66:0;111505:234;;111485:254;111766:9;111805:17;111836:165;111894:8;111928:6;111954:1;111974:12;111836:39;:165::i;:::-;111751:250;;-1:-1:-1;111751:250:0;;-1:-1:-1;112023:14:0;;-1:-1:-1;112016:3:0;:21;;;;;;;;:::i;:::-;;112012:73;;112069:3;112061:12;;;;;;;;:::i;:::-;112054:19;;;;;;;112012:73;112099:13;;112095:90;;112144:28;112136:37;;112095:90;112234:22;112259:45;;;;;;;;112281:6;-1:-1:-1;;;;;112274:26:0;;:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;112259:45;;112234:70;-1:-1:-1;112315:42:0;112337:6;112234:70;112315:21;:42::i;:::-;112368:53;112391:6;112399:8;112409:11;112368:22;:53::i;:::-;112444:9;;-1:-1:-1;;;;;112444:9:0;112436:32;112432:111;;112485:9;;:46;;-1:-1:-1;;;112485:46:0;;-1:-1:-1;;;;;112485:9:0;;;;:28;;:46;;112514:6;;112522:8;;112485:46;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;112432:111;112570:14;112555:30;110240:2353;-1:-1:-1;;;;;;;;110240:2353:0:o;84415:49::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;84415:49:0;;-1:-1:-1;84415:49:0;;-1:-1:-1;84415:49:0:o;136561:2099::-;136686:7;136758:5;;-1:-1:-1;;;;;136758:5:0;136744:10;:19;136740:208;;136804:132;136831:18;136872:45;136804:4;:132::i;:::-;136780:156;;;;136740:208;-1:-1:-1;;;;;137020:24:0;;136996:21;137020:24;;;:7;:24;;;;;137060:15;;;;137055:208;;137116:135;137143:23;137189:43;137116:4;:135::i;:::-;137092:159;;;;;137055:208;137311:68;;;;;;;;;;;;137458:44;;;;;;;;98915:6;137458:44;;137311:68;137517:46;137458:44;137311:68;3551:14;3535:13;;:30;;3432:141;137517:46;137513:247;;;137604:144;137631:31;137685:44;137604:4;:144::i;:::-;137580:168;;;;;;;137513:247;137848:32;;;;;:87;;-1:-1:-1;137897:6:0;;;:33;;-1:-1:-1;;;137897:33:0;;-1:-1:-1;;;;;4115:32:1;;;137897:33:0;;;4097:51:1;;;;137897:6:0;;;:25;;4070:18:1;;137897:33:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:38;137848:87;137830:301;;;137986:133;138013:17;138053:47;137986:4;:133::i;137830:301::-;138269:31;;;;;138311:61;;;;138474:135;;;-1:-1:-1;;;;;33829:32:1;;33811:51;;33893:2;33878:18;;33871:34;;;33921:18;;;33914:34;;;138474:135:0;;33799:2:1;33784:18;138474:135:0;;;;;;;138637:14;138622:30;136561:2099;-1:-1:-1;;;;;;;136561:2099:0:o;160081:97::-;160141:29;160151:6;160159:10;160141:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;160141:29:0;;;;;;;;;;;;;;;;;;;;;:9;:29::i;107356:624::-;107496:7;107516:15;107534:53;107556:6;107564:8;107574:12;107534:21;:53::i;:::-;107516:71;-1:-1:-1;107602:34:0;;107598:81;;107660:7;-1:-1:-1;107653:14:0;;107598:81;107728:29;107750:6;107728:21;:29::i;:::-;107768:40;107791:6;107799:8;107768:22;:40::i;:::-;107831:9;;-1:-1:-1;;;;;107831:9:0;107823:32;107819:111;;107872:9;;:46;;-1:-1:-1;;;107872:46:0;;-1:-1:-1;;;;;107872:9:0;;;;:28;;:46;;107901:6;;107909:8;;107872:46;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;107819:111;107957:14;107942:30;107356:624;-1:-1:-1;;;;;107356:624:0:o;102418:2486::-;102726:51;;-1:-1:-1;;;102726:51:0;;102766:10;102726:51;;;4097::1;102515:7:0;;102563:13;;102515:7;;;;;;-1:-1:-1;;;;;102726:39:0;;;;;4070:18:1;;102726:51:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;102667:110;;;;;;;102796:4;102804:1;102796:9;102788:59;;;;-1:-1:-1;;;102788:59:0;;34534:2:1;102788:59:0;;;34516:21:1;34573:2;34553:18;;;34546:30;34612:34;34592:18;;;34585:62;-1:-1:-1;;;34663:18:1;;;34656:35;34708:19;;102788:59:0;34332:401:1;102788:59:0;102945:15;;102941:205;;103001:133;103028:28;103079:36;103001:4;:133::i;:::-;102977:157;102418:2486;-1:-1:-1;;;;;;102418:2486:0:o;102941:205::-;103239:15;103257:110;103293:13;103321:10;103346;103257:21;:110::i;:::-;103239:128;-1:-1:-1;103382:12:0;;103378:222;;103435:153;103468:15;103506:33;103562:7;103435:10;:153::i;:::-;103411:177;102418:2486;-1:-1:-1;;;;;;;102418:2486:0:o;103378:222::-;-1:-1:-1;;;;;103642:24:0;;103612:27;103642:24;;;:7;:24;;;;;;;;103791:10;103760:42;;:30;;;:42;;;;;;;;;103755:106;;103834:14;103819:30;102418:2486;-1:-1:-1;;;;;;;;102418:2486:0:o;103755:106::-;103965:10;103934:42;;;;:30;;;:42;;;;;;;;103927:49;;-1:-1:-1;;103927:49:0;;;104136:13;:25;;;;;104104:57;;;;;;;;;;;;;;;;;;;104136:25;;104104:57;;;104136:25;104104:57;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;104104:57:0;;;;;;;;;;;;;;;;-1:-1:-1;;104186:20:0;;104104:57;;-1:-1:-1;104186:20:0;;-1:-1:-1;104172:11:0;;-1:-1:-1;;104252:165:0;104276:3;104272:1;:7;104252:165;;;104325:6;-1:-1:-1;;;;;104305:26:0;:13;104319:1;104305:16;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1;;;;;104305:26:0;;104301:105;;;104365:1;104352:14;;104385:5;;104301:105;104281:3;;;;:::i;:::-;;;;104252:165;;;;104546:3;104533:10;:16;104526:24;;;;:::i;:::-;104696:10;104652:27;104682:25;;;:13;:25;;;;;104754:17;;104682:25;;104754:21;;104774:1;;104754:21;:::i;:::-;104743:33;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;104743:33:0;104718:10;104729;104718:22;;;;;;;;:::i;:::-;;;;;;;;;:58;;;;;-1:-1:-1;;;;;104718:58:0;;;;;-1:-1:-1;;;;;104718:58:0;;;;;;104787:10;:16;;;;;;;:::i;:::-;;;;;;;;;;-1:-1:-1;;104787:16:0;;;;;-1:-1:-1;;;;;;104787:16:0;;;;;;104821:32;;;;;;104834:6;;104842:10;;104821:32;:::i;:::-;;;;;;;;104881:14;104866:30;102418:2486;-1:-1:-1;;;;;;;;;;;;102418:2486:0:o;4869:90::-;4922:4;4946:5;4950:1;4946;:5;:::i;5291:90::-;5344:4;5368:5;5372:1;5368;:5;:::i;153468:1218::-;-1:-1:-1;;;;;153617:23:0;;153579:35;153617:23;;;:15;:23;;;;;;;;153673:16;:24;;;;;;153617:23;;153729:93;166367:12;153750:16;153729:93;;;;;;;;;;;;;;;;;:6;:93::i;:::-;153917:17;;153708:114;;-1:-1:-1;153833:19:0;;153855:91;;153874:20;;;;;-1:-1:-1;;;153917:17:0;;;153855:4;:91::i;:::-;153833:113;;153975:1;153961:11;:15;:34;;;;;153994:1;153980:11;:15;153961:34;153957:722;;;154012:20;154035:103;154065:6;-1:-1:-1;;;;;154058:27:0;;:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;154106:17;154035:4;:103::i;:::-;154012:126;;154153:19;154175:30;154180:11;154193;154175:4;:30::i;:::-;154153:52;;154220:19;154257:1;154242:12;:16;:112;;154333:21;;;;;;;;154351:1;154333:21;;;154242:112;;;154278:35;154287:11;154300:12;154278:8;:35::i;:::-;154420:37;;;;;;;;;154438:17;;-1:-1:-1;;;;;154438:17:0;154420:37;;154220:134;;-1:-1:-1;154389:147:0;;154415:50;;154220:134;154415:4;:50::i;:::-;:59;154389:147;;;;;;;;;;;;;;;;;:7;:147::i;:::-;-1:-1:-1;;;;;154369:167:0;-1:-1:-1;;;154551:31:0;;;;;;;-1:-1:-1;153957:722:0;;-1:-1:-1;;153957:722:0;;154604:15;;154600:79;;154636:31;;;;;-1:-1:-1;;;154636:31:0;-1:-1:-1;;;;;154636:31:0;;;;;;153568:1118;;;;153468:1218;;:::o;157103:1954::-;-1:-1:-1;;;;;157590:23:0;;;157552:35;157590:23;;;:15;:23;;;;;;;;157646:17;;157698;:25;;;;;:35;;;;;;;;;;;;;;-1:-1:-1;;;;;157646:17:0;;;157843:49;;;;157590:23;;157909:18;;:53;;;;-1:-1:-1;;;;157931:31:0;;;157909:53;157905:364;;;-1:-1:-1;;;;157905:364:0;158370:24;158397:76;;;;;;;;158429:32;158434:11;158447:13;158429:4;:32::i;:::-;158397:76;;158530:44;;-1:-1:-1;;;158530:44:0;;-1:-1:-1;;;;;4115:32:1;;;158530:44:0;;;4097:51:1;158370:103:0;;-1:-1:-1;158486:22:0;;158511:106;;158530:34;;;;;;4070:18:1;;158530:44:0;;;;;;;;;;;;;;;;;;;;;;158511:106;158486:131;;158704:21;158728:32;158733:14;158749:10;158728:4;:32::i;:::-;-1:-1:-1;;;;;158804:21:0;;158773:23;158804:21;;;:11;:21;;;;;;158704:56;;-1:-1:-1;158773:23:0;158799:42;;158704:56;158799:4;:42::i;:::-;-1:-1:-1;;;;;158852:21:0;;;;;;;:11;:21;;;;;;;;;:39;;;158909:140;;18915:25:1;;;18956:18;;;18949:34;;;158852:39:0;;-1:-1:-1;158852:21:0;;158909:140;;;;;;18888:18:1;158909:140:0;;;;;;;157242:1815;;;;;;;157103:1954;;;:::o;150062:148::-;150116:4;150154:5;;-1:-1:-1;;;;;150154:5:0;150140:10;:19;;:62;;-1:-1:-1;150177:25:0;;-1:-1:-1;;;;;150177:25:0;150163:10;:39;150140:62;150133:69;;150062:148;:::o;162599:396::-;162759:7;;162802:30;;-1:-1:-1;;;162802:30:0;;162826:4;162802:30;;;4097:51:1;162692:7:0;;-1:-1:-1;;;;;162759:7:0;;162692;;162759;;162802:15;;4070:18:1;;162802:30:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;162778:54;;162856:1;162847:6;:10;:37;;;;;162871:13;162861:6;:23;;162847:37;162843:121;;;162901:28;;-1:-1:-1;;;162901:28:0;;-1:-1:-1;;;;;25273:32:1;;;162901:28:0;;;25255:51:1;25322:18;;;25315:34;;;162901:14:0;;;;;25228:18:1;;162901:28:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;162951:1;162944:8;;;;;;162843:121;-1:-1:-1;162981:6:0;;162599:396;-1:-1:-1;;;162599:396:0:o;127719:3654::-;127957:5;127977:7;127999;128034:37;;:::i;:::-;-1:-1:-1;;;;;128214:22:0;;128119:12;128214:22;;;:13;:22;;;;;;;;128189:47;;;;;;;;;;;;;;;;;128119:12;;128189:47;;128214:22;128189:47;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;128189:47:0;;;;;;;;;;;;;;;;;;;;;;;128252:9;128247:2643;128271:6;:13;128267:1;:17;128247:2643;;;128306:12;128321:6;128328:1;128321:9;;;;;;;;:::i;:::-;;;;;;;;;;;128574:33;;-1:-1:-1;;;128574:33:0;;-1:-1:-1;;;;;4115:32:1;;;128574:33:0;;;4097:51:1;128321:9:0;;-1:-1:-1;128574:24:0;;;;;;4070:18:1;;128574:33:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;128531:25;;;128415:192;128494:18;;;128415:192;128457:18;;;128415:192;;-1:-1:-1;128626:9:0;;128622:183;;128762:20;128784:1;128787;128754:35;;;;;;;;;;;;;128622:183;128843:97;;;;;;;;;-1:-1:-1;;;;;128876:23:0;;;-1:-1:-1;128876:23:0;;;:7;:23;;;;;:48;;;128843:97;;128819:21;;;:121;;;;128975:42;;;;;;;-1:-1:-1;;;128990:25:0;128975:42;;128955:17;;;:62;129115:6;;;:32;;-1:-1:-1;;;129115:32:0;;;;;4097:51:1;;;;129115:32:0;;:6;;;:25;;4070:18:1;;;;;128843:97:0;129115:32;;;;;:6;:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;129088:24;;;:59;;;129162:102;;129224:17;129243:1;129246;129216:32;;;;;;;;;;;;;129162:102;129297:41;;;;;;;;;129312:24;;;;129297:41;;129278:16;;;:60;129498:21;;;;129521:17;;;;129470:119;;129493:46;;:4;:46::i;:::-;129558:4;:16;;;129470:4;:119::i;:::-;129449:18;;;:140;;;129771:18;;;;129808;;129690:151;;129449:140;129771:18;129690:25;:151::i;:::-;129669:172;;129998:16;;;;130033:18;;;;130070:25;;;;129954:156;;129998:16;130033:18;129954:25;:156::i;:::-;129926:25;;;:184;-1:-1:-1;;;;;130198:21:0;;;;;;;130194:685;;;130375:168;130423:4;:18;;;130464:12;130499:4;:25;;;130375;:168::i;:::-;130347:25;;;:196;;;130745:16;;;;130697:166;;130784:12;;130697:25;:166::i;:::-;130669:25;;;:194;130194:685;-1:-1:-1;128286:3:0;;;;:::i;:::-;;;;128247:2643;;;-1:-1:-1;130999:25:0;;;;130978:18;;:46;130974:392;;;131121:25;;;;131100:18;;131067:14;;131100:46;;;:::i;:::-;131165:1;131041:140;;;;;;;;;;;130974:392;131240:14;131273:1;131321:4;:18;;;131293:4;:25;;;:46;;;;:::i;:::-;131214:140;;;;;;;;;;;152139:1099;-1:-1:-1;;;;;152244:23:0;;152206:35;152244:23;;;:15;:23;;;;;;;;152300:16;:24;;;;;;152244:23;;152356:93;166367:12;152377:16;166285:102;152356:93;152544:17;;152335:114;;-1:-1:-1;152460:19:0;;152482:91;;152501:20;;;;;-1:-1:-1;;;152544:17:0;;;152482:4;:91::i;:::-;152460:113;;152602:1;152588:11;:15;:34;;;;;152621:1;152607:11;:15;152588:34;152584:647;;;152639:20;152669:6;-1:-1:-1;;;;;152662:26:0;;:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;152639:51;;152705:19;152727:30;152732:11;152745;152727:4;:30::i;:::-;152705:52;;152772:19;152809:1;152794:12;:16;:112;;152885:21;;;;;;;;152903:1;152885:21;;;152794:112;;;152830:35;152839:11;152852:12;152830:8;:35::i;:::-;152972:37;;;;;;;;;152990:17;;-1:-1:-1;;;;;152990:17:0;152972:37;;152772:134;;-1:-1:-1;152941:147:0;;152967:50;;152772:134;152967:4;:50::i;152941:147::-;-1:-1:-1;;;;;152921:167:0;-1:-1:-1;;;153103:31:0;;;;;;;-1:-1:-1;152584:647:0;;-1:-1:-1;;152584:647:0;;153156:15;;153152:79;;153188:31;;;;;-1:-1:-1;;;153188:31:0;-1:-1:-1;;;;;153188:31:0;;;;;;152195:1043;;;;152139:1099;:::o;154942:1804::-;-1:-1:-1;;;;;155365:23:0;;;155327:35;155365:23;;;:15;:23;;;;;;;;155421:17;;155473;:25;;;;;:35;;;;;;;;;;;;;;-1:-1:-1;;;;;155421:17:0;;;155617:49;;;;155365:23;;155683:18;;:53;;;;-1:-1:-1;;;;155705:31:0;;;155683:53;155679:364;;;-1:-1:-1;;;;155679:364:0;156137:24;156164:76;;;;;;;;156196:32;156201:11;156214:13;156196:4;:32::i;:::-;156164:76;;156278:34;;-1:-1:-1;;;156278:34:0;;-1:-1:-1;;;;;4115:32:1;;;156278:34:0;;;4097:51:1;156137:103:0;;-1:-1:-1;156253:22:0;;156278:24;;;;;4070:18:1;;156278:34:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;156253:59;;156393:21;156417:32;156422:14;156438:10;156417:4;:32::i;:::-;-1:-1:-1;;;;;156493:21:0;;156462:23;156493:21;;;:11;:21;;;;;;156393:56;;-1:-1:-1;156462:23:0;156488:42;;156393:56;156488:4;:42::i;:::-;-1:-1:-1;;;;;156541:21:0;;;;;;;:11;:21;;;;;;;;;:39;;;156598:140;;18915:25:1;;;18956:18;;;18949:34;;;156541:39:0;;-1:-1:-1;156541:21:0;;156598:140;;;;;;18888:18:1;156598:140:0;;;;;;;155017:1729;;;;;;;154942:1804;;:::o;12342:153::-;12403:4;12425:33;12438:3;12433:9;;;;;;;;:::i;:::-;12449:4;12444:10;;;;;;;;:::i;:::-;12425:33;;;8764:25:1;;;8820:2;8805:18;;8798:34;;;;12456:1:0;8848:18:1;;;8841:34;8752:2;8737:18;12425:33:0;;;;;;;12483:3;12478:9;;;;;;;;:::i;125270:380::-;125388:5;125408:7;125430;125485:157;125543:7;125584:1;125606;125626;125485:39;:157::i;:::-;125465:177;;;;;;125270:380;;;;;:::o;2821:174::-;2899:4;2916:18;2937:15;2942:1;2945:6;2937:4;:15::i;:::-;2916:36;;2970:17;2979:7;2970:8;:17::i;6293:90::-;6346:4;6370:5;6374:1;6370;:5;:::i;141193:252::-;141262:9;141257:139;141281:10;:17;141277:21;;141257:139;;;141352:6;-1:-1:-1;;;;;141328:31:0;:10;141339:1;141328:13;;;;;;;;:::i;:::-;;;;;;;;;;;-1:-1:-1;;;;;141328:13:0;:31;;141320:64;;;;-1:-1:-1;;;141320:64:0;;36034:2:1;141320:64:0;;;36016:21:1;36073:2;36053:18;;;36046:30;-1:-1:-1;;;36092:18:1;;;36085:50;36152:18;;141320:64:0;35832:344:1;141320:64:0;141300:3;;;;:::i;:::-;;;;141257:139;;;-1:-1:-1;141406:10:0;:31;;;;;;;-1:-1:-1;141406:31:0;;;;;;;;-1:-1:-1;;;;;;141406:31:0;-1:-1:-1;;;;;141406:31:0;;;;;;;;;;141193:252::o;141453:867::-;141516:18;141537:93;166367:12;141558:16;166285:102;141537:93;-1:-1:-1;;;;;141681:23:0;;141643:35;141681:23;;;:15;:23;;;;;;;;141753:15;:23;;;;;;141858:17;;141516:114;;-1:-1:-1;141681:23:0;;-1:-1:-1;;;;;141858:17:0;141854:156;;141962:36;;-1:-1:-1;;;;;;141962:36:0;-1:-1:-1;;;141962:36:0;;;141854:156;142026:17;;-1:-1:-1;;;;;142026:17:0;142022:156;;142130:36;;-1:-1:-1;;;;;;142130:36:0;-1:-1:-1;;;142130:36:0;;;142022:156;142281:31;;;;;;-1:-1:-1;;;142281:31:0;-1:-1:-1;;;;;142281:31:0;;;;;;;;142261:51;;;;;;;;;;-1:-1:-1;141453:867:0:o;150512:1397::-;-1:-1:-1;;;;;150677:24:0;;150653:21;150677:24;;;:7;:24;;;;;150720:15;;;;150712:53;;;;-1:-1:-1;;;150712:53:0;;36383:2:1;150712:53:0;;;36365:21:1;36422:2;36402:18;;;36395:30;36461:27;36441:18;;;36434:55;36506:18;;150712:53:0;36181:349:1;150712:53:0;-1:-1:-1;;;;;150782:33:0;;;;;;:16;:33;;;;;;:48;;150778:511;;151068:38;151098:6;151068:21;:38::i;:::-;-1:-1:-1;;;;;151167:33:0;;;;;;:16;:33;;;;;;;:47;;;151234:43;;;;;151203:11;4844:25:1;;4832:2;4817:18;;4698:177;151234:43:0;;;;;;;;150778:511;-1:-1:-1;;;;;151305:33:0;;;;;;:16;:33;;;;;;:48;;151301:601;;151591:22;151616:37;;;;;;;;151631:6;-1:-1:-1;;;;;151631:18:0;;:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;151616:37;;151591:62;-1:-1:-1;151668:51:0;151698:6;151591:62;151668:21;:51::i;:::-;-1:-1:-1;;;;;151780:33:0;;;;;;:16;:33;;;;;;;:47;;;151847:43;;;;;151816:11;4844:25:1;;4832:2;4817:18;;4698:177;151847:43:0;;;;;;;;151355:547;150642:1267;150512:1397;;;:::o;107988:1062::-;-1:-1:-1;;;;;108157:15:0;;108132:7;108157:15;;;:7;:15;;;;;:24;;;108152:97;;108213:23;108205:32;;108152:97;-1:-1:-1;;;;;108360:15:0;;;;;;;:7;:15;;;;;;;;:43;;;;;:33;;;;:43;;;;;;108355:107;;108435:14;108427:23;;108355:107;108581:9;108620:17;108651:165;108709:8;108743:6;108769:12;108800:1;108651:39;:165::i;:::-;108566:250;;-1:-1:-1;108566:250:0;;-1:-1:-1;108838:14:0;;-1:-1:-1;108831:3:0;:21;;;;;;;;:::i;:::-;;108827:73;;108884:3;108876:12;;;;;;;;:::i;:::-;108869:19;;;;;;108827:73;108914:13;;108910:90;;108959:28;108951:37;;100984:1041;-1:-1:-1;;;;;101135:24:0;;101082:5;101135:24;;;:7;:24;;;;;101177:21;;;;101172:135;;101272:23;101265:30;;;;;101172:135;-1:-1:-1;;;;;101323:40:0;;;;;;:30;;;:40;;;;;;;;:48;;:40;:48;101319:133;;;101426:14;101419:21;;;;;101319:133;-1:-1:-1;;;;;101840:40:0;;;;;;;:30;;;:40;;;;;;;;:47;;101883:4;-1:-1:-1;;101840:47:0;;;;;;;;101898:13;:23;;;;;:36;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;101898:36:0;;;;;;;;;;;101952:31;;;;;101898:36;;101840:40;;101952:31;:::i;:::-;;;;;;;;-1:-1:-1;102003:14:0;;100984:1041;-1:-1:-1;;;100984:1041:0:o;5389:159::-;-1:-1:-1;;;;;;;;;;;;5484:56:0;;;;;;;;2099:4;5499:28;5504:1;:10;;;5516:1;:10;;;5499:4;:28::i;:::-;:39;;;;:::i;:::-;5484:56;;5477:63;5389:159;-1:-1:-1;;;5389:159:0:o;6391:164::-;-1:-1:-1;;;;;;;;;;;;6486:61:0;;;;;;;;6501:44;6506:26;6511:1;:10;;;2099:4;6506;:26::i;:::-;6534:10;;6501:4;:44::i;12618:187::-;12703:4;12725:43;12738:3;12733:9;;;;;;;;:::i;:::-;12749:4;12744:10;;;;;;;;:::i;:::-;12725:43;;;8764:25:1;;;8820:2;8805:18;;8798:34;;;;8848:18;;8841:34;;;8752:2;8737:18;12725:43:0;;;;;;;12793:3;12788:9;;;;;;;;:::i;4376:161::-;4451:6;4489:12;4482:5;4478:9;;4470:32;;;;-1:-1:-1;;;4470:32:0;;;;;;;;:::i;:::-;-1:-1:-1;4527:1:0;;4376:161;-1:-1:-1;;4376:161:0:o;6704:126::-;6763:4;6787:35;6792:17;6797:1;2099:4;6792;:17::i;:::-;6811:10;;6787:4;:35::i;7413:147::-;-1:-1:-1;;;;;;;;;;;;7503:49:0;;;;;;;;7521:29;7526:20;7531:1;-1:-1:-1;;;7526:4:0;:20::i;:::-;7548:1;7521:4;:29::i;4701:160::-;-1:-1:-1;;;;;;;;;;;;4805:48:0;;;;;;;;4823:28;4828:1;:10;;;4840:1;:10;;;4823:4;:28::i;4203:165::-;4279:7;4319:12;-1:-1:-1;;;4307:10:0;;4299:33;;;;-1:-1:-1;;;4299:33:0;;;;;;;;:::i;6158:127::-;6220:4;-1:-1:-1;;;6244:19:0;6249:1;6252;:10;;;6244:4;:19::i;:::-;:33;;;;:::i;3140:208::-;3238:4;3255:18;3276:15;3281:1;3284:6;3276:4;:15::i;:::-;3255:36;;3309:31;3314:17;3323:7;3314:8;:17::i;:::-;3333:6;3309:4;:31::i;5556:133::-;-1:-1:-1;;;;;;;;;;;;5645:36:0;;;;;;;;5660:19;5665:1;:10;;;5677:1;5660:4;:19::i;2495:213::-;2677:12;;2552:4;;2677:23;;2099:4;;2677:23;:::i;7315:90::-;7368:4;7392:5;7396:1;7392;:5;:::i;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;206:367:1:-;269:8;279:6;333:3;326:4;318:6;314:17;310:27;300:55;;351:1;348;341:12;300:55;-1:-1:-1;374:20:1;;417:18;406:30;;403:50;;;449:1;446;439:12;403:50;486:4;478:6;474:17;462:29;;546:3;539:4;529:6;526:1;522:14;514:6;510:27;506:38;503:47;500:67;;;563:1;560;553:12;500:67;206:367;;;;;:::o;578:773::-;700:6;708;716;724;777:2;765:9;756:7;752:23;748:32;745:52;;;793:1;790;783:12;745:52;833:9;820:23;862:18;903:2;895:6;892:14;889:34;;;919:1;916;909:12;889:34;958:70;1020:7;1011:6;1000:9;996:22;958:70;:::i;:::-;1047:8;;-1:-1:-1;932:96:1;-1:-1:-1;1135:2:1;1120:18;;1107:32;;-1:-1:-1;1151:16:1;;;1148:36;;;1180:1;1177;1170:12;1148:36;;1219:72;1283:7;1272:8;1261:9;1257:24;1219:72;:::i;:::-;578:773;;;;-1:-1:-1;1310:8:1;-1:-1:-1;;;;578:773:1:o;1356:139::-;-1:-1:-1;;;;;1439:31:1;;1429:42;;1419:70;;1485:1;1482;1475:12;1500:118;1586:5;1579:13;1572:21;1565:5;1562:32;1552:60;;1608:1;1605;1598:12;1623:405;1703:6;1711;1764:2;1752:9;1743:7;1739:23;1735:32;1732:52;;;1780:1;1777;1770:12;1732:52;1819:9;1806:23;1838:39;1871:5;1838:39;:::i;:::-;1896:5;-1:-1:-1;1953:2:1;1938:18;;1925:32;1966:30;1925:32;1966:30;:::i;:::-;2015:7;2005:17;;;1623:405;;;;;:::o;2033:127::-;2094:10;2089:3;2085:20;2082:1;2075:31;2125:4;2122:1;2115:15;2149:4;2146:1;2139:15;2165:275;2236:2;2230:9;2301:2;2282:13;;-1:-1:-1;;2278:27:1;2266:40;;2336:18;2321:34;;2357:22;;;2318:62;2315:88;;;2383:18;;:::i;:::-;2419:2;2412:22;2165:275;;-1:-1:-1;2165:275:1:o;2445:191::-;2513:4;2546:18;2538:6;2535:30;2532:56;;;2568:18;;:::i;:::-;-1:-1:-1;2613:1:1;2609:14;2625:4;2605:25;;2445:191::o;2641:761::-;2703:5;2756:3;2749:4;2741:6;2737:17;2733:27;2723:55;;2774:1;2771;2764:12;2723:55;2810:6;2797:20;2836:4;2860:68;2876:51;2924:2;2876:51;:::i;:::-;2860:68;:::i;:::-;2962:15;;;3048:1;3044:10;;;;3032:23;;3028:32;;;2993:12;;;;3072:15;;;3069:35;;;3100:1;3097;3090:12;3069:35;3136:2;3128:6;3124:15;3148:225;3164:6;3159:3;3156:15;3148:225;;;3244:3;3231:17;3261:39;3294:5;3261:39;:::i;:::-;3313:18;;3351:12;;;;3181;;3148:225;;;-1:-1:-1;3391:5:1;2641:761;-1:-1:-1;;;;;;2641:761:1:o;3407:514::-;3515:6;3523;3576:2;3564:9;3555:7;3551:23;3547:32;3544:52;;;3592:1;3589;3582:12;3544:52;3631:9;3618:23;3650:39;3683:5;3650:39;:::i;:::-;3708:5;-1:-1:-1;3764:2:1;3749:18;;3736:32;3791:18;3780:30;;3777:50;;;3823:1;3820;3813:12;3777:50;3846:69;3907:7;3898:6;3887:9;3883:22;3846:69;:::i;:::-;3836:79;;;3407:514;;;;;:::o;4159:274::-;4237:6;4290:2;4278:9;4269:7;4265:23;4261:32;4258:52;;;4306:1;4303;4296:12;4258:52;4345:9;4332:23;4364:39;4397:5;4364:39;:::i;4880:691::-;4975:6;4983;4991;4999;5007;5060:3;5048:9;5039:7;5035:23;5031:33;5028:53;;;5077:1;5074;5067:12;5028:53;5116:9;5103:23;5135:39;5168:5;5135:39;:::i;:::-;5193:5;-1:-1:-1;5250:2:1;5235:18;;5222:32;5263:41;5222:32;5263:41;:::i;:::-;5323:7;-1:-1:-1;5382:2:1;5367:18;;5354:32;5395:41;5354:32;5395:41;:::i;:::-;4880:691;;;;-1:-1:-1;5455:7:1;;5509:2;5494:18;;5481:32;;-1:-1:-1;5560:3:1;5545:19;5532:33;;4880:691;-1:-1:-1;;4880:691:1:o;5784:622::-;5870:6;5878;5886;5894;5947:3;5935:9;5926:7;5922:23;5918:33;5915:53;;;5964:1;5961;5954:12;5915:53;6003:9;5990:23;6022:39;6055:5;6022:39;:::i;:::-;6080:5;-1:-1:-1;6137:2:1;6122:18;;6109:32;6150:41;6109:32;6150:41;:::i;:::-;6210:7;-1:-1:-1;6269:2:1;6254:18;;6241:32;6282:41;6241:32;6282:41;:::i;:::-;5784:622;;;;-1:-1:-1;6342:7:1;;6396:2;6381:18;6368:32;;-1:-1:-1;;5784:622:1:o;6411:323::-;6479:6;6487;6540:2;6528:9;6519:7;6515:23;6511:32;6508:52;;;6556:1;6553;6546:12;6508:52;6595:9;6582:23;6614:39;6647:5;6614:39;:::i;:::-;6672:5;6724:2;6709:18;;;;6696:32;;-1:-1:-1;;;6411:323:1:o;6739:241::-;6795:6;6848:2;6836:9;6827:7;6823:23;6819:32;6816:52;;;6864:1;6861;6854:12;6816:52;6903:9;6890:23;6922:28;6944:5;6922:28;:::i;6985:180::-;7044:6;7097:2;7085:9;7076:7;7072:23;7068:32;7065:52;;;7113:1;7110;7103:12;7065:52;-1:-1:-1;7136:23:1;;6985:180;-1:-1:-1;6985:180:1:o;7170:541::-;7256:6;7264;7272;7280;7333:3;7321:9;7312:7;7308:23;7304:33;7301:53;;;7350:1;7347;7340:12;7301:53;7389:9;7376:23;7408:39;7441:5;7408:39;:::i;:::-;7466:5;-1:-1:-1;7523:2:1;7508:18;;7495:32;7536:41;7495:32;7536:41;:::i;:::-;7170:541;;7596:7;;-1:-1:-1;;;;7650:2:1;7635:18;;7622:32;;7701:2;7686:18;7673:32;;7170:541::o;7716:841::-;7820:6;7828;7836;7844;7852;7860;7913:3;7901:9;7892:7;7888:23;7884:33;7881:53;;;7930:1;7927;7920:12;7881:53;7969:9;7956:23;7988:39;8021:5;7988:39;:::i;:::-;8046:5;-1:-1:-1;8103:2:1;8088:18;;8075:32;8116:41;8075:32;8116:41;:::i;:::-;8176:7;-1:-1:-1;8235:2:1;8220:18;;8207:32;8248:41;8207:32;8248:41;:::i;:::-;8308:7;-1:-1:-1;8367:2:1;8352:18;;8339:32;8380:41;8339:32;8380:41;:::i;:::-;7716:841;;;;-1:-1:-1;7716:841:1;;8494:3;8479:19;;8466:33;;8546:3;8531:19;;;8518:33;;-1:-1:-1;7716:841:1;-1:-1:-1;;7716:841:1:o;8886:472::-;8963:6;8971;8979;9032:2;9020:9;9011:7;9007:23;9003:32;9000:52;;;9048:1;9045;9038:12;9000:52;9087:9;9074:23;9106:39;9139:5;9106:39;:::i;:::-;9164:5;-1:-1:-1;9221:2:1;9206:18;;9193:32;9234:41;9193:32;9234:41;:::i;:::-;8886:472;;9294:7;;-1:-1:-1;;;9348:2:1;9333:18;;;;9320:32;;8886:472::o;10151:772::-;10246:6;10254;10262;10270;10278;10331:3;10319:9;10310:7;10306:23;10302:33;10299:53;;;10348:1;10345;10338:12;10299:53;10387:9;10374:23;10406:39;10439:5;10406:39;:::i;:::-;10464:5;-1:-1:-1;10521:2:1;10506:18;;10493:32;10534:41;10493:32;10534:41;:::i;:::-;10594:7;-1:-1:-1;10653:2:1;10638:18;;10625:32;10666:41;10625:32;10666:41;:::i;:::-;10726:7;-1:-1:-1;10785:2:1;10770:18;;10757:32;10798:41;10757:32;10798:41;:::i;:::-;10151:772;;;;-1:-1:-1;10151:772:1;;10912:3;10897:19;10884:33;;10151:772;-1:-1:-1;;10151:772:1:o;11721:753::-;11775:5;11828:3;11821:4;11813:6;11809:17;11805:27;11795:55;;11846:1;11843;11836:12;11795:55;11882:6;11869:20;11908:4;11932:68;11948:51;11996:2;11948:51;:::i;11932:68::-;12034:15;;;12120:1;12116:10;;;;12104:23;;12100:32;;;12065:12;;;;12144:15;;;12141:35;;;12172:1;12169;12162:12;12141:35;12208:2;12200:6;12196:15;12220:225;12236:6;12231:3;12228:15;12220:225;;;12316:3;12303:17;12333:39;12366:5;12333:39;:::i;:::-;12385:18;;12423:12;;;;12253;;12220:225;;12479:883;12624:6;12632;12640;12648;12701:3;12689:9;12680:7;12676:23;12672:33;12669:53;;;12718:1;12715;12708:12;12669:53;12758:9;12745:23;12787:18;12828:2;12820:6;12817:14;12814:34;;;12844:1;12841;12834:12;12814:34;12867:61;12920:7;12911:6;12900:9;12896:22;12867:61;:::i;:::-;12857:71;;12981:2;12970:9;12966:18;12953:32;12937:48;;13010:2;13000:8;12997:16;12994:36;;;13026:1;13023;13016:12;12994:36;;13049:71;13112:7;13101:8;13090:9;13086:24;13049:71;:::i;:::-;13039:81;;;13170:2;13159:9;13155:18;13142:32;13183:28;13205:5;13183:28;:::i;:::-;13230:5;-1:-1:-1;13287:2:1;13272:18;;13259:32;13300:30;13259:32;13300:30;:::i;:::-;12479:883;;;;-1:-1:-1;12479:883:1;;-1:-1:-1;;12479:883:1:o;14233:419::-;14316:6;14324;14377:2;14365:9;14356:7;14352:23;14348:32;14345:52;;;14393:1;14390;14383:12;14345:52;14432:9;14419:23;14451:39;14484:5;14451:39;:::i;:::-;14509:5;-1:-1:-1;14566:2:1;14551:18;;14538:32;14579:41;14538:32;14579:41;:::i;15140:670::-;15194:5;15247:3;15240:4;15232:6;15228:17;15224:27;15214:55;;15265:1;15262;15255:12;15214:55;15301:6;15288:20;15327:4;15351:68;15367:51;15415:2;15367:51;:::i;15351:68::-;15453:15;;;15539:1;15535:10;;;;15523:23;;15519:32;;;15484:12;;;;15563:15;;;15560:35;;;15591:1;15588;15581:12;15560:35;15627:2;15619:6;15615:15;15639:142;15655:6;15650:3;15647:15;15639:142;;;15721:17;;15709:30;;15759:12;;;;15672;;15639:142;;15815:844;15982:6;15990;15998;16051:2;16039:9;16030:7;16026:23;16022:32;16019:52;;;16067:1;16064;16057:12;16019:52;16107:9;16094:23;16136:18;16177:2;16169:6;16166:14;16163:34;;;16193:1;16190;16183:12;16163:34;16216:69;16277:7;16268:6;16257:9;16253:22;16216:69;:::i;:::-;16206:79;;16338:2;16327:9;16323:18;16310:32;16294:48;;16367:2;16357:8;16354:16;16351:36;;;16383:1;16380;16373:12;16351:36;16406:63;16461:7;16450:8;16439:9;16435:24;16406:63;:::i;:::-;16396:73;;16522:2;16511:9;16507:18;16494:32;16478:48;;16551:2;16541:8;16538:16;16535:36;;;16567:1;16564;16557:12;16535:36;;16590:63;16645:7;16634:8;16623:9;16619:24;16590:63;:::i;:::-;16580:73;;;15815:844;;;;;:::o;16664:673::-;16850:2;16902:21;;;16972:13;;16875:18;;;16994:22;;;16821:4;;16850:2;17073:15;;;;17047:2;17032:18;;;16821:4;17116:195;17130:6;17127:1;17124:13;17116:195;;;17195:13;;-1:-1:-1;;;;;17191:39:1;17179:52;;17286:15;;;;17251:12;;;;17227:1;17145:9;17116:195;;;-1:-1:-1;17328:3:1;;16664:673;-1:-1:-1;;;;;;16664:673:1:o;17751:348::-;17835:6;17888:2;17876:9;17867:7;17863:23;17859:32;17856:52;;;17904:1;17901;17894:12;17856:52;17944:9;17931:23;17977:18;17969:6;17966:30;17963:50;;;18009:1;18006;17999:12;17963:50;18032:61;18085:7;18076:6;18065:9;18061:22;18032:61;:::i;18104:632::-;18275:2;18327:21;;;18397:13;;18300:18;;;18419:22;;;18246:4;;18275:2;18498:15;;;;18472:2;18457:18;;;18246:4;18541:169;18555:6;18552:1;18549:13;18541:169;;;18616:13;;18604:26;;18685:15;;;;18650:12;;;;18577:1;18570:9;18541:169;;20488:127;20549:10;20544:3;20540:20;20537:1;20530:31;20580:4;20577:1;20570:15;20604:4;20601:1;20594:15;20620:127;20681:10;20676:3;20672:20;20669:1;20662:31;20712:4;20709:1;20702:15;20736:4;20733:1;20726:15;20752:125;20792:4;20820:1;20817;20814:8;20811:34;;;20825:18;;:::i;:::-;-1:-1:-1;20862:9:1;;20752:125::o;20882:135::-;20921:3;-1:-1:-1;;20942:17:1;;20939:43;;;20962:18;;:::i;:::-;-1:-1:-1;21009:1:1;20998:13;;20882:135::o;21022:404::-;21224:2;21206:21;;;21263:2;21243:18;;;21236:30;21302:34;21297:2;21282:18;;21275:62;-1:-1:-1;;;21368:2:1;21353:18;;21346:38;21416:3;21401:19;;21022:404::o;21431:403::-;21633:2;21615:21;;;21672:2;21652:18;;;21645:30;21711:34;21706:2;21691:18;;21684:62;-1:-1:-1;;;21777:2:1;21762:18;;21755:37;21824:3;21809:19;;21431:403::o;21839:346::-;22041:2;22023:21;;;22080:2;22060:18;;;22053:30;-1:-1:-1;;;22114:2:1;22099:18;;22092:52;22176:2;22161:18;;21839:346::o;22719:259::-;22789:6;22842:2;22830:9;22821:7;22817:23;22813:32;22810:52;;;22858:1;22855;22848:12;22810:52;22890:9;22884:16;22909:39;22942:5;22909:39;:::i;23391:184::-;23461:6;23514:2;23502:9;23493:7;23489:23;23485:32;23482:52;;;23530:1;23527;23520:12;23482:52;-1:-1:-1;23553:16:1;;23391:184;-1:-1:-1;23391:184:1:o;23930:127::-;23991:10;23986:3;23982:20;23979:1;23972:31;24022:4;24019:1;24012:15;24046:4;24043:1;24036:15;24062:304;-1:-1:-1;;;;;24292:15:1;;;24274:34;;24344:15;;24339:2;24324:18;;24317:43;24224:2;24209:18;;24062:304::o;30769:245::-;30836:6;30889:2;30877:9;30868:7;30864:23;30860:32;30857:52;;;30905:1;30902;30895:12;30857:52;30937:9;30931:16;30956:28;30978:5;30956:28;:::i;33108:127::-;33169:10;33164:3;33160:20;33157:1;33150:31;33200:4;33197:1;33190:15;33224:4;33221:1;33214:15;33959:368;34056:6;34064;34072;34080;34133:3;34121:9;34112:7;34108:23;34104:33;34101:53;;;34150:1;34147;34140:12;34101:53;-1:-1:-1;;34173:16:1;;34229:2;34214:18;;34208:25;34273:2;34258:18;;34252:25;34317:2;34302:18;;;34296:25;34173:16;;34208:25;;-1:-1:-1;34296:25:1;;-1:-1:-1;33959:368:1;-1:-1:-1;33959:368:1:o;34738:127::-;34799:10;34794:3;34790:20;34787:1;34780:31;34830:4;34827:1;34820:15;34854:4;34851:1;34844:15;35194:128;35234:3;35265:1;35261:6;35258:1;35255:13;35252:39;;;35271:18;;:::i;:::-;-1:-1:-1;35307:9:1;;35194:128::o;35659:168::-;35699:7;35765:1;35761;35757:6;35753:14;35750:1;35747:21;35742:1;35735:9;35728:17;35724:45;35721:71;;;35772:18;;:::i;:::-;-1:-1:-1;35812:9:1;;35659:168::o;36535:217::-;36575:1;36601;36591:132;;36645:10;36640:3;36636:20;36633:1;36626:31;36680:4;36677:1;36670:15;36708:4;36705:1;36698:15;36591:132;-1:-1:-1;36737:9:1;;36535:217::o;36757:597::-;36869:4;36898:2;36927;36916:9;36909:21;36959:6;36953:13;37002:6;36997:2;36986:9;36982:18;36975:34;37027:1;37037:140;37051:6;37048:1;37045:13;37037:140;;;37146:14;;;37142:23;;37136:30;37112:17;;;37131:2;37108:26;37101:66;37066:10;;37037:140;;;37195:6;37192:1;37189:13;37186:91;;;37265:1;37260:2;37251:6;37240:9;37236:22;37232:31;37225:42;37186:91;-1:-1:-1;37338:2:1;37317:15;-1:-1:-1;;37313:29:1;37298:45;;;;37345:2;37294:54;;36757:597;-1:-1:-1;;;36757:597:1:o
Swarm Source
ipfs://1f07597c60bee14114bc41513326bc40568abb29280b70a84ac674455c23b3ff
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in GLMR
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.