Overview
BTT Balance
0 BTT
BTT Value
$0.00More Info
Private Name Tags
ContractCreator
Loading...
Loading
Contract Name:
CErc20
Compiler Version
v0.8.10+commit.fc410830
Contract Source Code (Solidity)
/** *Submitted for verification at bttcscan.com on 2022-11-16 */ // Sources flattened with hardhat v2.10.1 https://hardhat.org // File contracts/ComptrollerInterface.sol // SPDX-License-Identifier: BSD-3-Clause pragma solidity ^0.8.10; abstract contract ComptrollerInterface { /// @notice Indicator that this is a Comptroller contract (for inspection) bool public constant isComptroller = true; /*** Assets You Are In ***/ function enterMarkets(address[] calldata cTokens) virtual external returns (uint[] memory); function exitMarket(address cToken) virtual external returns (uint); /*** Policy Hooks ***/ function mintAllowed(address cToken, address minter, uint mintAmount) virtual external returns (uint); function mintVerify(address cToken, address minter, uint mintAmount, uint mintTokens) virtual external; function redeemAllowed(address cToken, address redeemer, uint redeemTokens) virtual external returns (uint); function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) virtual external; function borrowAllowed(address cToken, address borrower, uint borrowAmount) virtual external returns (uint); function borrowVerify(address cToken, address borrower, uint borrowAmount) virtual external; function repayBorrowAllowed( address cToken, address payer, address borrower, uint repayAmount) virtual external returns (uint); function repayBorrowVerify( address cToken, address payer, address borrower, uint repayAmount, uint borrowerIndex) virtual external; function liquidateBorrowAllowed( address cTokenBorrowed, address cTokenCollateral, address liquidator, address borrower, uint repayAmount) virtual external returns (uint); function liquidateBorrowVerify( address cTokenBorrowed, address cTokenCollateral, address liquidator, address borrower, uint repayAmount, uint seizeTokens) virtual external; function seizeAllowed( address cTokenCollateral, address cTokenBorrowed, address liquidator, address borrower, uint seizeTokens) virtual external returns (uint); function seizeVerify( address cTokenCollateral, address cTokenBorrowed, address liquidator, address borrower, uint seizeTokens) virtual external; function transferAllowed(address cToken, address src, address dst, uint transferTokens) virtual external returns (uint); function transferVerify(address cToken, address src, address dst, uint transferTokens) virtual external; /*** Liquidity/Liquidation Calculations ***/ function liquidateCalculateSeizeTokens( address cTokenBorrowed, address cTokenCollateral, uint repayAmount) virtual external view returns (uint, uint); } abstract contract InterestRateModel { /// @notice Indicator that this is an InterestRateModel contract (for inspection) bool public constant isInterestRateModel = true; /** * @notice Calculates the current borrow interest rate per block * @param cash The total amount of cash the market has * @param borrows The total amount of borrows the market has outstanding * @param reserves The total amount of reserves the market has * @return The borrow rate per block (as a percentage, and scaled by 1e18) */ function getBorrowRate(uint cash, uint borrows, uint reserves) virtual external view returns (uint); /** * @notice Calculates the current supply interest rate per block * @param cash The total amount of cash the market has * @param borrows The total amount of borrows the market has outstanding * @param reserves The total amount of reserves the market has * @param reserveFactorMantissa The current reserve factor the market has * @return The supply rate per block (as a percentage, and scaled by 1e18) */ function getSupplyRate(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) virtual external view returns (uint); } interface EIP20NonStandardInterface { /** * @notice Get the total number of tokens in circulation * @return The supply of tokens */ function totalSupply() external view returns (uint256); /** * @notice Gets the balance of the specified address * @param owner The address from which the balance will be retrieved * @return balance The balance */ function balanceOf(address owner) external view returns (uint256 balance); /// /// !!!!!!!!!!!!!! /// !!! NOTICE !!! `transfer` does not return a value, in violation of the ERC-20 specification /// !!!!!!!!!!!!!! /// /** * @notice Transfer `amount` tokens from `msg.sender` to `dst` * @param dst The address of the destination account * @param amount The number of tokens to transfer */ function transfer(address dst, uint256 amount) external; /// /// !!!!!!!!!!!!!! /// !!! NOTICE !!! `transferFrom` does not return a value, in violation of the ERC-20 specification /// !!!!!!!!!!!!!! /// /** * @notice Transfer `amount` tokens from `src` to `dst` * @param src The address of the source account * @param dst The address of the destination account * @param amount The number of tokens to transfer */ function transferFrom(address src, address dst, uint256 amount) external; /** * @notice Approve `spender` to transfer up to `amount` from `src` * @dev This will overwrite the approval amount for `spender` * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve) * @param spender The address of the account which may transfer tokens * @param amount The number of tokens that are approved * @return success Whether or not the approval succeeded */ function approve(address spender, uint256 amount) external returns (bool success); /** * @notice Get the current allowance from `owner` for `spender` * @param owner The address of the account which owns the tokens to be spent * @param spender The address of the account which may transfer tokens * @return remaining The number of tokens allowed to be spent */ function allowance(address owner, address spender) external view returns (uint256 remaining); event Transfer(address indexed from, address indexed to, uint256 amount); event Approval(address indexed owner, address indexed spender, uint256 amount); } contract ComptrollerErrorReporter { enum Error { NO_ERROR, UNAUTHORIZED, COMPTROLLER_MISMATCH, INSUFFICIENT_SHORTFALL, INSUFFICIENT_LIQUIDITY, INVALID_CLOSE_FACTOR, INVALID_COLLATERAL_FACTOR, INVALID_LIQUIDATION_INCENTIVE, MARKET_NOT_ENTERED, // no longer possible MARKET_NOT_LISTED, MARKET_ALREADY_LISTED, MATH_ERROR, NONZERO_BORROW_BALANCE, PRICE_ERROR, REJECTION, SNAPSHOT_ERROR, TOO_MANY_ASSETS, TOO_MUCH_REPAY } enum FailureInfo { ACCEPT_ADMIN_PENDING_ADMIN_CHECK, ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK, EXIT_MARKET_BALANCE_OWED, EXIT_MARKET_REJECTION, SET_CLOSE_FACTOR_OWNER_CHECK, SET_CLOSE_FACTOR_VALIDATION, SET_COLLATERAL_FACTOR_OWNER_CHECK, SET_COLLATERAL_FACTOR_NO_EXISTS, SET_COLLATERAL_FACTOR_VALIDATION, SET_COLLATERAL_FACTOR_WITHOUT_PRICE, SET_IMPLEMENTATION_OWNER_CHECK, SET_LIQUIDATION_INCENTIVE_OWNER_CHECK, SET_LIQUIDATION_INCENTIVE_VALIDATION, SET_MAX_ASSETS_OWNER_CHECK, SET_PENDING_ADMIN_OWNER_CHECK, SET_PENDING_IMPLEMENTATION_OWNER_CHECK, SET_PRICE_ORACLE_OWNER_CHECK, SUPPORT_MARKET_EXISTS, SUPPORT_MARKET_OWNER_CHECK, SET_PAUSE_GUARDIAN_OWNER_CHECK } /** * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary * contract-specific code that enables us to report opaque error codes from upgradeable contracts. **/ event Failure(uint error, uint info, uint detail); /** * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator */ function fail(Error err, FailureInfo info) internal returns (uint) { emit Failure(uint(err), uint(info), 0); return uint(err); } /** * @dev use this when reporting an opaque error from an upgradeable collaborator contract */ function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) { emit Failure(uint(err), uint(info), opaqueError); return uint(err); } } contract TokenErrorReporter { uint public constant NO_ERROR = 0; // support legacy return codes error TransferComptrollerRejection(uint256 errorCode); error TransferNotAllowed(); error TransferNotEnough(); error TransferTooMuch(); error MintComptrollerRejection(uint256 errorCode); error MintFreshnessCheck(); error RedeemComptrollerRejection(uint256 errorCode); error RedeemFreshnessCheck(); error RedeemTransferOutNotPossible(); error BorrowComptrollerRejection(uint256 errorCode); error BorrowFreshnessCheck(); error BorrowCashNotAvailable(); error RepayBorrowComptrollerRejection(uint256 errorCode); error RepayBorrowFreshnessCheck(); error LiquidateComptrollerRejection(uint256 errorCode); error LiquidateFreshnessCheck(); error LiquidateCollateralFreshnessCheck(); error LiquidateAccrueBorrowInterestFailed(uint256 errorCode); error LiquidateAccrueCollateralInterestFailed(uint256 errorCode); error LiquidateLiquidatorIsBorrower(); error LiquidateCloseAmountIsZero(); error LiquidateCloseAmountIsUintMax(); error LiquidateRepayBorrowFreshFailed(uint256 errorCode); error LiquidateSeizeComptrollerRejection(uint256 errorCode); error LiquidateSeizeLiquidatorIsBorrower(); error AcceptAdminPendingAdminCheck(); error SetComptrollerOwnerCheck(); error SetPendingAdminOwnerCheck(); error SetReserveFactorAdminCheck(); error SetReserveFactorFreshCheck(); error SetReserveFactorBoundsCheck(); error AddReservesFactorFreshCheck(uint256 actualAddAmount); error ReduceReservesAdminCheck(); error ReduceReservesFreshCheck(); error ReduceReservesCashNotAvailable(); error ReduceReservesCashValidation(); error SetInterestRateModelOwnerCheck(); error SetInterestRateModelFreshCheck(); } contract CTokenStorage { /** * @dev Guard variable for re-entrancy checks */ bool internal _notEntered; /** * @notice EIP-20 token name for this token */ string public name; /** * @notice EIP-20 token symbol for this token */ string public symbol; /** * @notice EIP-20 token decimals for this token */ uint8 public decimals; // Maximum borrow rate that can ever be applied (.0005% / block) uint internal constant borrowRateMaxMantissa = 0.0005e16; // Maximum fraction of interest that can be set aside for reserves uint internal constant reserveFactorMaxMantissa = 1e18; /** * @notice Administrator for this contract */ address payable public admin; /** * @notice Pending administrator for this contract */ address payable public pendingAdmin; /** * @notice Contract which oversees inter-cToken operations */ ComptrollerInterface public comptroller; /** * @notice Model which tells what the current interest rate should be */ InterestRateModel public interestRateModel; // Initial exchange rate used when minting the first CTokens (used when totalSupply = 0) uint internal initialExchangeRateMantissa; /** * @notice Fraction of interest currently set aside for reserves */ uint public reserveFactorMantissa; /** * @notice Block number that interest was last accrued at */ uint public accrualBlockNumber; /** * @notice Accumulator of the total earned interest rate since the opening of the market */ uint public borrowIndex; /** * @notice Total amount of outstanding borrows of the underlying in this market */ uint public totalBorrows; /** * @notice Total amount of reserves of the underlying held in this market */ uint public totalReserves; /** * @notice Total number of tokens in circulation */ uint public totalSupply; // Official record of token balances for each account mapping (address => uint) internal accountTokens; // Approved token transfer amounts on behalf of others mapping (address => mapping (address => uint)) internal transferAllowances; /** * @notice Container for borrow balance information * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action * @member interestIndex Global borrowIndex as of the most recent balance-changing action */ struct BorrowSnapshot { uint principal; uint interestIndex; } // Mapping of account addresses to outstanding borrow balances mapping(address => BorrowSnapshot) internal accountBorrows; /** * @notice Share of seized collateral that is added to reserves */ uint public constant protocolSeizeShareMantissa = 2.8e16; //2.8% } abstract contract CTokenInterface is CTokenStorage { /** * @notice Indicator that this is a CToken contract (for inspection) */ bool public constant isCToken = true; /*** Market Events ***/ /** * @notice Event emitted when interest is accrued */ event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows); /** * @notice Event emitted when tokens are minted */ event Mint(address minter, uint mintAmount, uint mintTokens); /** * @notice Event emitted when tokens are redeemed */ event Redeem(address redeemer, uint redeemAmount, uint redeemTokens); /** * @notice Event emitted when underlying is borrowed */ event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows); /** * @notice Event emitted when a borrow is repaid */ event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows); /** * @notice Event emitted when a borrow is liquidated */ event LiquidateBorrow(address liquidator, address borrower, uint repayAmount, address cTokenCollateral, uint seizeTokens); /*** Admin Events ***/ /** * @notice Event emitted when pendingAdmin is changed */ event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin); /** * @notice Event emitted when pendingAdmin is accepted, which means admin is updated */ event NewAdmin(address oldAdmin, address newAdmin); /** * @notice Event emitted when comptroller is changed */ event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller); /** * @notice Event emitted when interestRateModel is changed */ event NewMarketInterestRateModel(InterestRateModel oldInterestRateModel, InterestRateModel newInterestRateModel); /** * @notice Event emitted when the reserve factor is changed */ event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa); /** * @notice Event emitted when the reserves are added */ event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves); /** * @notice Event emitted when the reserves are reduced */ event ReservesReduced(address admin, uint reduceAmount, uint newTotalReserves); /** * @notice EIP20 Transfer event */ event Transfer(address indexed from, address indexed to, uint amount); /** * @notice EIP20 Approval event */ event Approval(address indexed owner, address indexed spender, uint amount); /*** User Interface ***/ function transfer(address dst, uint amount) virtual external returns (bool); function transferFrom(address src, address dst, uint amount) virtual external returns (bool); function approve(address spender, uint amount) virtual external returns (bool); function allowance(address owner, address spender) virtual external view returns (uint); function balanceOf(address owner) virtual external view returns (uint); function balanceOfUnderlying(address owner) virtual external returns (uint); function getAccountSnapshot(address account) virtual external view returns (uint, uint, uint, uint); function borrowRatePerBlock() virtual external view returns (uint); function supplyRatePerBlock() virtual external view returns (uint); function totalBorrowsCurrent() virtual external returns (uint); function borrowBalanceCurrent(address account) virtual external returns (uint); function borrowBalanceStored(address account) virtual external view returns (uint); function exchangeRateCurrent() virtual external returns (uint); function exchangeRateStored() virtual external view returns (uint); function getCash() virtual external view returns (uint); function accrueInterest() virtual external returns (uint); function seize(address liquidator, address borrower, uint seizeTokens) virtual external returns (uint); /*** Admin Functions ***/ function _setPendingAdmin(address payable newPendingAdmin) virtual external returns (uint); function _acceptAdmin() virtual external returns (uint); function _setComptroller(ComptrollerInterface newComptroller) virtual external returns (uint); function _setReserveFactor(uint newReserveFactorMantissa) virtual external returns (uint); function _reduceReserves(uint reduceAmount) virtual external returns (uint); function _setInterestRateModel(InterestRateModel newInterestRateModel) virtual external returns (uint); } contract CErc20Storage { /** * @notice Underlying asset for this CToken */ address public underlying; } abstract contract CErc20Interface is CErc20Storage { /*** User Interface ***/ function mint(uint mintAmount) virtual external returns (uint); function redeem(uint redeemTokens) virtual external returns (uint); function redeemUnderlying(uint redeemAmount) virtual external returns (uint); function borrow(uint borrowAmount) virtual external returns (uint); function repayBorrow(uint repayAmount) virtual external returns (uint); function repayBorrowBehalf(address borrower, uint repayAmount) virtual external returns (uint); function liquidateBorrow(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) virtual external returns (uint); function sweepToken(EIP20NonStandardInterface token) virtual external; /*** Admin Functions ***/ function _addReserves(uint addAmount) virtual external returns (uint); } contract CDelegationStorage { /** * @notice Implementation address for this contract */ address public implementation; } abstract contract CDelegatorInterface is CDelegationStorage { /** * @notice Emitted when implementation is changed */ event NewImplementation(address oldImplementation, address newImplementation); /** * @notice Called by the admin to update the implementation of the delegator * @param implementation_ The address of the new implementation for delegation * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation */ function _setImplementation(address implementation_, bool allowResign, bytes memory becomeImplementationData) virtual external; } abstract contract CDelegateInterface is CDelegationStorage { /** * @notice Called by the delegator on a delegate to initialize it for duty * @dev Should revert if any issues arise which make it unfit for delegation * @param data The encoded bytes data for any initialization */ function _becomeImplementation(bytes memory data) virtual external; /** * @notice Called by the delegator on a delegate to forfeit its responsibility */ function _resignImplementation() virtual external; } interface EIP20Interface { function name() external view returns (string memory); function symbol() external view returns (string memory); function decimals() external view returns (uint8); /** * @notice Get the total number of tokens in circulation * @return The supply of tokens */ function totalSupply() external view returns (uint256); /** * @notice Gets the balance of the specified address * @param owner The address from which the balance will be retrieved * @return balance The balance */ function balanceOf(address owner) external view returns (uint256 balance); /** * @notice Transfer `amount` tokens from `msg.sender` to `dst` * @param dst The address of the destination account * @param amount The number of tokens to transfer * @return success Whether or not the transfer succeeded */ function transfer(address dst, uint256 amount) external returns (bool success); /** * @notice Transfer `amount` tokens from `src` to `dst` * @param src The address of the source account * @param dst The address of the destination account * @param amount The number of tokens to transfer * @return success Whether or not the transfer succeeded */ function transferFrom(address src, address dst, uint256 amount) external returns (bool success); /** * @notice Approve `spender` to transfer up to `amount` from `src` * @dev This will overwrite the approval amount for `spender` * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve) * @param spender The address of the account which may transfer tokens * @param amount The number of tokens that are approved (-1 means infinite) * @return success Whether or not the approval succeeded */ function approve(address spender, uint256 amount) external returns (bool success); /** * @notice Get the current allowance from `owner` for `spender` * @param owner The address of the account which owns the tokens to be spent * @param spender The address of the account which may transfer tokens * @return remaining The number of tokens allowed to be spent (-1 means infinite) */ function allowance(address owner, address spender) external view returns (uint256 remaining); event Transfer(address indexed from, address indexed to, uint256 amount); event Approval(address indexed owner, address indexed spender, uint256 amount); } contract ExponentialNoError { uint constant expScale = 1e18; uint constant doubleScale = 1e36; uint constant halfExpScale = expScale/2; uint constant mantissaOne = expScale; struct Exp { uint mantissa; } struct Double { uint mantissa; } /** * @dev Truncates the given exp to a whole number value. * For example, truncate(Exp{mantissa: 15 * expScale}) = 15 */ function truncate(Exp memory exp) pure internal returns (uint) { // Note: We are not using careful math here as we're performing a division that cannot fail return exp.mantissa / expScale; } /** * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer. */ function mul_ScalarTruncate(Exp memory a, uint scalar) pure internal returns (uint) { Exp memory product = mul_(a, scalar); return truncate(product); } /** * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer. */ function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) pure internal returns (uint) { Exp memory product = mul_(a, scalar); return add_(truncate(product), addend); } /** * @dev Checks if first Exp is less than second Exp. */ function lessThanExp(Exp memory left, Exp memory right) pure internal returns (bool) { return left.mantissa < right.mantissa; } /** * @dev Checks if left Exp <= right Exp. */ function lessThanOrEqualExp(Exp memory left, Exp memory right) pure internal returns (bool) { return left.mantissa <= right.mantissa; } /** * @dev Checks if left Exp > right Exp. */ function greaterThanExp(Exp memory left, Exp memory right) pure internal returns (bool) { return left.mantissa > right.mantissa; } /** * @dev returns true if Exp is exactly zero */ function isZeroExp(Exp memory value) pure internal returns (bool) { return value.mantissa == 0; } function safe224(uint n, string memory errorMessage) pure internal returns (uint224) { require(n < 2**224, errorMessage); return uint224(n); } function safe32(uint n, string memory errorMessage) pure internal returns (uint32) { require(n < 2**32, errorMessage); return uint32(n); } function add_(Exp memory a, Exp memory b) pure internal returns (Exp memory) { return Exp({mantissa: add_(a.mantissa, b.mantissa)}); } function add_(Double memory a, Double memory b) pure internal returns (Double memory) { return Double({mantissa: add_(a.mantissa, b.mantissa)}); } function add_(uint a, uint b) pure internal returns (uint) { return a + b; } function sub_(Exp memory a, Exp memory b) pure internal returns (Exp memory) { return Exp({mantissa: sub_(a.mantissa, b.mantissa)}); } function sub_(Double memory a, Double memory b) pure internal returns (Double memory) { return Double({mantissa: sub_(a.mantissa, b.mantissa)}); } function sub_(uint a, uint b) pure internal returns (uint) { return a - b; } function mul_(Exp memory a, Exp memory b) pure internal returns (Exp memory) { return Exp({mantissa: mul_(a.mantissa, b.mantissa) / expScale}); } function mul_(Exp memory a, uint b) pure internal returns (Exp memory) { return Exp({mantissa: mul_(a.mantissa, b)}); } function mul_(uint a, Exp memory b) pure internal returns (uint) { return mul_(a, b.mantissa) / expScale; } function mul_(Double memory a, Double memory b) pure internal returns (Double memory) { return Double({mantissa: mul_(a.mantissa, b.mantissa) / doubleScale}); } function mul_(Double memory a, uint b) pure internal returns (Double memory) { return Double({mantissa: mul_(a.mantissa, b)}); } function mul_(uint a, Double memory b) pure internal returns (uint) { return mul_(a, b.mantissa) / doubleScale; } function mul_(uint a, uint b) pure internal returns (uint) { return a * b; } function div_(Exp memory a, Exp memory b) pure internal returns (Exp memory) { return Exp({mantissa: div_(mul_(a.mantissa, expScale), b.mantissa)}); } function div_(Exp memory a, uint b) pure internal returns (Exp memory) { return Exp({mantissa: div_(a.mantissa, b)}); } function div_(uint a, Exp memory b) pure internal returns (uint) { return div_(mul_(a, expScale), b.mantissa); } function div_(Double memory a, Double memory b) pure internal returns (Double memory) { return Double({mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa)}); } function div_(Double memory a, uint b) pure internal returns (Double memory) { return Double({mantissa: div_(a.mantissa, b)}); } function div_(uint a, Double memory b) pure internal returns (uint) { return div_(mul_(a, doubleScale), b.mantissa); } function div_(uint a, uint b) pure internal returns (uint) { return a / b; } function fraction(uint a, uint b) pure internal returns (Double memory) { return Double({mantissa: div_(mul_(a, doubleScale), b)}); } } abstract contract CToken is CTokenInterface, ExponentialNoError, TokenErrorReporter { /** * @notice Initialize the money market * @param comptroller_ The address of the Comptroller * @param interestRateModel_ The address of the interest rate model * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18 * @param name_ EIP-20 name of this token * @param symbol_ EIP-20 symbol of this token * @param decimals_ EIP-20 decimal precision of this token */ function initialize(ComptrollerInterface comptroller_, InterestRateModel interestRateModel_, uint initialExchangeRateMantissa_, string memory name_, string memory symbol_, uint8 decimals_) public { require(msg.sender == admin, "only admin may initialize the market"); require(accrualBlockNumber == 0 && borrowIndex == 0, "market may only be initialized once"); // Set initial exchange rate initialExchangeRateMantissa = initialExchangeRateMantissa_; require(initialExchangeRateMantissa > 0, "initial exchange rate must be greater than zero."); // Set the comptroller uint err = _setComptroller(comptroller_); require(err == NO_ERROR, "setting comptroller failed"); // Initialize block number and borrow index (block number mocks depend on comptroller being set) accrualBlockNumber = getBlockNumber(); borrowIndex = mantissaOne; // Set the interest rate model (depends on block number / borrow index) err = _setInterestRateModelFresh(interestRateModel_); require(err == NO_ERROR, "setting interest rate model failed"); name = name_; symbol = symbol_; decimals = decimals_; // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund) _notEntered = true; } /** * @notice Transfer `tokens` tokens from `src` to `dst` by `spender` * @dev Called by both `transfer` and `transferFrom` internally * @param spender The address of the account performing the transfer * @param src The address of the source account * @param dst The address of the destination account * @param tokens The number of tokens to transfer * @return 0 if the transfer succeeded, else revert */ function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) { /* Fail if transfer not allowed */ uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens); if (allowed != 0) { revert TransferComptrollerRejection(allowed); } /* Do not allow self-transfers */ if (src == dst) { revert TransferNotAllowed(); } /* Get the allowance, infinite for the account owner */ uint startingAllowance = 0; if (spender == src) { startingAllowance = type(uint).max; } else { startingAllowance = transferAllowances[src][spender]; } /* Do the calculations, checking for {under,over}flow */ uint allowanceNew = startingAllowance - tokens; uint srcTokensNew = accountTokens[src] - tokens; uint dstTokensNew = accountTokens[dst] + tokens; ///////////////////////// // EFFECTS & INTERACTIONS // (No safe failures beyond this point) accountTokens[src] = srcTokensNew; accountTokens[dst] = dstTokensNew; /* Eat some of the allowance (if necessary) */ if (startingAllowance != type(uint).max) { transferAllowances[src][spender] = allowanceNew; } /* We emit a Transfer event */ emit Transfer(src, dst, tokens); // unused function // comptroller.transferVerify(address(this), src, dst, tokens); return NO_ERROR; } /** * @notice Transfer `amount` tokens from `msg.sender` to `dst` * @param dst The address of the destination account * @param amount The number of tokens to transfer * @return Whether or not the transfer succeeded */ function transfer(address dst, uint256 amount) override external nonReentrant returns (bool) { return transferTokens(msg.sender, msg.sender, dst, amount) == NO_ERROR; } /** * @notice Transfer `amount` tokens from `src` to `dst` * @param src The address of the source account * @param dst The address of the destination account * @param amount The number of tokens to transfer * @return Whether or not the transfer succeeded */ function transferFrom(address src, address dst, uint256 amount) override external nonReentrant returns (bool) { return transferTokens(msg.sender, src, dst, amount) == NO_ERROR; } /** * @notice Approve `spender` to transfer up to `amount` from `src` * @dev This will overwrite the approval amount for `spender` * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve) * @param spender The address of the account which may transfer tokens * @param amount The number of tokens that are approved (uint256.max means infinite) * @return Whether or not the approval succeeded */ function approve(address spender, uint256 amount) override external returns (bool) { address src = msg.sender; transferAllowances[src][spender] = amount; emit Approval(src, spender, amount); return true; } /** * @notice Get the current allowance from `owner` for `spender` * @param owner The address of the account which owns the tokens to be spent * @param spender The address of the account which may transfer tokens * @return The number of tokens allowed to be spent (-1 means infinite) */ function allowance(address owner, address spender) override external view returns (uint256) { return transferAllowances[owner][spender]; } /** * @notice Get the token balance of the `owner` * @param owner The address of the account to query * @return The number of tokens owned by `owner` */ function balanceOf(address owner) override external view returns (uint256) { return accountTokens[owner]; } /** * @notice Get the underlying balance of the `owner` * @dev This also accrues interest in a transaction * @param owner The address of the account to query * @return The amount of underlying owned by `owner` */ function balanceOfUnderlying(address owner) override external returns (uint) { Exp memory exchangeRate = Exp({mantissa: exchangeRateCurrent()}); return mul_ScalarTruncate(exchangeRate, accountTokens[owner]); } /** * @notice Get a snapshot of the account's balances, and the cached exchange rate * @dev This is used by comptroller to more efficiently perform liquidity checks. * @param account Address of the account to snapshot * @return (possible error, token balance, borrow balance, exchange rate mantissa) */ function getAccountSnapshot(address account) override external view returns (uint, uint, uint, uint) { return ( NO_ERROR, accountTokens[account], borrowBalanceStoredInternal(account), exchangeRateStoredInternal() ); } /** * @dev Function to simply retrieve block number * This exists mainly for inheriting test contracts to stub this result. */ function getBlockNumber() virtual internal view returns (uint) { return block.number; } /** * @notice Returns the current per-block borrow interest rate for this cToken * @return The borrow interest rate per block, scaled by 1e18 */ function borrowRatePerBlock() override external view returns (uint) { return interestRateModel.getBorrowRate(getCashPrior(), totalBorrows, totalReserves); } /** * @notice Returns the current per-block supply interest rate for this cToken * @return The supply interest rate per block, scaled by 1e18 */ function supplyRatePerBlock() override external view returns (uint) { return interestRateModel.getSupplyRate(getCashPrior(), totalBorrows, totalReserves, reserveFactorMantissa); } /** * @notice Returns the current total borrows plus accrued interest * @return The total borrows with interest */ function totalBorrowsCurrent() override external nonReentrant returns (uint) { accrueInterest(); return totalBorrows; } /** * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex * @param account The address whose balance should be calculated after updating borrowIndex * @return The calculated balance */ function borrowBalanceCurrent(address account) override external nonReentrant returns (uint) { accrueInterest(); return borrowBalanceStored(account); } /** * @notice Return the borrow balance of account based on stored data * @param account The address whose balance should be calculated * @return The calculated balance */ function borrowBalanceStored(address account) override public view returns (uint) { return borrowBalanceStoredInternal(account); } /** * @notice Return the borrow balance of account based on stored data * @param account The address whose balance should be calculated * @return (error code, the calculated balance or 0 if error code is non-zero) */ function borrowBalanceStoredInternal(address account) internal view returns (uint) { /* Get borrowBalance and borrowIndex */ BorrowSnapshot storage borrowSnapshot = accountBorrows[account]; /* If borrowBalance = 0 then borrowIndex is likely also 0. * Rather than failing the calculation with a division by 0, we immediately return 0 in this case. */ if (borrowSnapshot.principal == 0) { return 0; } /* Calculate new borrow balance using the interest index: * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex */ uint principalTimesIndex = borrowSnapshot.principal * borrowIndex; return principalTimesIndex / borrowSnapshot.interestIndex; } /** * @notice Accrue interest then return the up-to-date exchange rate * @return Calculated exchange rate scaled by 1e18 */ function exchangeRateCurrent() override public nonReentrant returns (uint) { accrueInterest(); return exchangeRateStored(); } /** * @notice Calculates the exchange rate from the underlying to the CToken * @dev This function does not accrue interest before calculating the exchange rate * @return Calculated exchange rate scaled by 1e18 */ function exchangeRateStored() override public view returns (uint) { return exchangeRateStoredInternal(); } /** * @notice Calculates the exchange rate from the underlying to the CToken * @dev This function does not accrue interest before calculating the exchange rate * @return calculated exchange rate scaled by 1e18 */ function exchangeRateStoredInternal() virtual internal view returns (uint) { uint _totalSupply = totalSupply; if (_totalSupply == 0) { /* * If there are no tokens minted: * exchangeRate = initialExchangeRate */ return initialExchangeRateMantissa; } else { /* * Otherwise: * exchangeRate = (totalCash + totalBorrows - totalReserves) / totalSupply */ uint totalCash = getCashPrior(); uint cashPlusBorrowsMinusReserves = totalCash + totalBorrows - totalReserves; uint exchangeRate = cashPlusBorrowsMinusReserves * expScale / _totalSupply; return exchangeRate; } } /** * @notice Get cash balance of this cToken in the underlying asset * @return The quantity of underlying asset owned by this contract */ function getCash() override external view returns (uint) { return getCashPrior(); } /** * @notice Applies accrued interest to total borrows and reserves * @dev This calculates interest accrued from the last checkpointed block * up to the current block and writes new checkpoint to storage. */ function accrueInterest() virtual override public returns (uint) { /* Remember the initial block number */ uint currentBlockNumber = getBlockNumber(); uint accrualBlockNumberPrior = accrualBlockNumber; /* Short-circuit accumulating 0 interest */ if (accrualBlockNumberPrior == currentBlockNumber) { return NO_ERROR; } /* Read the previous values out of storage */ uint cashPrior = getCashPrior(); uint borrowsPrior = totalBorrows; uint reservesPrior = totalReserves; uint borrowIndexPrior = borrowIndex; /* Calculate the current borrow interest rate */ uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior); require(borrowRateMantissa <= borrowRateMaxMantissa, "borrow rate is absurdly high"); /* Calculate the number of blocks elapsed since the last accrual */ uint blockDelta = currentBlockNumber - accrualBlockNumberPrior; /* * Calculate the interest accumulated into borrows and reserves and the new index: * simpleInterestFactor = borrowRate * blockDelta * interestAccumulated = simpleInterestFactor * totalBorrows * totalBorrowsNew = interestAccumulated + totalBorrows * totalReservesNew = interestAccumulated * reserveFactor + totalReserves * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex */ Exp memory simpleInterestFactor = mul_(Exp({mantissa: borrowRateMantissa}), blockDelta); uint interestAccumulated = mul_ScalarTruncate(simpleInterestFactor, borrowsPrior); uint totalBorrowsNew = interestAccumulated + borrowsPrior; uint totalReservesNew = mul_ScalarTruncateAddUInt(Exp({mantissa: reserveFactorMantissa}), interestAccumulated, reservesPrior); uint borrowIndexNew = mul_ScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior); ///////////////////////// // EFFECTS & INTERACTIONS // (No safe failures beyond this point) /* We write the previously calculated values into storage */ accrualBlockNumber = currentBlockNumber; borrowIndex = borrowIndexNew; totalBorrows = totalBorrowsNew; totalReserves = totalReservesNew; /* We emit an AccrueInterest event */ emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew); return NO_ERROR; } /** * @notice Sender supplies assets into the market and receives cTokens in exchange * @dev Accrues interest whether or not the operation succeeds, unless reverted * @param mintAmount The amount of the underlying asset to supply */ function mintInternal(uint mintAmount) internal nonReentrant { accrueInterest(); // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to mintFresh(msg.sender, mintAmount); } /** * @notice User supplies assets into the market and receives cTokens in exchange * @dev Assumes interest has already been accrued up to the current block * @param minter The address of the account which is supplying the assets * @param mintAmount The amount of the underlying asset to supply */ function mintFresh(address minter, uint mintAmount) internal { /* Fail if mint not allowed */ uint allowed = comptroller.mintAllowed(address(this), minter, mintAmount); if (allowed != 0) { revert MintComptrollerRejection(allowed); } /* Verify market's block number equals current block number */ if (accrualBlockNumber != getBlockNumber()) { revert MintFreshnessCheck(); } Exp memory exchangeRate = Exp({mantissa: exchangeRateStoredInternal()}); ///////////////////////// // EFFECTS & INTERACTIONS // (No safe failures beyond this point) /* * We call `doTransferIn` for the minter and the mintAmount. * Note: The cToken must handle variations between ERC-20 and ETH underlying. * `doTransferIn` reverts if anything goes wrong, since we can't be sure if * side-effects occurred. The function returns the amount actually transferred, * in case of a fee. On success, the cToken holds an additional `actualMintAmount` * of cash. */ uint actualMintAmount = doTransferIn(minter, mintAmount); /* * We get the current exchange rate and calculate the number of cTokens to be minted: * mintTokens = actualMintAmount / exchangeRate */ uint mintTokens = div_(actualMintAmount, exchangeRate); /* * We calculate the new total supply of cTokens and minter token balance, checking for overflow: * totalSupplyNew = totalSupply + mintTokens * accountTokensNew = accountTokens[minter] + mintTokens * And write them into storage */ totalSupply = totalSupply + mintTokens; accountTokens[minter] = accountTokens[minter] + mintTokens; /* We emit a Mint event, and a Transfer event */ emit Mint(minter, actualMintAmount, mintTokens); emit Transfer(address(this), minter, mintTokens); /* We call the defense hook */ // unused function // comptroller.mintVerify(address(this), minter, actualMintAmount, mintTokens); } /** * @notice Sender redeems cTokens in exchange for the underlying asset * @dev Accrues interest whether or not the operation succeeds, unless reverted * @param redeemTokens The number of cTokens to redeem into underlying */ function redeemInternal(uint redeemTokens) internal nonReentrant { accrueInterest(); // redeemFresh emits redeem-specific logs on errors, so we don't need to redeemFresh(payable(msg.sender), redeemTokens, 0); } /** * @notice Sender redeems cTokens in exchange for a specified amount of underlying asset * @dev Accrues interest whether or not the operation succeeds, unless reverted * @param redeemAmount The amount of underlying to receive from redeeming cTokens */ function redeemUnderlyingInternal(uint redeemAmount) internal nonReentrant { accrueInterest(); // redeemFresh emits redeem-specific logs on errors, so we don't need to redeemFresh(payable(msg.sender), 0, redeemAmount); } /** * @notice User redeems cTokens in exchange for the underlying asset * @dev Assumes interest has already been accrued up to the current block * @param redeemer The address of the account which is redeeming the tokens * @param redeemTokensIn The number of cTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero) * @param redeemAmountIn The number of underlying tokens to receive from redeeming cTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero) */ function redeemFresh(address payable redeemer, uint redeemTokensIn, uint redeemAmountIn) internal { require(redeemTokensIn == 0 || redeemAmountIn == 0, "one of redeemTokensIn or redeemAmountIn must be zero"); /* exchangeRate = invoke Exchange Rate Stored() */ Exp memory exchangeRate = Exp({mantissa: exchangeRateStoredInternal() }); uint redeemTokens; uint redeemAmount; /* If redeemTokensIn > 0: */ if (redeemTokensIn > 0) { /* * We calculate the exchange rate and the amount of underlying to be redeemed: * redeemTokens = redeemTokensIn * redeemAmount = redeemTokensIn x exchangeRateCurrent */ redeemTokens = redeemTokensIn; redeemAmount = mul_ScalarTruncate(exchangeRate, redeemTokensIn); } else { /* * We get the current exchange rate and calculate the amount to be redeemed: * redeemTokens = redeemAmountIn / exchangeRate * redeemAmount = redeemAmountIn */ redeemTokens = div_(redeemAmountIn, exchangeRate); redeemAmount = redeemAmountIn; } /* Fail if redeem not allowed */ uint allowed = comptroller.redeemAllowed(address(this), redeemer, redeemTokens); if (allowed != 0) { revert RedeemComptrollerRejection(allowed); } /* Verify market's block number equals current block number */ if (accrualBlockNumber != getBlockNumber()) { revert RedeemFreshnessCheck(); } /* Fail gracefully if protocol has insufficient cash */ if (getCashPrior() < redeemAmount) { revert RedeemTransferOutNotPossible(); } ///////////////////////// // EFFECTS & INTERACTIONS // (No safe failures beyond this point) /* * We write the previously calculated values into storage. * Note: Avoid token reentrancy attacks by writing reduced supply before external transfer. */ totalSupply = totalSupply - redeemTokens; accountTokens[redeemer] = accountTokens[redeemer] - redeemTokens; /* * We invoke doTransferOut for the redeemer and the redeemAmount. * Note: The cToken must handle variations between ERC-20 and ETH underlying. * On success, the cToken has redeemAmount less of cash. * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred. */ doTransferOut(redeemer, redeemAmount); /* We emit a Transfer event, and a Redeem event */ emit Transfer(redeemer, address(this), redeemTokens); emit Redeem(redeemer, redeemAmount, redeemTokens); /* We call the defense hook */ comptroller.redeemVerify(address(this), redeemer, redeemAmount, redeemTokens); } /** * @notice Sender borrows assets from the protocol to their own address * @param borrowAmount The amount of the underlying asset to borrow */ function borrowInternal(uint borrowAmount) internal nonReentrant { accrueInterest(); // borrowFresh emits borrow-specific logs on errors, so we don't need to borrowFresh(payable(msg.sender), borrowAmount); } /** * @notice Users borrow assets from the protocol to their own address * @param borrowAmount The amount of the underlying asset to borrow */ function borrowFresh(address payable borrower, uint borrowAmount) internal { /* Fail if borrow not allowed */ uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount); if (allowed != 0) { revert BorrowComptrollerRejection(allowed); } /* Verify market's block number equals current block number */ if (accrualBlockNumber != getBlockNumber()) { revert BorrowFreshnessCheck(); } /* Fail gracefully if protocol has insufficient underlying cash */ if (getCashPrior() < borrowAmount) { revert BorrowCashNotAvailable(); } /* * We calculate the new borrower and total borrow balances, failing on overflow: * accountBorrowNew = accountBorrow + borrowAmount * totalBorrowsNew = totalBorrows + borrowAmount */ uint accountBorrowsPrev = borrowBalanceStoredInternal(borrower); uint accountBorrowsNew = accountBorrowsPrev + borrowAmount; uint totalBorrowsNew = totalBorrows + borrowAmount; ///////////////////////// // EFFECTS & INTERACTIONS // (No safe failures beyond this point) /* * We write the previously calculated values into storage. * Note: Avoid token reentrancy attacks by writing increased borrow before external transfer. `*/ accountBorrows[borrower].principal = accountBorrowsNew; accountBorrows[borrower].interestIndex = borrowIndex; totalBorrows = totalBorrowsNew; /* * We invoke doTransferOut for the borrower and the borrowAmount. * Note: The cToken must handle variations between ERC-20 and ETH underlying. * On success, the cToken borrowAmount less of cash. * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred. */ doTransferOut(borrower, borrowAmount); /* We emit a Borrow event */ emit Borrow(borrower, borrowAmount, accountBorrowsNew, totalBorrowsNew); } /** * @notice Sender repays their own borrow * @param repayAmount The amount to repay, or -1 for the full outstanding amount */ function repayBorrowInternal(uint repayAmount) internal nonReentrant { accrueInterest(); // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to repayBorrowFresh(msg.sender, msg.sender, repayAmount); } /** * @notice Sender repays a borrow belonging to borrower * @param borrower the account with the debt being payed off * @param repayAmount The amount to repay, or -1 for the full outstanding amount */ function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant { accrueInterest(); // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to repayBorrowFresh(msg.sender, borrower, repayAmount); } /** * @notice Borrows are repaid by another user (possibly the borrower). * @param payer the account paying off the borrow * @param borrower the account with the debt being payed off * @param repayAmount the amount of underlying tokens being returned, or -1 for the full outstanding amount * @return (uint) the actual repayment amount. */ function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint) { /* Fail if repayBorrow not allowed */ uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount); if (allowed != 0) { revert RepayBorrowComptrollerRejection(allowed); } /* Verify market's block number equals current block number */ if (accrualBlockNumber != getBlockNumber()) { revert RepayBorrowFreshnessCheck(); } /* We fetch the amount the borrower owes, with accumulated interest */ uint accountBorrowsPrev = borrowBalanceStoredInternal(borrower); /* If repayAmount == -1, repayAmount = accountBorrows */ uint repayAmountFinal = repayAmount == type(uint).max ? accountBorrowsPrev : repayAmount; ///////////////////////// // EFFECTS & INTERACTIONS // (No safe failures beyond this point) /* * We call doTransferIn for the payer and the repayAmount * Note: The cToken must handle variations between ERC-20 and ETH underlying. * On success, the cToken holds an additional repayAmount of cash. * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred. * it returns the amount actually transferred, in case of a fee. */ uint actualRepayAmount = doTransferIn(payer, repayAmountFinal); /* * We calculate the new borrower and total borrow balances, failing on underflow: * accountBorrowsNew = accountBorrows - actualRepayAmount * totalBorrowsNew = totalBorrows - actualRepayAmount */ uint accountBorrowsNew = accountBorrowsPrev - actualRepayAmount; uint totalBorrowsNew = totalBorrows - actualRepayAmount; /* We write the previously calculated values into storage */ accountBorrows[borrower].principal = accountBorrowsNew; accountBorrows[borrower].interestIndex = borrowIndex; totalBorrows = totalBorrowsNew; /* We emit a RepayBorrow event */ emit RepayBorrow(payer, borrower, actualRepayAmount, accountBorrowsNew, totalBorrowsNew); return actualRepayAmount; } /** * @notice The sender liquidates the borrowers collateral. * The collateral seized is transferred to the liquidator. * @param borrower The borrower of this cToken to be liquidated * @param cTokenCollateral The market in which to seize collateral from the borrower * @param repayAmount The amount of the underlying borrowed asset to repay */ function liquidateBorrowInternal(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) internal nonReentrant { accrueInterest(); uint error = cTokenCollateral.accrueInterest(); if (error != NO_ERROR) { // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed revert LiquidateAccrueCollateralInterestFailed(error); } // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to liquidateBorrowFresh(msg.sender, borrower, repayAmount, cTokenCollateral); } /** * @notice The liquidator liquidates the borrowers collateral. * The collateral seized is transferred to the liquidator. * @param borrower The borrower of this cToken to be liquidated * @param liquidator The address repaying the borrow and seizing collateral * @param cTokenCollateral The market in which to seize collateral from the borrower * @param repayAmount The amount of the underlying borrowed asset to repay */ function liquidateBorrowFresh(address liquidator, address borrower, uint repayAmount, CTokenInterface cTokenCollateral) internal { /* Fail if liquidate not allowed */ uint allowed = comptroller.liquidateBorrowAllowed(address(this), address(cTokenCollateral), liquidator, borrower, repayAmount); if (allowed != 0) { revert LiquidateComptrollerRejection(allowed); } /* Verify market's block number equals current block number */ if (accrualBlockNumber != getBlockNumber()) { revert LiquidateFreshnessCheck(); } /* Verify cTokenCollateral market's block number equals current block number */ if (cTokenCollateral.accrualBlockNumber() != getBlockNumber()) { revert LiquidateCollateralFreshnessCheck(); } /* Fail if borrower = liquidator */ if (borrower == liquidator) { revert LiquidateLiquidatorIsBorrower(); } /* Fail if repayAmount = 0 */ if (repayAmount == 0) { revert LiquidateCloseAmountIsZero(); } /* Fail if repayAmount = -1 */ if (repayAmount == type(uint).max) { revert LiquidateCloseAmountIsUintMax(); } /* Fail if repayBorrow fails */ uint actualRepayAmount = repayBorrowFresh(liquidator, borrower, repayAmount); ///////////////////////// // EFFECTS & INTERACTIONS // (No safe failures beyond this point) /* We calculate the number of collateral tokens that will be seized */ (uint amountSeizeError, uint seizeTokens) = comptroller.liquidateCalculateSeizeTokens(address(this), address(cTokenCollateral), actualRepayAmount); require(amountSeizeError == NO_ERROR, "LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED"); /* Revert if borrower collateral token balance < seizeTokens */ require(cTokenCollateral.balanceOf(borrower) >= seizeTokens, "LIQUIDATE_SEIZE_TOO_MUCH"); // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call if (address(cTokenCollateral) == address(this)) { seizeInternal(address(this), liquidator, borrower, seizeTokens); } else { require(cTokenCollateral.seize(liquidator, borrower, seizeTokens) == NO_ERROR, "token seizure failed"); } /* We emit a LiquidateBorrow event */ emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(cTokenCollateral), seizeTokens); } /** * @notice Transfers collateral tokens (this market) to the liquidator. * @dev Will fail unless called by another cToken during the process of liquidation. * Its absolutely critical to use msg.sender as the borrowed cToken and not a parameter. * @param liquidator The account receiving seized collateral * @param borrower The account having collateral seized * @param seizeTokens The number of cTokens to seize * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function seize(address liquidator, address borrower, uint seizeTokens) override external nonReentrant returns (uint) { seizeInternal(msg.sender, liquidator, borrower, seizeTokens); return NO_ERROR; } /** * @notice Transfers collateral tokens (this market) to the liquidator. * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another CToken. * Its absolutely critical to use msg.sender as the seizer cToken and not a parameter. * @param seizerToken The contract seizing the collateral (i.e. borrowed cToken) * @param liquidator The account receiving seized collateral * @param borrower The account having collateral seized * @param seizeTokens The number of cTokens to seize */ function seizeInternal(address seizerToken, address liquidator, address borrower, uint seizeTokens) internal { /* Fail if seize not allowed */ uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens); if (allowed != 0) { revert LiquidateSeizeComptrollerRejection(allowed); } /* Fail if borrower = liquidator */ if (borrower == liquidator) { revert LiquidateSeizeLiquidatorIsBorrower(); } /* * We calculate the new borrower and liquidator token balances, failing on underflow/overflow: * borrowerTokensNew = accountTokens[borrower] - seizeTokens * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens */ uint protocolSeizeTokens = mul_(seizeTokens, Exp({mantissa: protocolSeizeShareMantissa})); uint liquidatorSeizeTokens = seizeTokens - protocolSeizeTokens; Exp memory exchangeRate = Exp({mantissa: exchangeRateStoredInternal()}); uint protocolSeizeAmount = mul_ScalarTruncate(exchangeRate, protocolSeizeTokens); uint totalReservesNew = totalReserves + protocolSeizeAmount; ///////////////////////// // EFFECTS & INTERACTIONS // (No safe failures beyond this point) /* We write the calculated values into storage */ totalReserves = totalReservesNew; totalSupply = totalSupply - protocolSeizeTokens; accountTokens[borrower] = accountTokens[borrower] - seizeTokens; accountTokens[liquidator] = accountTokens[liquidator] + liquidatorSeizeTokens; /* Emit a Transfer event */ emit Transfer(borrower, liquidator, liquidatorSeizeTokens); emit Transfer(borrower, address(this), protocolSeizeTokens); emit ReservesAdded(address(this), protocolSeizeAmount, totalReservesNew); } /*** Admin Functions ***/ /** * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer. * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer. * @param newPendingAdmin New pending admin. * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function _setPendingAdmin(address payable newPendingAdmin) override external returns (uint) { // Check caller = admin if (msg.sender != admin) { revert SetPendingAdminOwnerCheck(); } // Save current value, if any, for inclusion in log address oldPendingAdmin = pendingAdmin; // Store pendingAdmin with value newPendingAdmin pendingAdmin = newPendingAdmin; // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin) emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin); return NO_ERROR; } /** * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin * @dev Admin function for pending admin to accept role and update admin * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function _acceptAdmin() override external returns (uint) { // Check caller is pendingAdmin and pendingAdmin ≠ address(0) if (msg.sender != pendingAdmin || msg.sender == address(0)) { revert AcceptAdminPendingAdminCheck(); } // Save current values for inclusion in log address oldAdmin = admin; address oldPendingAdmin = pendingAdmin; // Store admin with value pendingAdmin admin = pendingAdmin; // Clear the pending value pendingAdmin = payable(address(0)); emit NewAdmin(oldAdmin, admin); emit NewPendingAdmin(oldPendingAdmin, pendingAdmin); return NO_ERROR; } /** * @notice Sets a new comptroller for the market * @dev Admin function to set a new comptroller * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function _setComptroller(ComptrollerInterface newComptroller) override public returns (uint) { // Check caller is admin if (msg.sender != admin) { revert SetComptrollerOwnerCheck(); } ComptrollerInterface oldComptroller = comptroller; // Ensure invoke comptroller.isComptroller() returns true require(newComptroller.isComptroller(), "marker method returned false"); // Set market's comptroller to newComptroller comptroller = newComptroller; // Emit NewComptroller(oldComptroller, newComptroller) emit NewComptroller(oldComptroller, newComptroller); return NO_ERROR; } /** * @notice accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh * @dev Admin function to accrue interest and set a new reserve factor * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function _setReserveFactor(uint newReserveFactorMantissa) override external nonReentrant returns (uint) { accrueInterest(); // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to. return _setReserveFactorFresh(newReserveFactorMantissa); } /** * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual) * @dev Admin function to set a new reserve factor * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) { // Check caller is admin if (msg.sender != admin) { revert SetReserveFactorAdminCheck(); } // Verify market's block number equals current block number if (accrualBlockNumber != getBlockNumber()) { revert SetReserveFactorFreshCheck(); } // Check newReserveFactor ≤ maxReserveFactor if (newReserveFactorMantissa > reserveFactorMaxMantissa) { revert SetReserveFactorBoundsCheck(); } uint oldReserveFactorMantissa = reserveFactorMantissa; reserveFactorMantissa = newReserveFactorMantissa; emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa); return NO_ERROR; } /** * @notice Accrues interest and reduces reserves by transferring from msg.sender * @param addAmount Amount of addition to reserves * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) { accrueInterest(); // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to. _addReservesFresh(addAmount); return NO_ERROR; } /** * @notice Add reserves by transferring from caller * @dev Requires fresh interest accrual * @param addAmount Amount of addition to reserves * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees */ function _addReservesFresh(uint addAmount) internal returns (uint, uint) { // totalReserves + actualAddAmount uint totalReservesNew; uint actualAddAmount; // We fail gracefully unless market's block number equals current block number if (accrualBlockNumber != getBlockNumber()) { revert AddReservesFactorFreshCheck(actualAddAmount); } ///////////////////////// // EFFECTS & INTERACTIONS // (No safe failures beyond this point) /* * We call doTransferIn for the caller and the addAmount * Note: The cToken must handle variations between ERC-20 and ETH underlying. * On success, the cToken holds an additional addAmount of cash. * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred. * it returns the amount actually transferred, in case of a fee. */ actualAddAmount = doTransferIn(msg.sender, addAmount); totalReservesNew = totalReserves + actualAddAmount; // Store reserves[n+1] = reserves[n] + actualAddAmount totalReserves = totalReservesNew; /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */ emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew); /* Return (NO_ERROR, actualAddAmount) */ return (NO_ERROR, actualAddAmount); } /** * @notice Accrues interest and reduces reserves by transferring to admin * @param reduceAmount Amount of reduction to reserves * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function _reduceReserves(uint reduceAmount) override external nonReentrant returns (uint) { accrueInterest(); // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to. return _reduceReservesFresh(reduceAmount); } /** * @notice Reduces reserves by transferring to admin * @dev Requires fresh interest accrual * @param reduceAmount Amount of reduction to reserves * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function _reduceReservesFresh(uint reduceAmount) internal returns (uint) { // totalReserves - reduceAmount uint totalReservesNew; // Check caller is admin if (msg.sender != admin) { revert ReduceReservesAdminCheck(); } // We fail gracefully unless market's block number equals current block number if (accrualBlockNumber != getBlockNumber()) { revert ReduceReservesFreshCheck(); } // Fail gracefully if protocol has insufficient underlying cash if (getCashPrior() < reduceAmount) { revert ReduceReservesCashNotAvailable(); } // Check reduceAmount ≤ reserves[n] (totalReserves) if (reduceAmount > totalReserves) { revert ReduceReservesCashValidation(); } ///////////////////////// // EFFECTS & INTERACTIONS // (No safe failures beyond this point) totalReservesNew = totalReserves - reduceAmount; // Store reserves[n+1] = reserves[n] - reduceAmount totalReserves = totalReservesNew; // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred. doTransferOut(admin, reduceAmount); emit ReservesReduced(admin, reduceAmount, totalReservesNew); return NO_ERROR; } /** * @notice accrues interest and updates the interest rate model using _setInterestRateModelFresh * @dev Admin function to accrue interest and update the interest rate model * @param newInterestRateModel the new interest rate model to use * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function _setInterestRateModel(InterestRateModel newInterestRateModel) override public returns (uint) { accrueInterest(); // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to. return _setInterestRateModelFresh(newInterestRateModel); } /** * @notice updates the interest rate model (*requires fresh interest accrual) * @dev Admin function to update the interest rate model * @param newInterestRateModel the new interest rate model to use * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal returns (uint) { // Used to store old model for use in the event that is emitted on success InterestRateModel oldInterestRateModel; // Check caller is admin if (msg.sender != admin) { revert SetInterestRateModelOwnerCheck(); } // We fail gracefully unless market's block number equals current block number if (accrualBlockNumber != getBlockNumber()) { revert SetInterestRateModelFreshCheck(); } // Track the market's current interest rate model oldInterestRateModel = interestRateModel; // Ensure invoke newInterestRateModel.isInterestRateModel() returns true require(newInterestRateModel.isInterestRateModel(), "marker method returned false"); // Set the interest rate model to newInterestRateModel interestRateModel = newInterestRateModel; // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel) emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel); return NO_ERROR; } /*** Safe Token ***/ /** * @notice Gets balance of this contract in terms of the underlying * @dev This excludes the value of the current message, if any * @return The quantity of underlying owned by this contract */ function getCashPrior() virtual internal view returns (uint); /** * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee. * This may revert due to insufficient balance or insufficient allowance. */ function doTransferIn(address from, uint amount) virtual internal returns (uint); /** * @dev Performs a transfer out, ideally returning an explanatory error code upon failure rather than reverting. * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract. * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions. */ function doTransferOut(address payable to, uint amount) virtual internal; /*** Reentrancy Guard ***/ /** * @dev Prevents a contract from calling itself, directly or indirectly. */ modifier nonReentrant() { require(_notEntered, "re-entered"); _notEntered = false; _; _notEntered = true; // get a gas-refund post-Istanbul } } interface CompLike { function delegate(address delegatee) external; } /** * @title Compound's CErc20 Contract * @notice CTokens which wrap an EIP-20 underlying * @author Compound */ contract CErc20 is CToken, CErc20Interface { /** * @notice Initialize the new money market * @param underlying_ The address of the underlying asset * @param comptroller_ The address of the Comptroller * @param interestRateModel_ The address of the interest rate model * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18 * @param name_ ERC-20 name of this token * @param symbol_ ERC-20 symbol of this token * @param decimals_ ERC-20 decimal precision of this token */ function initialize(address underlying_, ComptrollerInterface comptroller_, InterestRateModel interestRateModel_, uint initialExchangeRateMantissa_, string memory name_, string memory symbol_, uint8 decimals_) public { // CToken initialize does the bulk of the work super.initialize(comptroller_, interestRateModel_, initialExchangeRateMantissa_, name_, symbol_, decimals_); // Set underlying and sanity check it underlying = underlying_; EIP20Interface(underlying).totalSupply(); } /*** User Interface ***/ /** * @notice Sender supplies assets into the market and receives cTokens in exchange * @dev Accrues interest whether or not the operation succeeds, unless reverted * @param mintAmount The amount of the underlying asset to supply * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function mint(uint mintAmount) override external returns (uint) { mintInternal(mintAmount); return NO_ERROR; } /** * @notice Sender redeems cTokens in exchange for the underlying asset * @dev Accrues interest whether or not the operation succeeds, unless reverted * @param redeemTokens The number of cTokens to redeem into underlying * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function redeem(uint redeemTokens) override external returns (uint) { redeemInternal(redeemTokens); return NO_ERROR; } /** * @notice Sender redeems cTokens in exchange for a specified amount of underlying asset * @dev Accrues interest whether or not the operation succeeds, unless reverted * @param redeemAmount The amount of underlying to redeem * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function redeemUnderlying(uint redeemAmount) override external returns (uint) { redeemUnderlyingInternal(redeemAmount); return NO_ERROR; } /** * @notice Sender borrows assets from the protocol to their own address * @param borrowAmount The amount of the underlying asset to borrow * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function borrow(uint borrowAmount) override external returns (uint) { borrowInternal(borrowAmount); return NO_ERROR; } /** * @notice Sender repays their own borrow * @param repayAmount The amount to repay, or -1 for the full outstanding amount * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function repayBorrow(uint repayAmount) override external returns (uint) { repayBorrowInternal(repayAmount); return NO_ERROR; } /** * @notice Sender repays a borrow belonging to borrower * @param borrower the account with the debt being payed off * @param repayAmount The amount to repay, or -1 for the full outstanding amount * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function repayBorrowBehalf(address borrower, uint repayAmount) override external returns (uint) { repayBorrowBehalfInternal(borrower, repayAmount); return NO_ERROR; } /** * @notice The sender liquidates the borrowers collateral. * The collateral seized is transferred to the liquidator. * @param borrower The borrower of this cToken to be liquidated * @param repayAmount The amount of the underlying borrowed asset to repay * @param cTokenCollateral The market in which to seize collateral from the borrower * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function liquidateBorrow(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) override external returns (uint) { liquidateBorrowInternal(borrower, repayAmount, cTokenCollateral); return NO_ERROR; } /** * @notice A public function to sweep accidental ERC-20 transfers to this contract. Tokens are sent to admin (timelock) * @param token The address of the ERC-20 token to sweep */ function sweepToken(EIP20NonStandardInterface token) override external { require(msg.sender == admin, "CErc20::sweepToken: only admin can sweep tokens"); require(address(token) != underlying, "CErc20::sweepToken: can not sweep underlying token"); uint256 balance = token.balanceOf(address(this)); token.transfer(admin, balance); } /** * @notice The sender adds to reserves. * @param addAmount The amount fo underlying token to add as reserves * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function _addReserves(uint addAmount) override external returns (uint) { return _addReservesInternal(addAmount); } /*** Safe Token ***/ /** * @notice Gets balance of this contract in terms of the underlying * @dev This excludes the value of the current message, if any * @return The quantity of underlying tokens owned by this contract */ function getCashPrior() virtual override internal view returns (uint) { EIP20Interface token = EIP20Interface(underlying); return token.balanceOf(address(this)); } /** * @dev Similar to EIP20 transfer, except it handles a False result from `transferFrom` and reverts in that case. * This will revert due to insufficient balance or insufficient allowance. * This function returns the actual amount received, * which may be less than `amount` if there is a fee attached to the transfer. * * Note: This wrapper safely handles non-standard ERC-20 tokens that do not return a value. * See here: https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca */ function doTransferIn(address from, uint amount) virtual override internal returns (uint) { // Read from storage once address underlying_ = underlying; EIP20NonStandardInterface token = EIP20NonStandardInterface(underlying_); uint balanceBefore = EIP20Interface(underlying_).balanceOf(address(this)); token.transferFrom(from, address(this), amount); bool success; assembly { switch returndatasize() case 0 { // This is a non-standard ERC-20 success := not(0) // set success to true } case 32 { // This is a compliant ERC-20 returndatacopy(0, 0, 32) success := mload(0) // Set `success = returndata` of override external call } default { // This is an excessively non-compliant ERC-20, revert. revert(0, 0) } } require(success, "TOKEN_TRANSFER_IN_FAILED"); // Calculate the amount that was *actually* transferred uint balanceAfter = EIP20Interface(underlying_).balanceOf(address(this)); return balanceAfter - balanceBefore; // underflow already checked above, just subtract } /** * @dev Similar to EIP20 transfer, except it handles a False success from `transfer` and returns an explanatory * error code rather than reverting. If caller has not called checked protocol's balance, this may revert due to * insufficient cash held in this contract. If caller has checked protocol's balance prior to this call, and verified * it is >= amount, this should not revert in normal conditions. * * Note: This wrapper safely handles non-standard ERC-20 tokens that do not return a value. * See here: https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca */ function doTransferOut(address payable to, uint amount) virtual override internal { EIP20NonStandardInterface token = EIP20NonStandardInterface(underlying); token.transfer(to, amount); bool success; assembly { switch returndatasize() case 0 { // This is a non-standard ERC-20 success := not(0) // set success to true } case 32 { // This is a compliant ERC-20 returndatacopy(0, 0, 32) success := mload(0) // Set `success = returndata` of override external call } default { // This is an excessively non-compliant ERC-20, revert. revert(0, 0) } } require(success, "TOKEN_TRANSFER_OUT_FAILED"); } /** * @notice Admin call to delegate the votes of the COMP-like underlying * @param compLikeDelegatee The address to delegate votes to * @dev CTokens whose underlying are not CompLike should revert here */ function _delegateCompLikeTo(address compLikeDelegatee) external { require(msg.sender == admin, "only the admin may set the comp-like delegate"); CompLike(underlying).delegate(compLikeDelegatee); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"name":"AcceptAdminPendingAdminCheck","type":"error"},{"inputs":[{"internalType":"uint256","name":"actualAddAmount","type":"uint256"}],"name":"AddReservesFactorFreshCheck","type":"error"},{"inputs":[],"name":"BorrowCashNotAvailable","type":"error"},{"inputs":[{"internalType":"uint256","name":"errorCode","type":"uint256"}],"name":"BorrowComptrollerRejection","type":"error"},{"inputs":[],"name":"BorrowFreshnessCheck","type":"error"},{"inputs":[{"internalType":"uint256","name":"errorCode","type":"uint256"}],"name":"LiquidateAccrueBorrowInterestFailed","type":"error"},{"inputs":[{"internalType":"uint256","name":"errorCode","type":"uint256"}],"name":"LiquidateAccrueCollateralInterestFailed","type":"error"},{"inputs":[],"name":"LiquidateCloseAmountIsUintMax","type":"error"},{"inputs":[],"name":"LiquidateCloseAmountIsZero","type":"error"},{"inputs":[],"name":"LiquidateCollateralFreshnessCheck","type":"error"},{"inputs":[{"internalType":"uint256","name":"errorCode","type":"uint256"}],"name":"LiquidateComptrollerRejection","type":"error"},{"inputs":[],"name":"LiquidateFreshnessCheck","type":"error"},{"inputs":[],"name":"LiquidateLiquidatorIsBorrower","type":"error"},{"inputs":[{"internalType":"uint256","name":"errorCode","type":"uint256"}],"name":"LiquidateRepayBorrowFreshFailed","type":"error"},{"inputs":[{"internalType":"uint256","name":"errorCode","type":"uint256"}],"name":"LiquidateSeizeComptrollerRejection","type":"error"},{"inputs":[],"name":"LiquidateSeizeLiquidatorIsBorrower","type":"error"},{"inputs":[{"internalType":"uint256","name":"errorCode","type":"uint256"}],"name":"MintComptrollerRejection","type":"error"},{"inputs":[],"name":"MintFreshnessCheck","type":"error"},{"inputs":[{"internalType":"uint256","name":"errorCode","type":"uint256"}],"name":"RedeemComptrollerRejection","type":"error"},{"inputs":[],"name":"RedeemFreshnessCheck","type":"error"},{"inputs":[],"name":"RedeemTransferOutNotPossible","type":"error"},{"inputs":[],"name":"ReduceReservesAdminCheck","type":"error"},{"inputs":[],"name":"ReduceReservesCashNotAvailable","type":"error"},{"inputs":[],"name":"ReduceReservesCashValidation","type":"error"},{"inputs":[],"name":"ReduceReservesFreshCheck","type":"error"},{"inputs":[{"internalType":"uint256","name":"errorCode","type":"uint256"}],"name":"RepayBorrowComptrollerRejection","type":"error"},{"inputs":[],"name":"RepayBorrowFreshnessCheck","type":"error"},{"inputs":[],"name":"SetComptrollerOwnerCheck","type":"error"},{"inputs":[],"name":"SetInterestRateModelFreshCheck","type":"error"},{"inputs":[],"name":"SetInterestRateModelOwnerCheck","type":"error"},{"inputs":[],"name":"SetPendingAdminOwnerCheck","type":"error"},{"inputs":[],"name":"SetReserveFactorAdminCheck","type":"error"},{"inputs":[],"name":"SetReserveFactorBoundsCheck","type":"error"},{"inputs":[],"name":"SetReserveFactorFreshCheck","type":"error"},{"inputs":[{"internalType":"uint256","name":"errorCode","type":"uint256"}],"name":"TransferComptrollerRejection","type":"error"},{"inputs":[],"name":"TransferNotAllowed","type":"error"},{"inputs":[],"name":"TransferNotEnough","type":"error"},{"inputs":[],"name":"TransferTooMuch","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"cashPrior","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"interestAccumulated","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"borrowIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalBorrows","type":"uint256"}],"name":"AccrueInterest","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"borrower","type":"address"},{"indexed":false,"internalType":"uint256","name":"borrowAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"accountBorrows","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalBorrows","type":"uint256"}],"name":"Borrow","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"liquidator","type":"address"},{"indexed":false,"internalType":"address","name":"borrower","type":"address"},{"indexed":false,"internalType":"uint256","name":"repayAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"cTokenCollateral","type":"address"},{"indexed":false,"internalType":"uint256","name":"seizeTokens","type":"uint256"}],"name":"LiquidateBorrow","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"minter","type":"address"},{"indexed":false,"internalType":"uint256","name":"mintAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"mintTokens","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"NewAdmin","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract ComptrollerInterface","name":"oldComptroller","type":"address"},{"indexed":false,"internalType":"contract ComptrollerInterface","name":"newComptroller","type":"address"}],"name":"NewComptroller","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract InterestRateModel","name":"oldInterestRateModel","type":"address"},{"indexed":false,"internalType":"contract InterestRateModel","name":"newInterestRateModel","type":"address"}],"name":"NewMarketInterestRateModel","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldPendingAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newPendingAdmin","type":"address"}],"name":"NewPendingAdmin","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldReserveFactorMantissa","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newReserveFactorMantissa","type":"uint256"}],"name":"NewReserveFactor","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"redeemer","type":"address"},{"indexed":false,"internalType":"uint256","name":"redeemAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"redeemTokens","type":"uint256"}],"name":"Redeem","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"payer","type":"address"},{"indexed":false,"internalType":"address","name":"borrower","type":"address"},{"indexed":false,"internalType":"uint256","name":"repayAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"accountBorrows","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalBorrows","type":"uint256"}],"name":"RepayBorrow","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"benefactor","type":"address"},{"indexed":false,"internalType":"uint256","name":"addAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newTotalReserves","type":"uint256"}],"name":"ReservesAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"admin","type":"address"},{"indexed":false,"internalType":"uint256","name":"reduceAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newTotalReserves","type":"uint256"}],"name":"ReservesReduced","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"NO_ERROR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_acceptAdmin","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"addAmount","type":"uint256"}],"name":"_addReserves","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"compLikeDelegatee","type":"address"}],"name":"_delegateCompLikeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"reduceAmount","type":"uint256"}],"name":"_reduceReserves","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ComptrollerInterface","name":"newComptroller","type":"address"}],"name":"_setComptroller","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract InterestRateModel","name":"newInterestRateModel","type":"address"}],"name":"_setInterestRateModel","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"newPendingAdmin","type":"address"}],"name":"_setPendingAdmin","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newReserveFactorMantissa","type":"uint256"}],"name":"_setReserveFactor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"accrualBlockNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"accrueInterest","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOfUnderlying","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"borrowAmount","type":"uint256"}],"name":"borrow","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"borrowBalanceCurrent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"borrowBalanceStored","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"borrowIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"borrowRatePerBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"comptroller","outputs":[{"internalType":"contract ComptrollerInterface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"exchangeRateCurrent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"exchangeRateStored","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getAccountSnapshot","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCash","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"underlying_","type":"address"},{"internalType":"contract ComptrollerInterface","name":"comptroller_","type":"address"},{"internalType":"contract InterestRateModel","name":"interestRateModel_","type":"address"},{"internalType":"uint256","name":"initialExchangeRateMantissa_","type":"uint256"},{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"},{"internalType":"uint8","name":"decimals_","type":"uint8"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ComptrollerInterface","name":"comptroller_","type":"address"},{"internalType":"contract InterestRateModel","name":"interestRateModel_","type":"address"},{"internalType":"uint256","name":"initialExchangeRateMantissa_","type":"uint256"},{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"},{"internalType":"uint8","name":"decimals_","type":"uint8"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"interestRateModel","outputs":[{"internalType":"contract InterestRateModel","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isCToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"borrower","type":"address"},{"internalType":"uint256","name":"repayAmount","type":"uint256"},{"internalType":"contract CTokenInterface","name":"cTokenCollateral","type":"address"}],"name":"liquidateBorrow","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"mintAmount","type":"uint256"}],"name":"mint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingAdmin","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"protocolSeizeShareMantissa","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"redeemTokens","type":"uint256"}],"name":"redeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"redeemAmount","type":"uint256"}],"name":"redeemUnderlying","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"repayAmount","type":"uint256"}],"name":"repayBorrow","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"borrower","type":"address"},{"internalType":"uint256","name":"repayAmount","type":"uint256"}],"name":"repayBorrowBehalf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"reserveFactorMantissa","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"liquidator","type":"address"},{"internalType":"address","name":"borrower","type":"address"},{"internalType":"uint256","name":"seizeTokens","type":"uint256"}],"name":"seize","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"supplyRatePerBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract EIP20NonStandardInterface","name":"token","type":"address"}],"name":"sweepToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalBorrows","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalBorrowsCurrent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalReserves","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"src","type":"address"},{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"underlying","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b506139be806100206000396000f3fe608060405234801561001057600080fd5b506004361061030c5760003560e01c80637f1e06be1161019d578063bd6d894d116100e9578063f2b3abbd116100a2578063f851a4401161007c578063f851a440146106a8578063f8f9da28146106c0578063fca7820b146106c8578063fe9c44ae146106db57600080fd5b8063f2b3abbd1461066f578063f3fdb15a14610682578063f5e3c4621461069557600080fd5b8063bd6d894d146105cd578063c37f68e2146105d5578063c5ebeaec14610608578063db006a751461061b578063dd62ed3e1461062e578063e9c714f21461066757600080fd5b8063a0712d6811610156578063aa5af0fd11610130578063aa5af0fd14610596578063ae9d70b01461059f578063b2a02ff1146105a7578063b71d1a0c146105ba57600080fd5b8063a0712d6814610568578063a6afed951461057b578063a9059cbb1461058357600080fd5b80637f1e06be1461050b578063852a12e31461051e5780638f840ddd1461053157806395d89b411461053a57806395dd91931461054257806399d8c1b41461055557600080fd5b80633af9e6691161025c578063601a0bf1116102155780636c540baf116101ef5780636c540baf146104be5780636f307dc3146104c757806370a08231146104da57806373acee981461050357600080fd5b8063601a0bf1146104955780636752e702146104a857806369ab3250146104b657600080fd5b80633af9e669146104385780633b1d21a21461044b5780633e941010146104535780634576b5db1461046657806347bd3718146104795780635fe3b5671461048257600080fd5b8063182df0f5116102c957806323b872dd116102a357806323b872dd146103c85780632608f818146103db57806326782247146103ee578063313ce5671461041957600080fd5b8063182df0f5146103985780631a31d465146103a05780631be19560146103b557600080fd5b806306fdde0314610311578063095ea7b31461032f5780630e75270214610352578063173b99041461037357806317bfdfbc1461037c57806318160ddd1461038f575b600080fd5b6103196106e3565b6040516103269190613443565b60405180910390f35b61034261033d3660046134b0565b610771565b6040519015158152602001610326565b6103656103603660046134dc565b6107df565b604051908152602001610326565b61036560085481565b61036561038a3660046134f5565b6107f2565b610365600d5481565b61036561084e565b6103b36103ae3660046135cb565b61085d565b005b6103b36103c33660046134f5565b6108f2565b6103426103d6366004613681565b610abe565b6103656103e93660046134b0565b610b0e565b600454610401906001600160a01b031681565b6040516001600160a01b039091168152602001610326565b6003546104269060ff1681565b60405160ff9091168152602001610326565b6103656104463660046134f5565b610b23565b610365610b69565b6103656104613660046134dc565b610b73565b6103656104743660046134f5565b610b84565b610365600b5481565b600554610401906001600160a01b031681565b6103656104a33660046134dc565b610cd6565b610365666379da05b6000081565b610365600081565b61036560095481565b601154610401906001600160a01b031681565b6103656104e83660046134f5565b6001600160a01b03166000908152600e602052604090205490565b610365610d15565b6103b36105193660046134f5565b610d5f565b61036561052c3660046134dc565b610e36565b610365600c5481565b610319610e41565b6103656105503660046134f5565b610e4e565b6103b36105633660046136c2565b610e59565b6103656105763660046134dc565b6110b4565b6103656110bf565b6103426105913660046134b0565b6112ad565b610365600a5481565b6103656112fc565b6103656105b5366004613681565b611394565b6103656105c83660046134f5565b6113e3565b610365611470565b6105e86105e33660046134f5565b6114c0565b604080519485526020850193909352918301526060820152608001610326565b6103656106163660046134dc565b611501565b6103656106293660046134dc565b61150c565b61036561063c366004613764565b6001600160a01b039182166000908152600f6020908152604080832093909416825291909152205490565b610365611517565b61036561067d3660046134f5565b61161e565b600654610401906001600160a01b031681565b6103656106a336600461379d565b611632565b6003546104019061010090046001600160a01b031681565b610365611649565b6103656106d63660046134dc565b61169c565b610342600181565b600180546106f0906137df565b80601f016020809104026020016040519081016040528092919081815260200182805461071c906137df565b80156107695780601f1061073e57610100808354040283529160200191610769565b820191906000526020600020905b81548152906001019060200180831161074c57829003601f168201915b505050505081565b336000818152600f602090815260408083206001600160a01b03871680855292528083208590555191929182907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906107cd9087815260200190565b60405180910390a35060019392505050565b60006107ea826116db565b506000919050565b6000805460ff1661081e5760405162461bcd60e51b81526004016108159061381a565b60405180910390fd5b6000805460ff191690556108306110bf565b5061083a82610e4e565b90506000805460ff19166001179055919050565b600061085861172c565b905090565b61086b868686868686610e59565b601180546001600160a01b0319166001600160a01b038916908117909155604080516318160ddd60e01b815290516318160ddd916004808201926020929091908290030181865afa1580156108c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108e8919061383e565b5050505050505050565b60035461010090046001600160a01b031633146109695760405162461bcd60e51b815260206004820152602f60248201527f4345726332303a3a7377656570546f6b656e3a206f6e6c792061646d696e206360448201526e616e20737765657020746f6b656e7360881b6064820152608401610815565b6011546001600160a01b03828116911614156109e25760405162461bcd60e51b815260206004820152603260248201527f4345726332303a3a7377656570546f6b656e3a2063616e206e6f74207377656560448201527138103ab73232b9363cb4b733903a37b5b2b760711b6064820152608401610815565b6040516370a0823160e01b81523060048201526000906001600160a01b038316906370a0823190602401602060405180830381865afa158015610a29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a4d919061383e565b60035460405163a9059cbb60e01b81526001600160a01b03610100909204821660048201526024810183905291925083169063a9059cbb90604401600060405180830381600087803b158015610aa257600080fd5b505af1158015610ab6573d6000803e3d6000fd5b505050505050565b6000805460ff16610ae15760405162461bcd60e51b81526004016108159061381a565b6000805460ff19168155610af733868686611796565b1490506000805460ff191660011790559392505050565b6000610b1a83836119c4565b50600092915050565b6000806040518060200160405280610b39611470565b90526001600160a01b0384166000908152600e6020526040902054909150610b62908290611a16565b9392505050565b6000610858611a36565b6000610b7e82611aab565b92915050565b60035460009061010090046001600160a01b03163314610bb75760405163d219dc1f60e01b815260040160405180910390fd5b60055460408051623f1ee960e11b815290516001600160a01b0392831692851691627e3dd29160048083019260209291908290030181865afa158015610c01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c259190613857565b610c715760405162461bcd60e51b815260206004820152601c60248201527f6d61726b6572206d6574686f642072657475726e65642066616c7365000000006044820152606401610815565b600580546001600160a01b0319166001600160a01b0385811691821790925560408051928416835260208301919091527f7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d91015b60405180910390a150600092915050565b6000805460ff16610cf95760405162461bcd60e51b81526004016108159061381a565b6000805460ff19169055610d0b6110bf565b5061083a82611b02565b6000805460ff16610d385760405162461bcd60e51b81526004016108159061381a565b6000805460ff19169055610d4a6110bf565b5050600b546000805460ff1916600117905590565b60035461010090046001600160a01b03163314610dd45760405162461bcd60e51b815260206004820152602d60248201527f6f6e6c79207468652061646d696e206d6179207365742074686520636f6d702d60448201526c6c696b652064656c656761746560981b6064820152608401610815565b6011546040516317066a5760e21b81526001600160a01b03838116600483015290911690635c19a95c90602401600060405180830381600087803b158015610e1b57600080fd5b505af1158015610e2f573d6000803e3d6000fd5b5050505050565b60006107ea82611c1d565b600280546106f0906137df565b6000610b7e82611c6e565b60035461010090046001600160a01b03163314610ec45760405162461bcd60e51b8152602060048201526024808201527f6f6e6c792061646d696e206d617920696e697469616c697a6520746865206d616044820152631c9ad95d60e21b6064820152608401610815565b600954158015610ed45750600a54155b610f2c5760405162461bcd60e51b815260206004820152602360248201527f6d61726b6574206d6179206f6e6c7920626520696e697469616c697a6564206f6044820152626e636560e81b6064820152608401610815565b600784905583610f975760405162461bcd60e51b815260206004820152603060248201527f696e697469616c2065786368616e67652072617465206d75737420626520677260448201526f32b0ba32b9103a3430b7103d32b9379760811b6064820152608401610815565b6000610fa287610b84565b90508015610ff25760405162461bcd60e51b815260206004820152601a60248201527f73657474696e6720636f6d7074726f6c6c6572206661696c65640000000000006044820152606401610815565b43600955670de0b6b3a7640000600a5561100b86611cb8565b905080156110665760405162461bcd60e51b815260206004820152602260248201527f73657474696e6720696e7465726573742072617465206d6f64656c206661696c604482015261195960f21b6064820152608401610815565b83516110799060019060208701906133b3565b50825161108d9060029060208601906133b3565b50506003805460ff90921660ff199283161790556000805490911660011790555050505050565b60006107ea82611e2d565b6009546000904390808214156110d85760009250505090565b60006110e2611a36565b600b54600c54600a546006546040516315f2405360e01b81526004810186905260248101859052604481018490529495509293919290916000916001600160a01b0316906315f2405390606401602060405180830381865afa15801561114c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611170919061383e565b905065048c273950008111156111c85760405162461bcd60e51b815260206004820152601c60248201527f626f72726f772072617465206973206162737572646c792068696768000000006044820152606401610815565b60006111d4878961388f565b905060006111f060405180602001604052808581525083611e6c565b905060006111fe8288611a16565b9050600061120c88836138a6565b9050600061122b6040518060200160405280600854815250848a611e9d565b9050600061123a85898a611e9d565b60098e9055600a819055600b849055600c839055604080518d815260208101879052908101829052606081018590529091507f4dec04e750ca11537cabcd8a9eab06494de08da3735bc8871cd41250e190bc049060800160405180910390a160009d505050505050505050505050505090565b6000805460ff166112d05760405162461bcd60e51b81526004016108159061381a565b6000805460ff191681556112e633808686611796565b1490506000805460ff1916600117905592915050565b6006546000906001600160a01b031663b8168816611318611a36565b600b54600c546008546040516001600160e01b031960e087901b16815260048101949094526024840192909252604483015260648201526084015b602060405180830381865afa158015611370573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610858919061383e565b6000805460ff166113b75760405162461bcd60e51b81526004016108159061381a565b6000805460ff191690556113cd33858585611ebe565b50600080805460ff191660011790559392505050565b60035460009061010090046001600160a01b0316331461141657604051635cb56c2b60e01b815260040160405180910390fd5b600480546001600160a01b038481166001600160a01b031983168117909355604080519190921680825260208201939093527fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a99101610cc5565b6000805460ff166114935760405162461bcd60e51b81526004016108159061381a565b6000805460ff191690556114a56110bf565b506114ae61084e565b90506000805460ff1916600117905590565b6001600160a01b0381166000908152600e602052604081205481908190819081906114ea87611c6e565b6114f261172c565b93509350935093509193509193565b60006107ea82612137565b60006107ea82612176565b6004546000906001600160a01b031633141580611532575033155b1561155057604051631ba24f2960e21b815260040160405180910390fd5b60038054600480546001600160a01b03808216610100818102610100600160a81b0319871617968790556001600160a01b031990931690935560408051948390048216808652929095041660208401529290917ff9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc910160405180910390a1600454604080516001600160a01b03808516825290921660208301527fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9910160405180910390a160009250505090565b60006116286110bf565b50610b7e82611cb8565b600061163f8484846121b7565b5060009392505050565b6006546000906001600160a01b03166315f24053611665611a36565b600b54600c546040516001600160e01b031960e086901b168152600481019390935260248301919091526044820152606401611353565b6000805460ff166116bf5760405162461bcd60e51b81526004016108159061381a565b6000805460ff191690556116d16110bf565b5061083a82612295565b60005460ff166116fd5760405162461bcd60e51b81526004016108159061381a565b6000805460ff1916905561170f6110bf565b5061171b333383612351565b50506000805460ff19166001179055565b600d546000908061173f57505060075490565b6000611749611a36565b90506000600c54600b548361175e91906138a6565b611768919061388f565b905060008361177f670de0b6b3a7640000846138be565b61178991906138dd565b95945050505050565b5090565b6005546040516317b9b84b60e31b81523060048201526001600160a01b038581166024830152848116604483015260648201849052600092839291169063bdcdc258906084016020604051808303816000875af11580156117fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061181f919061383e565b905080156118435760405163089d427760e11b815260048101829052602401610815565b836001600160a01b0316856001600160a01b0316141561187657604051638cd22d1960e01b815260040160405180910390fd5b6000856001600160a01b0316876001600160a01b0316141561189b57506000196118c3565b506001600160a01b038086166000908152600f60209081526040808320938a16835292905220545b60006118cf858361388f565b6001600160a01b0388166000908152600e6020526040812054919250906118f790879061388f565b6001600160a01b0388166000908152600e60205260408120549192509061191f9088906138a6565b6001600160a01b03808b166000908152600e6020526040808220869055918b1681522081905590506000198414611979576001600160a01b03808a166000908152600f60209081526040808320938e168352929052208390555b876001600160a01b0316896001600160a01b0316600080516020613969833981519152896040516119ac91815260200190565b60405180910390a35060009998505050505050505050565b60005460ff166119e65760405162461bcd60e51b81526004016108159061381a565b6000805460ff191690556119f86110bf565b50611a04338383612351565b50506000805460ff1916600117905550565b600080611a238484611e6c565b9050611a2e816124fa565b949350505050565b6011546040516370a0823160e01b81523060048201526000916001600160a01b03169081906370a0823190602401602060405180830381865afa158015611a81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa5919061383e565b91505090565b6000805460ff16611ace5760405162461bcd60e51b81526004016108159061381a565b6000805460ff19169055611ae06110bf565b50611aea82612512565b5050600090506000805460ff19166001179055919050565b600354600090819061010090046001600160a01b03163314611b3757604051630f7e5e6d60e41b815260040160405180910390fd5b4360095414611b5957604051630dff50cb60e41b815260040160405180910390fd5b82611b62611a36565b1015611b8157604051633345e99960e01b815260040160405180910390fd5b600c54831115611ba4576040516378d2980560e11b815260040160405180910390fd5b82600c54611bb2919061388f565b600c819055600354909150611bd59061010090046001600160a01b0316846125a6565b7f3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e600360019054906101000a90046001600160a01b03168483604051610cc5939291906138ff565b60005460ff16611c3f5760405162461bcd60e51b81526004016108159061381a565b6000805460ff19169055611c516110bf565b50611c5e33600083612690565b506000805460ff19166001179055565b6001600160a01b03811660009081526010602052604081208054611c955750600092915050565b600a548154600091611ca6916138be565b9050816001015481611a2e91906138dd565b600354600090819061010090046001600160a01b03163314611ced5760405163407fded560e01b815260040160405180910390fd5b4360095414611d0f57604051630be2a5cb60e11b815260040160405180910390fd5b600660009054906101000a90046001600160a01b03169050826001600160a01b0316632191f92a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d65573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d899190613857565b611dd55760405162461bcd60e51b815260206004820152601c60248201527f6d61726b6572206d6574686f642072657475726e65642066616c7365000000006044820152606401610815565b600680546001600160a01b0319166001600160a01b0385811691821790925560408051928416835260208301919091527fedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f9269101610cc5565b60005460ff16611e4f5760405162461bcd60e51b81526004016108159061381a565b6000805460ff19169055611e616110bf565b50611c5e338261296d565b6040805160208101909152600081526040518060200160405280611e94856000015185612b23565b90529392505050565b600080611eaa8585611e6c565b9050611789611eb8826124fa565b84612b2f565b60055460405163d02f735160e01b81523060048201526001600160a01b0386811660248301528581166044830152848116606483015260848201849052600092169063d02f73519060a4016020604051808303816000875af1158015611f28573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f4c919061383e565b90508015611f70576040516363e00e3360e11b815260048101829052602401610815565b836001600160a01b0316836001600160a01b03161415611fa357604051633a94626760e11b815260040160405180910390fd5b6000611fc4836040518060200160405280666379da05b60000815250612b3b565b90506000611fd2828561388f565b905060006040518060200160405280611fe961172c565b905290506000611ff98285611a16565b9050600081600c5461200b91906138a6565b600c819055600d5490915061202190869061388f565b600d556001600160a01b0388166000908152600e602052604090205461204890889061388f565b6001600160a01b03808a166000908152600e602052604080822093909355908b16815220546120789085906138a6565b6001600160a01b03808b166000818152600e602052604090819020939093559151908a1690600080516020613969833981519152906120ba9088815260200190565b60405180910390a360405185815230906001600160a01b038a16906000805160206139698339815191529060200160405180910390a37fa91e67c5ea634cd43a12c5a482724b03de01e85ca68702a53d0c2f45cb7c1dc5308383604051612123939291906138ff565b60405180910390a150505050505050505050565b60005460ff166121595760405162461bcd60e51b81526004016108159061381a565b6000805460ff1916905561216b6110bf565b50611c5e3382612b5e565b60005460ff166121985760405162461bcd60e51b81526004016108159061381a565b6000805460ff191690556121aa6110bf565b50611c5e33826000612690565b60005460ff166121d95760405162461bcd60e51b81526004016108159061381a565b6000805460ff191690556121eb6110bf565b506000816001600160a01b031663a6afed956040518163ffffffff1660e01b81526004016020604051808303816000875af115801561222e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612252919061383e565b9050801561227657604051633eea49b760e11b815260048101829052602401610815565b61228233858585612cfd565b50506000805460ff191660011790555050565b60035460009061010090046001600160a01b031633146122c857604051631205b57b60e11b815260040160405180910390fd5b43600954146122ea57604051637dfca6b760e11b815260040160405180910390fd5b670de0b6b3a76400008211156123135760405163717220f360e11b815260040160405180910390fd5b600880549083905560408051828152602081018590527faaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f8214609101610cc5565b600554604051631200453160e11b81523060048201526001600160a01b03858116602483015284811660448301526064820184905260009283929116906324008a62906084016020604051808303816000875af11580156123b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123da919061383e565b905080156123fe57604051638c81362d60e01b815260048101829052602401610815565b43600954146124205760405163c9021e2f60e01b815260040160405180910390fd5b600061242b85611c6e565b90506000600019851461243e5784612440565b815b9050600061244e88836131b7565b9050600061245c828561388f565b9050600082600b5461246e919061388f565b6001600160a01b038a8116600081815260106020908152604091829020878155600a54600190910155600b8590558151938f168452830191909152810185905260608101849052608081018290529091507f1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a19060a00160405180910390a1509098975050505050505050565b8051600090610b7e90670de0b6b3a7640000906138dd565b6000808080436009541461253c576040516338acf79960e01b815260048101829052602401610815565b61254633866131b7565b905080600c5461255691906138a6565b915081600c819055507fa91e67c5ea634cd43a12c5a482724b03de01e85ca68702a53d0c2f45cb7c1dc5338284604051612592939291906138ff565b60405180910390a160009590945092505050565b60115460405163a9059cbb60e01b81526001600160a01b0384811660048301526024820184905290911690819063a9059cbb90604401600060405180830381600087803b1580156125f657600080fd5b505af115801561260a573d6000803e3d6000fd5b5050505060003d60008114612626576020811461263057600080fd5b600019915061263c565b60206000803e60005191505b508061268a5760405162461bcd60e51b815260206004820152601960248201527f544f4b454e5f5452414e534645525f4f55545f4641494c4544000000000000006044820152606401610815565b50505050565b81158061269b575080155b6127045760405162461bcd60e51b815260206004820152603460248201527f6f6e65206f662072656465656d546f6b656e73496e206f722072656465656d416044820152736d6f756e74496e206d757374206265207a65726f60601b6064820152608401610815565b6000604051806020016040528061271961172c565b90529050600080841561273a578491506127338386611a16565b905061274a565b612744848461338e565b91508390505b60055460405163eabe7d9160e01b81526000916001600160a01b03169063eabe7d919061277f9030908b908890600401613920565b6020604051808303816000875af115801561279e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127c2919061383e565b905080156127e65760405163480f424760e01b815260048101829052602401610815565b4360095414612808576040516397b5cfcd60e01b815260040160405180910390fd5b81612811611a36565b1015612830576040516391240a1b60e01b815260040160405180910390fd5b82600d5461283e919061388f565b600d556001600160a01b0387166000908152600e602052604090205461286590849061388f565b6001600160a01b0388166000908152600e602052604090205561288887836125a6565b60405183815230906001600160a01b038916906000805160206139698339815191529060200160405180910390a37fe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a9298783856040516128e9939291906138ff565b60405180910390a16005546040516351dff98960e01b81523060048201526001600160a01b0389811660248301526044820185905260648201869052909116906351dff98990608401600060405180830381600087803b15801561294c57600080fd5b505af1158015612960573d6000803e3d6000fd5b5050505050505050505050565b600554604051634ef4c3e160e01b81526000916001600160a01b031690634ef4c3e1906129a290309087908790600401613920565b6020604051808303816000875af11580156129c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129e5919061383e565b90508015612a09576040516349abd4fd60e01b815260048101829052602401610815565b4360095414612a2b576040516338d8859760e01b815260040160405180910390fd5b60006040518060200160405280612a4061172c565b905290506000612a5085856131b7565b90506000612a5e828461338e565b905080600d54612a6e91906138a6565b600d556001600160a01b0386166000908152600e6020526040902054612a959082906138a6565b6001600160a01b0387166000908152600e60205260409081902091909155517f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f90612ae5908890859085906138ff565b60405180910390a16040518181526001600160a01b0387169030906000805160206139698339815191529060200160405180910390a3505050505050565b6000610b6282846138be565b6000610b6282846138a6565b6000670de0b6b3a7640000612b54848460000151612b23565b610b6291906138dd565b60055460405163368f515360e21b81526000916001600160a01b03169063da3d454c90612b9390309087908790600401613920565b6020604051808303816000875af1158015612bb2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bd6919061383e565b90508015612bfa5760405163918db40f60e01b815260048101829052602401610815565b4360095414612c1c57604051630e8d8c6160e21b815260040160405180910390fd5b81612c25611a36565b1015612c44576040516348c2588160e01b815260040160405180910390fd5b6000612c4f84611c6e565b90506000612c5d84836138a6565b9050600084600b54612c6f91906138a6565b6001600160a01b0387166000908152601060205260409020838155600a54600190910155600b8190559050612ca486866125a6565b604080516001600160a01b038816815260208101879052908101839052606081018290527f13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab809060800160405180910390a1505050505050565b600554604051632fe3f38f60e11b81523060048201526001600160a01b03838116602483015286811660448301528581166064830152608482018590526000921690635fc7e71e9060a4016020604051808303816000875af1158015612d67573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d8b919061383e565b90508015612daf57604051630a14d17960e11b815260048101829052602401610815565b4360095414612dd1576040516380965b1b60e01b815260040160405180910390fd5b43826001600160a01b0316636c540baf6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612e10573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e34919061383e565b14612e5257604051631046f38d60e31b815260040160405180910390fd5b846001600160a01b0316846001600160a01b03161415612e8557604051631bd1a62160e21b815260040160405180910390fd5b82612ea35760405163d29da7ef60e01b815260040160405180910390fd5b600019831415612ec657604051635982c5bb60e11b815260040160405180910390fd5b6000612ed3868686612351565b60055460405163c488847b60e01b815291925060009182916001600160a01b03169063c488847b90612f0d90309089908890600401613920565b6040805180830381865afa158015612f29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f4d9190613944565b9150915060008214612fbd5760405162461bcd60e51b815260206004820152603360248201527f4c49515549444154455f434f4d5054524f4c4c45525f43414c43554c4154455f604482015272105353d5539517d4d152569157d19052531151606a1b6064820152608401610815565b6040516370a0823160e01b81526001600160a01b0388811660048301528291908716906370a0823190602401602060405180830381865afa158015613006573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061302a919061383e565b10156130785760405162461bcd60e51b815260206004820152601860248201527f4c49515549444154455f5345495a455f544f4f5f4d55434800000000000000006044820152606401610815565b6001600160a01b03851630141561309a5761309530898984611ebe565b613154565b60405163b2a02ff160e01b81526000906001600160a01b0387169063b2a02ff1906130cd908c908c908790600401613920565b6020604051808303816000875af11580156130ec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613110919061383e565b146131545760405162461bcd60e51b81526020600482015260146024820152731d1bdad95b881cd95a5e9d5c994819985a5b195960621b6044820152606401610815565b604080516001600160a01b038a811682528981166020830152818301869052871660608201526080810183905290517f298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb529181900360a00190a15050505050505050565b6011546040516370a0823160e01b81523060048201526000916001600160a01b0316908190839082906370a0823190602401602060405180830381865afa158015613206573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061322a919061383e565b6040516323b872dd60e01b81529091506001600160a01b038316906323b872dd9061325d90899030908a90600401613920565b600060405180830381600087803b15801561327757600080fd5b505af115801561328b573d6000803e3d6000fd5b5050505060003d600081146132a757602081146132b157600080fd5b60001991506132bd565b60206000803e60005191505b508061330b5760405162461bcd60e51b815260206004820152601860248201527f544f4b454e5f5452414e534645525f494e5f4641494c454400000000000000006044820152606401610815565b6040516370a0823160e01b81523060048201526000906001600160a01b038616906370a0823190602401602060405180830381865afa158015613352573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613376919061383e565b9050613382838261388f565b98975050505050505050565b6000610b626133a584670de0b6b3a7640000612b23565b83516000610b6282846138dd565b8280546133bf906137df565b90600052602060002090601f0160209004810192826133e15760008555613427565b82601f106133fa57805160ff1916838001178555613427565b82800160010185558215613427579182015b8281111561342757825182559160200191906001019061340c565b506117929291505b80821115611792576000815560010161342f565b600060208083528351808285015260005b8181101561347057858101830151858201604001528201613454565b81811115613482576000604083870101525b50601f01601f1916929092016040019392505050565b6001600160a01b03811681146134ad57600080fd5b50565b600080604083850312156134c357600080fd5b82356134ce81613498565b946020939093013593505050565b6000602082840312156134ee57600080fd5b5035919050565b60006020828403121561350757600080fd5b8135610b6281613498565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261353957600080fd5b813567ffffffffffffffff8082111561355457613554613512565b604051601f8301601f19908116603f0116810190828211818310171561357c5761357c613512565b8160405283815286602085880101111561359557600080fd5b836020870160208301376000602085830101528094505050505092915050565b803560ff811681146135c657600080fd5b919050565b600080600080600080600060e0888a0312156135e657600080fd5b87356135f181613498565b9650602088013561360181613498565b9550604088013561361181613498565b945060608801359350608088013567ffffffffffffffff8082111561363557600080fd5b6136418b838c01613528565b945060a08a013591508082111561365757600080fd5b506136648a828b01613528565b92505061367360c089016135b5565b905092959891949750929550565b60008060006060848603121561369657600080fd5b83356136a181613498565b925060208401356136b181613498565b929592945050506040919091013590565b60008060008060008060c087890312156136db57600080fd5b86356136e681613498565b955060208701356136f681613498565b945060408701359350606087013567ffffffffffffffff8082111561371a57600080fd5b6137268a838b01613528565b9450608089013591508082111561373c57600080fd5b5061374989828a01613528565b92505061375860a088016135b5565b90509295509295509295565b6000806040838503121561377757600080fd5b823561378281613498565b9150602083013561379281613498565b809150509250929050565b6000806000606084860312156137b257600080fd5b83356137bd81613498565b92506020840135915060408401356137d481613498565b809150509250925092565b600181811c908216806137f357607f821691505b6020821081141561381457634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252600a90820152691c994b595b9d195c995960b21b604082015260600190565b60006020828403121561385057600080fd5b5051919050565b60006020828403121561386957600080fd5b81518015158114610b6257600080fd5b634e487b7160e01b600052601160045260246000fd5b6000828210156138a1576138a1613879565b500390565b600082198211156138b9576138b9613879565b500190565b60008160001904831182151516156138d8576138d8613879565b500290565b6000826138fa57634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b039390931683526020830191909152604082015260600190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6000806040838503121561395757600080fd5b50508051602090910151909290915056feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa26469706673582212206986794797f3615ae938bfb57cf952b9655c64451480c72bc64a1f974150c38564736f6c634300080a0033
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061030c5760003560e01c80637f1e06be1161019d578063bd6d894d116100e9578063f2b3abbd116100a2578063f851a4401161007c578063f851a440146106a8578063f8f9da28146106c0578063fca7820b146106c8578063fe9c44ae146106db57600080fd5b8063f2b3abbd1461066f578063f3fdb15a14610682578063f5e3c4621461069557600080fd5b8063bd6d894d146105cd578063c37f68e2146105d5578063c5ebeaec14610608578063db006a751461061b578063dd62ed3e1461062e578063e9c714f21461066757600080fd5b8063a0712d6811610156578063aa5af0fd11610130578063aa5af0fd14610596578063ae9d70b01461059f578063b2a02ff1146105a7578063b71d1a0c146105ba57600080fd5b8063a0712d6814610568578063a6afed951461057b578063a9059cbb1461058357600080fd5b80637f1e06be1461050b578063852a12e31461051e5780638f840ddd1461053157806395d89b411461053a57806395dd91931461054257806399d8c1b41461055557600080fd5b80633af9e6691161025c578063601a0bf1116102155780636c540baf116101ef5780636c540baf146104be5780636f307dc3146104c757806370a08231146104da57806373acee981461050357600080fd5b8063601a0bf1146104955780636752e702146104a857806369ab3250146104b657600080fd5b80633af9e669146104385780633b1d21a21461044b5780633e941010146104535780634576b5db1461046657806347bd3718146104795780635fe3b5671461048257600080fd5b8063182df0f5116102c957806323b872dd116102a357806323b872dd146103c85780632608f818146103db57806326782247146103ee578063313ce5671461041957600080fd5b8063182df0f5146103985780631a31d465146103a05780631be19560146103b557600080fd5b806306fdde0314610311578063095ea7b31461032f5780630e75270214610352578063173b99041461037357806317bfdfbc1461037c57806318160ddd1461038f575b600080fd5b6103196106e3565b6040516103269190613443565b60405180910390f35b61034261033d3660046134b0565b610771565b6040519015158152602001610326565b6103656103603660046134dc565b6107df565b604051908152602001610326565b61036560085481565b61036561038a3660046134f5565b6107f2565b610365600d5481565b61036561084e565b6103b36103ae3660046135cb565b61085d565b005b6103b36103c33660046134f5565b6108f2565b6103426103d6366004613681565b610abe565b6103656103e93660046134b0565b610b0e565b600454610401906001600160a01b031681565b6040516001600160a01b039091168152602001610326565b6003546104269060ff1681565b60405160ff9091168152602001610326565b6103656104463660046134f5565b610b23565b610365610b69565b6103656104613660046134dc565b610b73565b6103656104743660046134f5565b610b84565b610365600b5481565b600554610401906001600160a01b031681565b6103656104a33660046134dc565b610cd6565b610365666379da05b6000081565b610365600081565b61036560095481565b601154610401906001600160a01b031681565b6103656104e83660046134f5565b6001600160a01b03166000908152600e602052604090205490565b610365610d15565b6103b36105193660046134f5565b610d5f565b61036561052c3660046134dc565b610e36565b610365600c5481565b610319610e41565b6103656105503660046134f5565b610e4e565b6103b36105633660046136c2565b610e59565b6103656105763660046134dc565b6110b4565b6103656110bf565b6103426105913660046134b0565b6112ad565b610365600a5481565b6103656112fc565b6103656105b5366004613681565b611394565b6103656105c83660046134f5565b6113e3565b610365611470565b6105e86105e33660046134f5565b6114c0565b604080519485526020850193909352918301526060820152608001610326565b6103656106163660046134dc565b611501565b6103656106293660046134dc565b61150c565b61036561063c366004613764565b6001600160a01b039182166000908152600f6020908152604080832093909416825291909152205490565b610365611517565b61036561067d3660046134f5565b61161e565b600654610401906001600160a01b031681565b6103656106a336600461379d565b611632565b6003546104019061010090046001600160a01b031681565b610365611649565b6103656106d63660046134dc565b61169c565b610342600181565b600180546106f0906137df565b80601f016020809104026020016040519081016040528092919081815260200182805461071c906137df565b80156107695780601f1061073e57610100808354040283529160200191610769565b820191906000526020600020905b81548152906001019060200180831161074c57829003601f168201915b505050505081565b336000818152600f602090815260408083206001600160a01b03871680855292528083208590555191929182907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906107cd9087815260200190565b60405180910390a35060019392505050565b60006107ea826116db565b506000919050565b6000805460ff1661081e5760405162461bcd60e51b81526004016108159061381a565b60405180910390fd5b6000805460ff191690556108306110bf565b5061083a82610e4e565b90506000805460ff19166001179055919050565b600061085861172c565b905090565b61086b868686868686610e59565b601180546001600160a01b0319166001600160a01b038916908117909155604080516318160ddd60e01b815290516318160ddd916004808201926020929091908290030181865afa1580156108c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108e8919061383e565b5050505050505050565b60035461010090046001600160a01b031633146109695760405162461bcd60e51b815260206004820152602f60248201527f4345726332303a3a7377656570546f6b656e3a206f6e6c792061646d696e206360448201526e616e20737765657020746f6b656e7360881b6064820152608401610815565b6011546001600160a01b03828116911614156109e25760405162461bcd60e51b815260206004820152603260248201527f4345726332303a3a7377656570546f6b656e3a2063616e206e6f74207377656560448201527138103ab73232b9363cb4b733903a37b5b2b760711b6064820152608401610815565b6040516370a0823160e01b81523060048201526000906001600160a01b038316906370a0823190602401602060405180830381865afa158015610a29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a4d919061383e565b60035460405163a9059cbb60e01b81526001600160a01b03610100909204821660048201526024810183905291925083169063a9059cbb90604401600060405180830381600087803b158015610aa257600080fd5b505af1158015610ab6573d6000803e3d6000fd5b505050505050565b6000805460ff16610ae15760405162461bcd60e51b81526004016108159061381a565b6000805460ff19168155610af733868686611796565b1490506000805460ff191660011790559392505050565b6000610b1a83836119c4565b50600092915050565b6000806040518060200160405280610b39611470565b90526001600160a01b0384166000908152600e6020526040902054909150610b62908290611a16565b9392505050565b6000610858611a36565b6000610b7e82611aab565b92915050565b60035460009061010090046001600160a01b03163314610bb75760405163d219dc1f60e01b815260040160405180910390fd5b60055460408051623f1ee960e11b815290516001600160a01b0392831692851691627e3dd29160048083019260209291908290030181865afa158015610c01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c259190613857565b610c715760405162461bcd60e51b815260206004820152601c60248201527f6d61726b6572206d6574686f642072657475726e65642066616c7365000000006044820152606401610815565b600580546001600160a01b0319166001600160a01b0385811691821790925560408051928416835260208301919091527f7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d91015b60405180910390a150600092915050565b6000805460ff16610cf95760405162461bcd60e51b81526004016108159061381a565b6000805460ff19169055610d0b6110bf565b5061083a82611b02565b6000805460ff16610d385760405162461bcd60e51b81526004016108159061381a565b6000805460ff19169055610d4a6110bf565b5050600b546000805460ff1916600117905590565b60035461010090046001600160a01b03163314610dd45760405162461bcd60e51b815260206004820152602d60248201527f6f6e6c79207468652061646d696e206d6179207365742074686520636f6d702d60448201526c6c696b652064656c656761746560981b6064820152608401610815565b6011546040516317066a5760e21b81526001600160a01b03838116600483015290911690635c19a95c90602401600060405180830381600087803b158015610e1b57600080fd5b505af1158015610e2f573d6000803e3d6000fd5b5050505050565b60006107ea82611c1d565b600280546106f0906137df565b6000610b7e82611c6e565b60035461010090046001600160a01b03163314610ec45760405162461bcd60e51b8152602060048201526024808201527f6f6e6c792061646d696e206d617920696e697469616c697a6520746865206d616044820152631c9ad95d60e21b6064820152608401610815565b600954158015610ed45750600a54155b610f2c5760405162461bcd60e51b815260206004820152602360248201527f6d61726b6574206d6179206f6e6c7920626520696e697469616c697a6564206f6044820152626e636560e81b6064820152608401610815565b600784905583610f975760405162461bcd60e51b815260206004820152603060248201527f696e697469616c2065786368616e67652072617465206d75737420626520677260448201526f32b0ba32b9103a3430b7103d32b9379760811b6064820152608401610815565b6000610fa287610b84565b90508015610ff25760405162461bcd60e51b815260206004820152601a60248201527f73657474696e6720636f6d7074726f6c6c6572206661696c65640000000000006044820152606401610815565b43600955670de0b6b3a7640000600a5561100b86611cb8565b905080156110665760405162461bcd60e51b815260206004820152602260248201527f73657474696e6720696e7465726573742072617465206d6f64656c206661696c604482015261195960f21b6064820152608401610815565b83516110799060019060208701906133b3565b50825161108d9060029060208601906133b3565b50506003805460ff90921660ff199283161790556000805490911660011790555050505050565b60006107ea82611e2d565b6009546000904390808214156110d85760009250505090565b60006110e2611a36565b600b54600c54600a546006546040516315f2405360e01b81526004810186905260248101859052604481018490529495509293919290916000916001600160a01b0316906315f2405390606401602060405180830381865afa15801561114c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611170919061383e565b905065048c273950008111156111c85760405162461bcd60e51b815260206004820152601c60248201527f626f72726f772072617465206973206162737572646c792068696768000000006044820152606401610815565b60006111d4878961388f565b905060006111f060405180602001604052808581525083611e6c565b905060006111fe8288611a16565b9050600061120c88836138a6565b9050600061122b6040518060200160405280600854815250848a611e9d565b9050600061123a85898a611e9d565b60098e9055600a819055600b849055600c839055604080518d815260208101879052908101829052606081018590529091507f4dec04e750ca11537cabcd8a9eab06494de08da3735bc8871cd41250e190bc049060800160405180910390a160009d505050505050505050505050505090565b6000805460ff166112d05760405162461bcd60e51b81526004016108159061381a565b6000805460ff191681556112e633808686611796565b1490506000805460ff1916600117905592915050565b6006546000906001600160a01b031663b8168816611318611a36565b600b54600c546008546040516001600160e01b031960e087901b16815260048101949094526024840192909252604483015260648201526084015b602060405180830381865afa158015611370573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610858919061383e565b6000805460ff166113b75760405162461bcd60e51b81526004016108159061381a565b6000805460ff191690556113cd33858585611ebe565b50600080805460ff191660011790559392505050565b60035460009061010090046001600160a01b0316331461141657604051635cb56c2b60e01b815260040160405180910390fd5b600480546001600160a01b038481166001600160a01b031983168117909355604080519190921680825260208201939093527fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a99101610cc5565b6000805460ff166114935760405162461bcd60e51b81526004016108159061381a565b6000805460ff191690556114a56110bf565b506114ae61084e565b90506000805460ff1916600117905590565b6001600160a01b0381166000908152600e602052604081205481908190819081906114ea87611c6e565b6114f261172c565b93509350935093509193509193565b60006107ea82612137565b60006107ea82612176565b6004546000906001600160a01b031633141580611532575033155b1561155057604051631ba24f2960e21b815260040160405180910390fd5b60038054600480546001600160a01b03808216610100818102610100600160a81b0319871617968790556001600160a01b031990931690935560408051948390048216808652929095041660208401529290917ff9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc910160405180910390a1600454604080516001600160a01b03808516825290921660208301527fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9910160405180910390a160009250505090565b60006116286110bf565b50610b7e82611cb8565b600061163f8484846121b7565b5060009392505050565b6006546000906001600160a01b03166315f24053611665611a36565b600b54600c546040516001600160e01b031960e086901b168152600481019390935260248301919091526044820152606401611353565b6000805460ff166116bf5760405162461bcd60e51b81526004016108159061381a565b6000805460ff191690556116d16110bf565b5061083a82612295565b60005460ff166116fd5760405162461bcd60e51b81526004016108159061381a565b6000805460ff1916905561170f6110bf565b5061171b333383612351565b50506000805460ff19166001179055565b600d546000908061173f57505060075490565b6000611749611a36565b90506000600c54600b548361175e91906138a6565b611768919061388f565b905060008361177f670de0b6b3a7640000846138be565b61178991906138dd565b95945050505050565b5090565b6005546040516317b9b84b60e31b81523060048201526001600160a01b038581166024830152848116604483015260648201849052600092839291169063bdcdc258906084016020604051808303816000875af11580156117fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061181f919061383e565b905080156118435760405163089d427760e11b815260048101829052602401610815565b836001600160a01b0316856001600160a01b0316141561187657604051638cd22d1960e01b815260040160405180910390fd5b6000856001600160a01b0316876001600160a01b0316141561189b57506000196118c3565b506001600160a01b038086166000908152600f60209081526040808320938a16835292905220545b60006118cf858361388f565b6001600160a01b0388166000908152600e6020526040812054919250906118f790879061388f565b6001600160a01b0388166000908152600e60205260408120549192509061191f9088906138a6565b6001600160a01b03808b166000908152600e6020526040808220869055918b1681522081905590506000198414611979576001600160a01b03808a166000908152600f60209081526040808320938e168352929052208390555b876001600160a01b0316896001600160a01b0316600080516020613969833981519152896040516119ac91815260200190565b60405180910390a35060009998505050505050505050565b60005460ff166119e65760405162461bcd60e51b81526004016108159061381a565b6000805460ff191690556119f86110bf565b50611a04338383612351565b50506000805460ff1916600117905550565b600080611a238484611e6c565b9050611a2e816124fa565b949350505050565b6011546040516370a0823160e01b81523060048201526000916001600160a01b03169081906370a0823190602401602060405180830381865afa158015611a81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa5919061383e565b91505090565b6000805460ff16611ace5760405162461bcd60e51b81526004016108159061381a565b6000805460ff19169055611ae06110bf565b50611aea82612512565b5050600090506000805460ff19166001179055919050565b600354600090819061010090046001600160a01b03163314611b3757604051630f7e5e6d60e41b815260040160405180910390fd5b4360095414611b5957604051630dff50cb60e41b815260040160405180910390fd5b82611b62611a36565b1015611b8157604051633345e99960e01b815260040160405180910390fd5b600c54831115611ba4576040516378d2980560e11b815260040160405180910390fd5b82600c54611bb2919061388f565b600c819055600354909150611bd59061010090046001600160a01b0316846125a6565b7f3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e600360019054906101000a90046001600160a01b03168483604051610cc5939291906138ff565b60005460ff16611c3f5760405162461bcd60e51b81526004016108159061381a565b6000805460ff19169055611c516110bf565b50611c5e33600083612690565b506000805460ff19166001179055565b6001600160a01b03811660009081526010602052604081208054611c955750600092915050565b600a548154600091611ca6916138be565b9050816001015481611a2e91906138dd565b600354600090819061010090046001600160a01b03163314611ced5760405163407fded560e01b815260040160405180910390fd5b4360095414611d0f57604051630be2a5cb60e11b815260040160405180910390fd5b600660009054906101000a90046001600160a01b03169050826001600160a01b0316632191f92a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d65573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d899190613857565b611dd55760405162461bcd60e51b815260206004820152601c60248201527f6d61726b6572206d6574686f642072657475726e65642066616c7365000000006044820152606401610815565b600680546001600160a01b0319166001600160a01b0385811691821790925560408051928416835260208301919091527fedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f9269101610cc5565b60005460ff16611e4f5760405162461bcd60e51b81526004016108159061381a565b6000805460ff19169055611e616110bf565b50611c5e338261296d565b6040805160208101909152600081526040518060200160405280611e94856000015185612b23565b90529392505050565b600080611eaa8585611e6c565b9050611789611eb8826124fa565b84612b2f565b60055460405163d02f735160e01b81523060048201526001600160a01b0386811660248301528581166044830152848116606483015260848201849052600092169063d02f73519060a4016020604051808303816000875af1158015611f28573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f4c919061383e565b90508015611f70576040516363e00e3360e11b815260048101829052602401610815565b836001600160a01b0316836001600160a01b03161415611fa357604051633a94626760e11b815260040160405180910390fd5b6000611fc4836040518060200160405280666379da05b60000815250612b3b565b90506000611fd2828561388f565b905060006040518060200160405280611fe961172c565b905290506000611ff98285611a16565b9050600081600c5461200b91906138a6565b600c819055600d5490915061202190869061388f565b600d556001600160a01b0388166000908152600e602052604090205461204890889061388f565b6001600160a01b03808a166000908152600e602052604080822093909355908b16815220546120789085906138a6565b6001600160a01b03808b166000818152600e602052604090819020939093559151908a1690600080516020613969833981519152906120ba9088815260200190565b60405180910390a360405185815230906001600160a01b038a16906000805160206139698339815191529060200160405180910390a37fa91e67c5ea634cd43a12c5a482724b03de01e85ca68702a53d0c2f45cb7c1dc5308383604051612123939291906138ff565b60405180910390a150505050505050505050565b60005460ff166121595760405162461bcd60e51b81526004016108159061381a565b6000805460ff1916905561216b6110bf565b50611c5e3382612b5e565b60005460ff166121985760405162461bcd60e51b81526004016108159061381a565b6000805460ff191690556121aa6110bf565b50611c5e33826000612690565b60005460ff166121d95760405162461bcd60e51b81526004016108159061381a565b6000805460ff191690556121eb6110bf565b506000816001600160a01b031663a6afed956040518163ffffffff1660e01b81526004016020604051808303816000875af115801561222e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612252919061383e565b9050801561227657604051633eea49b760e11b815260048101829052602401610815565b61228233858585612cfd565b50506000805460ff191660011790555050565b60035460009061010090046001600160a01b031633146122c857604051631205b57b60e11b815260040160405180910390fd5b43600954146122ea57604051637dfca6b760e11b815260040160405180910390fd5b670de0b6b3a76400008211156123135760405163717220f360e11b815260040160405180910390fd5b600880549083905560408051828152602081018590527faaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f8214609101610cc5565b600554604051631200453160e11b81523060048201526001600160a01b03858116602483015284811660448301526064820184905260009283929116906324008a62906084016020604051808303816000875af11580156123b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123da919061383e565b905080156123fe57604051638c81362d60e01b815260048101829052602401610815565b43600954146124205760405163c9021e2f60e01b815260040160405180910390fd5b600061242b85611c6e565b90506000600019851461243e5784612440565b815b9050600061244e88836131b7565b9050600061245c828561388f565b9050600082600b5461246e919061388f565b6001600160a01b038a8116600081815260106020908152604091829020878155600a54600190910155600b8590558151938f168452830191909152810185905260608101849052608081018290529091507f1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a19060a00160405180910390a1509098975050505050505050565b8051600090610b7e90670de0b6b3a7640000906138dd565b6000808080436009541461253c576040516338acf79960e01b815260048101829052602401610815565b61254633866131b7565b905080600c5461255691906138a6565b915081600c819055507fa91e67c5ea634cd43a12c5a482724b03de01e85ca68702a53d0c2f45cb7c1dc5338284604051612592939291906138ff565b60405180910390a160009590945092505050565b60115460405163a9059cbb60e01b81526001600160a01b0384811660048301526024820184905290911690819063a9059cbb90604401600060405180830381600087803b1580156125f657600080fd5b505af115801561260a573d6000803e3d6000fd5b5050505060003d60008114612626576020811461263057600080fd5b600019915061263c565b60206000803e60005191505b508061268a5760405162461bcd60e51b815260206004820152601960248201527f544f4b454e5f5452414e534645525f4f55545f4641494c4544000000000000006044820152606401610815565b50505050565b81158061269b575080155b6127045760405162461bcd60e51b815260206004820152603460248201527f6f6e65206f662072656465656d546f6b656e73496e206f722072656465656d416044820152736d6f756e74496e206d757374206265207a65726f60601b6064820152608401610815565b6000604051806020016040528061271961172c565b90529050600080841561273a578491506127338386611a16565b905061274a565b612744848461338e565b91508390505b60055460405163eabe7d9160e01b81526000916001600160a01b03169063eabe7d919061277f9030908b908890600401613920565b6020604051808303816000875af115801561279e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127c2919061383e565b905080156127e65760405163480f424760e01b815260048101829052602401610815565b4360095414612808576040516397b5cfcd60e01b815260040160405180910390fd5b81612811611a36565b1015612830576040516391240a1b60e01b815260040160405180910390fd5b82600d5461283e919061388f565b600d556001600160a01b0387166000908152600e602052604090205461286590849061388f565b6001600160a01b0388166000908152600e602052604090205561288887836125a6565b60405183815230906001600160a01b038916906000805160206139698339815191529060200160405180910390a37fe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a9298783856040516128e9939291906138ff565b60405180910390a16005546040516351dff98960e01b81523060048201526001600160a01b0389811660248301526044820185905260648201869052909116906351dff98990608401600060405180830381600087803b15801561294c57600080fd5b505af1158015612960573d6000803e3d6000fd5b5050505050505050505050565b600554604051634ef4c3e160e01b81526000916001600160a01b031690634ef4c3e1906129a290309087908790600401613920565b6020604051808303816000875af11580156129c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129e5919061383e565b90508015612a09576040516349abd4fd60e01b815260048101829052602401610815565b4360095414612a2b576040516338d8859760e01b815260040160405180910390fd5b60006040518060200160405280612a4061172c565b905290506000612a5085856131b7565b90506000612a5e828461338e565b905080600d54612a6e91906138a6565b600d556001600160a01b0386166000908152600e6020526040902054612a959082906138a6565b6001600160a01b0387166000908152600e60205260409081902091909155517f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f90612ae5908890859085906138ff565b60405180910390a16040518181526001600160a01b0387169030906000805160206139698339815191529060200160405180910390a3505050505050565b6000610b6282846138be565b6000610b6282846138a6565b6000670de0b6b3a7640000612b54848460000151612b23565b610b6291906138dd565b60055460405163368f515360e21b81526000916001600160a01b03169063da3d454c90612b9390309087908790600401613920565b6020604051808303816000875af1158015612bb2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bd6919061383e565b90508015612bfa5760405163918db40f60e01b815260048101829052602401610815565b4360095414612c1c57604051630e8d8c6160e21b815260040160405180910390fd5b81612c25611a36565b1015612c44576040516348c2588160e01b815260040160405180910390fd5b6000612c4f84611c6e565b90506000612c5d84836138a6565b9050600084600b54612c6f91906138a6565b6001600160a01b0387166000908152601060205260409020838155600a54600190910155600b8190559050612ca486866125a6565b604080516001600160a01b038816815260208101879052908101839052606081018290527f13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab809060800160405180910390a1505050505050565b600554604051632fe3f38f60e11b81523060048201526001600160a01b03838116602483015286811660448301528581166064830152608482018590526000921690635fc7e71e9060a4016020604051808303816000875af1158015612d67573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d8b919061383e565b90508015612daf57604051630a14d17960e11b815260048101829052602401610815565b4360095414612dd1576040516380965b1b60e01b815260040160405180910390fd5b43826001600160a01b0316636c540baf6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612e10573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e34919061383e565b14612e5257604051631046f38d60e31b815260040160405180910390fd5b846001600160a01b0316846001600160a01b03161415612e8557604051631bd1a62160e21b815260040160405180910390fd5b82612ea35760405163d29da7ef60e01b815260040160405180910390fd5b600019831415612ec657604051635982c5bb60e11b815260040160405180910390fd5b6000612ed3868686612351565b60055460405163c488847b60e01b815291925060009182916001600160a01b03169063c488847b90612f0d90309089908890600401613920565b6040805180830381865afa158015612f29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f4d9190613944565b9150915060008214612fbd5760405162461bcd60e51b815260206004820152603360248201527f4c49515549444154455f434f4d5054524f4c4c45525f43414c43554c4154455f604482015272105353d5539517d4d152569157d19052531151606a1b6064820152608401610815565b6040516370a0823160e01b81526001600160a01b0388811660048301528291908716906370a0823190602401602060405180830381865afa158015613006573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061302a919061383e565b10156130785760405162461bcd60e51b815260206004820152601860248201527f4c49515549444154455f5345495a455f544f4f5f4d55434800000000000000006044820152606401610815565b6001600160a01b03851630141561309a5761309530898984611ebe565b613154565b60405163b2a02ff160e01b81526000906001600160a01b0387169063b2a02ff1906130cd908c908c908790600401613920565b6020604051808303816000875af11580156130ec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613110919061383e565b146131545760405162461bcd60e51b81526020600482015260146024820152731d1bdad95b881cd95a5e9d5c994819985a5b195960621b6044820152606401610815565b604080516001600160a01b038a811682528981166020830152818301869052871660608201526080810183905290517f298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb529181900360a00190a15050505050505050565b6011546040516370a0823160e01b81523060048201526000916001600160a01b0316908190839082906370a0823190602401602060405180830381865afa158015613206573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061322a919061383e565b6040516323b872dd60e01b81529091506001600160a01b038316906323b872dd9061325d90899030908a90600401613920565b600060405180830381600087803b15801561327757600080fd5b505af115801561328b573d6000803e3d6000fd5b5050505060003d600081146132a757602081146132b157600080fd5b60001991506132bd565b60206000803e60005191505b508061330b5760405162461bcd60e51b815260206004820152601860248201527f544f4b454e5f5452414e534645525f494e5f4641494c454400000000000000006044820152606401610815565b6040516370a0823160e01b81523060048201526000906001600160a01b038616906370a0823190602401602060405180830381865afa158015613352573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613376919061383e565b9050613382838261388f565b98975050505050505050565b6000610b626133a584670de0b6b3a7640000612b23565b83516000610b6282846138dd565b8280546133bf906137df565b90600052602060002090601f0160209004810192826133e15760008555613427565b82601f106133fa57805160ff1916838001178555613427565b82800160010185558215613427579182015b8281111561342757825182559160200191906001019061340c565b506117929291505b80821115611792576000815560010161342f565b600060208083528351808285015260005b8181101561347057858101830151858201604001528201613454565b81811115613482576000604083870101525b50601f01601f1916929092016040019392505050565b6001600160a01b03811681146134ad57600080fd5b50565b600080604083850312156134c357600080fd5b82356134ce81613498565b946020939093013593505050565b6000602082840312156134ee57600080fd5b5035919050565b60006020828403121561350757600080fd5b8135610b6281613498565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261353957600080fd5b813567ffffffffffffffff8082111561355457613554613512565b604051601f8301601f19908116603f0116810190828211818310171561357c5761357c613512565b8160405283815286602085880101111561359557600080fd5b836020870160208301376000602085830101528094505050505092915050565b803560ff811681146135c657600080fd5b919050565b600080600080600080600060e0888a0312156135e657600080fd5b87356135f181613498565b9650602088013561360181613498565b9550604088013561361181613498565b945060608801359350608088013567ffffffffffffffff8082111561363557600080fd5b6136418b838c01613528565b945060a08a013591508082111561365757600080fd5b506136648a828b01613528565b92505061367360c089016135b5565b905092959891949750929550565b60008060006060848603121561369657600080fd5b83356136a181613498565b925060208401356136b181613498565b929592945050506040919091013590565b60008060008060008060c087890312156136db57600080fd5b86356136e681613498565b955060208701356136f681613498565b945060408701359350606087013567ffffffffffffffff8082111561371a57600080fd5b6137268a838b01613528565b9450608089013591508082111561373c57600080fd5b5061374989828a01613528565b92505061375860a088016135b5565b90509295509295509295565b6000806040838503121561377757600080fd5b823561378281613498565b9150602083013561379281613498565b809150509250929050565b6000806000606084860312156137b257600080fd5b83356137bd81613498565b92506020840135915060408401356137d481613498565b809150509250925092565b600181811c908216806137f357607f821691505b6020821081141561381457634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252600a90820152691c994b595b9d195c995960b21b604082015260600190565b60006020828403121561385057600080fd5b5051919050565b60006020828403121561386957600080fd5b81518015158114610b6257600080fd5b634e487b7160e01b600052601160045260246000fd5b6000828210156138a1576138a1613879565b500390565b600082198211156138b9576138b9613879565b500190565b60008160001904831182151516156138d8576138d8613879565b500290565b6000826138fa57634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b039390931683526020830191909152604082015260600190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6000806040838503121561395757600080fd5b50508051602090910151909290915056feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa26469706673582212206986794797f3615ae938bfb57cf952b9655c64451480c72bc64a1f974150c38564736f6c634300080a0033
Deployed Bytecode Sourcemap
79645:10300:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11256:18;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;35004:246;;;;;;:::i;:::-;;:::i;:::-;;;1237:14:1;;1230:22;1212:41;;1200:2;1185:18;35004:246:0;1072:187:1;83076:149:0;;;;;;:::i;:::-;;:::i;:::-;;;1595:25:1;;;1583:2;1568:18;83076:149:0;1449:177:1;12479:33:0;;;;;;38723:174;;;;;;:::i;:::-;;:::i;13124:23::-;;;;;;40870:120;;;:::i;80204:684::-;;;;;;:::i;:::-;;:::i;:::-;;84673:371;;;;;;:::i;:::-;;:::i;34333:192::-;;;;;;:::i;:::-;;:::i;83552:189::-;;;;;;:::i;:::-;;:::i;11929:35::-;;;;;-1:-1:-1;;;;;11929:35:0;;;;;;-1:-1:-1;;;;;4986:32:1;;;4968:51;;4956:2;4941:18;11929:35:0;4806:219:1;11452:21:0;;;;;;;;;;;;5202:4:1;5190:17;;;5172:36;;5160:2;5145:18;11452:21:0;5030:184:1;36299:232:0;;;;;;:::i;:::-;;:::i;42190:97::-;;;:::i;85278:128::-;;;;;;:::i;:::-;;:::i;68842:693::-;;;;;;:::i;:::-;;:::i;12888:24::-;;;;;;12055:39;;;;;-1:-1:-1;;;;;12055:39:0;;;73841:280;;;;;;:::i;:::-;;:::i;14019:56::-;;14069:6;14019:56;;9184:33;;9216:1;9184:33;;12602:30;;;;;;18978:25;;;;;-1:-1:-1;;;;;18978:25:0;;;35922:121;;;;;;:::i;:::-;-1:-1:-1;;;;;36015:20:0;35988:7;36015:20;;;:13;:20;;;;;;;35922:121;38290:142;;;:::i;89722:220::-;;;;;;:::i;:::-;;:::i;82259:161::-;;;;;;:::i;:::-;;:::i;13018:25::-;;;;;;11352:20;;;:::i;39106:144::-;;;;;;:::i;:::-;;:::i;30016:1505::-;;;;;;:::i;:::-;;:::i;81278:133::-;;;;;;:::i;:::-;;:::i;42535:2570::-;;;:::i;33844:182::-;;;;;;:::i;:::-;;:::i;12753:23::-;;;;;;37951:193;;;:::i;63835:224::-;;;;;;:::i;:::-;;:::i;67027:604::-;;;;;;:::i;:::-;;:::i;40472:148::-;;;:::i;36877:292::-;;;;;;:::i;:::-;;:::i;:::-;;;;7452:25:1;;;7508:2;7493:18;;7486:34;;;;7536:18;;;7529:34;7594:2;7579:18;;7572:34;7439:3;7424:19;36877:292:0;7221:391:1;82688:141:0;;;;;;:::i;:::-;;:::i;81762:::-;;;;;;:::i;:::-;;:::i;35580:152::-;;;;;;:::i;:::-;-1:-1:-1;;;;;35690:25:0;;;35663:7;35690:25;;;:18;:25;;;;;;;;:34;;;;;;;;;;;;;35580:152;67909:708;;;:::i;76156:321::-;;;;;;:::i;:::-;;:::i;12196:42::-;;;;;-1:-1:-1;;;;;12196:42:0;;;84223:237;;;;;;:::i;:::-;;:::i;11818:28::-;;;;;;;;-1:-1:-1;;;;;11818:28:0;;;37605:170;;;:::i;69838:307::-;;;;;;:::i;:::-;;:::i;14240:36::-;;14272:4;14240:36;;11256:18;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;35004:246::-;35112:10;35081:4;35133:23;;;:18;:23;;;;;;;;-1:-1:-1;;;;;35133:32:0;;;;;;;;;;:41;;;35190:30;35081:4;;35112:10;;;35190:30;;;;35168:6;1595:25:1;;1583:2;1568:18;;1449:177;35190:30:0;;;;;;;;-1:-1:-1;35238:4:0;;35004:246;-1:-1:-1;;;35004:246:0:o;83076:149::-;83142:4;83159:32;83179:11;83159:19;:32::i;:::-;-1:-1:-1;9216:1:0;;83076:149;-1:-1:-1;83076:149:0:o;38723:174::-;38810:4;79299:11;;;;79291:34;;;;-1:-1:-1;;;79291:34:0;;;;;;;:::i;:::-;;;;;;;;;79350:5;79336:19;;-1:-1:-1;;79336:19:0;;;38827:16:::1;:14;:16::i;:::-;;38861:28;38881:7;38861:19;:28::i;:::-;38854:35;;79378:11:::0;:18;;-1:-1:-1;;79378:18:0;79392:4;79378:18;;;38723:174;;-1:-1:-1;38723:174:0:o;40870:120::-;40930:4;40954:28;:26;:28::i;:::-;40947:35;;40870:120;:::o;80204:684::-;80638:107;80655:12;80669:18;80689:28;80719:5;80726:7;80735:9;80638:16;:107::i;:::-;80805:10;:24;;-1:-1:-1;;;;;;80805:24:0;-1:-1:-1;;;;;80805:24:0;;;;;;;;80840:40;;;-1:-1:-1;;;80840:40:0;;;;:38;;:40;;;;;;;;;;;;;;;80805:24;80840:40;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;80204:684;;;;;;;:::o;84673:371::-;84777:5;;;;;-1:-1:-1;;;;;84777:5:0;84763:10;:19;84755:79;;;;-1:-1:-1;;;84755:79:0;;10119:2:1;84755:79:0;;;10101:21:1;10158:2;10138:18;;;10131:30;10197:34;10177:18;;;10170:62;-1:-1:-1;;;10248:18:1;;;10241:45;10303:19;;84755:79:0;9917:411:1;84755:79:0;84871:10;;-1:-1:-1;;;;;84853:28:0;;;84871:10;;84853:28;;84845:91;;;;-1:-1:-1;;;84845:91:0;;10535:2:1;84845:91:0;;;10517:21:1;10574:2;10554:18;;;10547:30;10613:34;10593:18;;;10586:62;-1:-1:-1;;;10664:18:1;;;10657:48;10722:19;;84845:91:0;10333:414:1;84845:91:0;84965:30;;-1:-1:-1;;;84965:30:0;;84989:4;84965:30;;;4968:51:1;84947:15:0;;-1:-1:-1;;;;;84965:15:0;;;;;4941:18:1;;84965:30:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;85021:5;;85006:30;;-1:-1:-1;;;85006:30:0;;-1:-1:-1;;;;;85021:5:0;;;;;;85006:30;;;10934:51:1;11001:18;;;10994:34;;;;;-1:-1:-1;85006:14:0;;;;;10907:18:1;;85006:30:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;84744:300;84673:371;:::o;34333:192::-;34437:4;79299:11;;;;79291:34;;;;-1:-1:-1;;;79291:34:0;;;;;;;:::i;:::-;79350:5;79336:19;;-1:-1:-1;;79336:19:0;;;34461:44:::1;34476:10;34488:3:::0;34493;34498:6;34461:14:::1;:44::i;:::-;:56;34454:63;;79378:11:::0;:18;;-1:-1:-1;;79378:18:0;79392:4;79378:18;;;34333:192;;-1:-1:-1;;;34333:192:0:o;83552:189::-;83642:4;83659:48;83685:8;83695:11;83659:25;:48::i;:::-;-1:-1:-1;9216:1:0;83552:189;;;;:::o;36299:232::-;36370:4;36387:23;36413:38;;;;;;;;36428:21;:19;:21::i;:::-;36413:38;;-1:-1:-1;;;;;36502:20:0;;;;;;:13;:20;;;;;;36387:64;;-1:-1:-1;36469:54:0;;36387:64;;36469:18;:54::i;:::-;36462:61;36299:232;-1:-1:-1;;;36299:232:0:o;42190:97::-;42241:4;42265:14;:12;:14::i;85278:128::-;85343:4;85367:31;85388:9;85367:20;:31::i;:::-;85360:38;85278:128;-1:-1:-1;;85278:128:0:o;68842:693::-;68998:5;;68929:4;;68998:5;;;-1:-1:-1;;;;;68998:5:0;68984:10;:19;68980:85;;69027:26;;-1:-1:-1;;;69027:26:0;;;;;;;;;;;68980:85;69115:11;;69212:30;;;-1:-1:-1;;;69212:30:0;;;;-1:-1:-1;;;;;69115:11:0;;;;69212:28;;;;;:30;;;;;;;;;;;;;;:28;:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;69204:71;;;;-1:-1:-1;;;69204:71:0;;11523:2:1;69204:71:0;;;11505:21:1;11562:2;11542:18;;;11535:30;11601;11581:18;;;11574:58;11649:18;;69204:71:0;11321:352:1;69204:71:0;69343:11;:28;;-1:-1:-1;;;;;;69343:28:0;-1:-1:-1;;;;;69343:28:0;;;;;;;;;69453:46;;;11964:15:1;;;11946:34;;12011:2;11996:18;;11989:43;;;;69453:46:0;;11881:18:1;69453:46:0;;;;;;;;-1:-1:-1;9216:1:0;;68842:693;-1:-1:-1;;68842:693:0:o;73841:280::-;73925:4;79299:11;;;;79291:34;;;;-1:-1:-1;;;79291:34:0;;;;;;;:::i;:::-;79350:5;79336:19;;-1:-1:-1;;79336:19:0;;;73942:16:::1;:14;:16::i;:::-;;74079:34;74100:12;74079:20;:34::i;38290:142::-:0;38361:4;79299:11;;;;79291:34;;;;-1:-1:-1;;;79291:34:0;;;;;;;:::i;:::-;79350:5;79336:19;;-1:-1:-1;;79336:19:0;;;38378:16:::1;:14;:16::i;:::-;-1:-1:-1::0;;38412:12:0::1;::::0;79378:11;:18;;-1:-1:-1;;79378:18:0;79392:4;79378:18;;;38290:142;:::o;89722:220::-;89820:5;;;;;-1:-1:-1;;;;;89820:5:0;89806:10;:19;89798:77;;;;-1:-1:-1;;;89798:77:0;;12245:2:1;89798:77:0;;;12227:21:1;12284:2;12264:18;;;12257:30;12323:34;12303:18;;;12296:62;-1:-1:-1;;;12374:18:1;;;12367:43;12427:19;;89798:77:0;12043:409:1;89798:77:0;89895:10;;89886:48;;-1:-1:-1;;;89886:48:0;;-1:-1:-1;;;;;4986:32:1;;;89886:48:0;;;4968:51:1;89895:10:0;;;;89886:29;;4941:18:1;;89886:48:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;89722:220;:::o;82259:161::-;82331:4;82348:38;82373:12;82348:24;:38::i;11352:20::-;;;;;;;:::i;39106:144::-;39182:4;39206:36;39234:7;39206:27;:36::i;30016:1505::-;30370:5;;;;;-1:-1:-1;;;;;30370:5:0;30356:10;:19;30348:68;;;;-1:-1:-1;;;30348:68:0;;12659:2:1;30348:68:0;;;12641:21:1;12698:2;12678:18;;;12671:30;12737:34;12717:18;;;12710:62;-1:-1:-1;;;12788:18:1;;;12781:34;12832:19;;30348:68:0;12457:400:1;30348:68:0;30435:18;;:23;:43;;;;-1:-1:-1;30462:11:0;;:16;30435:43;30427:91;;;;-1:-1:-1;;;30427:91:0;;13064:2:1;30427:91:0;;;13046:21:1;13103:2;13083:18;;;13076:30;13142:34;13122:18;;;13115:62;-1:-1:-1;;;13193:18:1;;;13186:33;13236:19;;30427:91:0;12862:399:1;30427:91:0;30569:27;:58;;;30646:31;30638:92;;;;-1:-1:-1;;;30638:92:0;;13468:2:1;30638:92:0;;;13450:21:1;13507:2;13487:18;;;13480:30;13546:34;13526:18;;;13519:62;-1:-1:-1;;;13597:18:1;;;13590:46;13653:19;;30638:92:0;13266:412:1;30638:92:0;30775:8;30786:29;30802:12;30786:15;:29::i;:::-;30775:40;-1:-1:-1;30834:15:0;;30826:54;;;;-1:-1:-1;;;30826:54:0;;13885:2:1;30826:54:0;;;13867:21:1;13924:2;13904:18;;;13897:30;13963:28;13943:18;;;13936:56;14009:18;;30826:54:0;13683:350:1;30826:54:0;37409:12;30999:18;:37;24015:4;31047:11;:25;31172:46;31199:18;31172:26;:46::i;:::-;31166:52;-1:-1:-1;31237:15:0;;31229:62;;;;-1:-1:-1;;;31229:62:0;;14240:2:1;31229:62:0;;;14222:21:1;14279:2;14259:18;;;14252:30;14318:34;14298:18;;;14291:62;-1:-1:-1;;;14369:18:1;;;14362:32;14411:19;;31229:62:0;14038:398:1;31229:62:0;31304:12;;;;:4;;:12;;;;;:::i;:::-;-1:-1:-1;31327:16:0;;;;:6;;:16;;;;;:::i;:::-;-1:-1:-1;;31354:8:0;:20;;;;;;-1:-1:-1;;31354:20:0;;;;;;:8;31495:18;;;;;31354:20;31495:18;;;-1:-1:-1;;;;;30016:1505:0:o;81278:133::-;81336:4;81353:24;81366:10;81353:12;:24::i;42535:2570::-;42744:18;;42594:4;;37409:12;;42832:45;;;42828:93;;;9216:1;42894:15;;;;42535:2570;:::o;42828:93::-;42988:14;43005;:12;:14::i;:::-;43050:12;;43094:13;;43142:11;;43250:17;;:71;;-1:-1:-1;;;43250:71:0;;;;;14643:25:1;;;14684:18;;;14677:34;;;14727:18;;;14720:34;;;42988:31:0;;-1:-1:-1;43050:12:0;;43094:13;;43142:11;;43030:17;;-1:-1:-1;;;;;43250:17:0;;:31;;14616:18:1;;43250:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;43224:97;;11599:9;43340:18;:43;;43332:84;;;;-1:-1:-1;;;43332:84:0;;14967:2:1;43332:84:0;;;14949:21:1;15006:2;14986:18;;;14979:30;15045;15025:18;;;15018:58;15093:18;;43332:84:0;14765:352:1;43332:84:0;43506:15;43524:44;43545:23;43524:18;:44;:::i;:::-;43506:62;;44060:31;44094:53;44099:35;;;;;;;;44114:18;44099:35;;;44136:10;44094:4;:53::i;:::-;44060:87;;44158:24;44185:54;44204:20;44226:12;44185:18;:54::i;:::-;44158:81;-1:-1:-1;44250:20:0;44273:34;44295:12;44158:81;44273:34;:::i;:::-;44250:57;;44318:21;44342:101;44368:38;;;;;;;;44383:21;;44368:38;;;44408:19;44429:13;44342:25;:101::i;:::-;44318:125;;44454:19;44476:83;44502:20;44524:16;44542;44476:25;:83::i;:::-;44763:18;:39;;;44813:11;:28;;;44852:12;:30;;;44893:13;:32;;;44990:79;;;7452:25:1;;;7508:2;7493:18;;7486:34;;;7536:18;;;7529:34;;;7594:2;7579:18;;7572:34;;;44813:28:0;;-1:-1:-1;44990:79:0;;7439:3:1;7424:19;44990:79:0;;;;;;;9216:1;45082:15;;;;;;;;;;;;;;;42535:2570;:::o;33844:182::-;33931:4;79299:11;;;;79291:34;;;;-1:-1:-1;;;79291:34:0;;;;;;;:::i;:::-;79350:5;79336:19;;-1:-1:-1;;79336:19:0;;;33955:51:::1;33970:10;::::0;33994:3;33999:6;33955:14:::1;:51::i;:::-;:63;33948:70;;79378:11:::0;:18;;-1:-1:-1;;79378:18:0;79392:4;79378:18;;;33844:182;;-1:-1:-1;;33844:182:0:o;37951:193::-;38037:17;;38013:4;;-1:-1:-1;;;;;38037:17:0;:31;38069:14;:12;:14::i;:::-;38085:12;;38099:13;;38114:21;;38037:99;;-1:-1:-1;;;;;;38037:99:0;;;;;;;;;;7452:25:1;;;;7493:18;;;7486:34;;;;7536:18;;;7529:34;7579:18;;;7572:34;7424:19;;38037:99:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;63835:224::-;63946:4;79299:11;;;;79291:34;;;;-1:-1:-1;;;79291:34:0;;;;;;;:::i;:::-;79350:5;79336:19;;-1:-1:-1;;79336:19:0;;;63963:60:::1;63977:10;63989::::0;64001:8;64011:11;63963:13:::1;:60::i;:::-;-1:-1:-1::0;9216:1:0::1;79378:11:::0;:18;;-1:-1:-1;;79378:18:0;79392:4;79378:18;;;63835:224;;-1:-1:-1;;;63835:224:0:o;67027:604::-;67181:5;;67113:4;;67181:5;;;-1:-1:-1;;;;;67181:5:0;67167:10;:19;67163:86;;67210:27;;-1:-1:-1;;;67210:27:0;;;;;;;;;;;67163:86;67348:12;;;-1:-1:-1;;;;;67431:30:0;;;-1:-1:-1;;;;;;67431:30:0;;;;;;;67546:49;;;67348:12;;;;11946:34:1;;;12011:2;11996:18;;11989:43;;;;67546:49:0;;11881:18:1;67546:49:0;11678:360:1;40472:148:0;40541:4;79299:11;;;;79291:34;;;;-1:-1:-1;;;79291:34:0;;;;;;;:::i;:::-;79350:5;79336:19;;-1:-1:-1;;79336:19:0;;;40558:16:::1;:14;:16::i;:::-;;40592:20;:18;:20::i;:::-;40585:27;;79378:11:::0;:18;;-1:-1:-1;;79378:18:0;79392:4;79378:18;;;40472:148;:::o;36877:292::-;-1:-1:-1;;;;;37034:22:0;;36954:4;37034:22;;;:13;:22;;;;;;36954:4;;;;;;;;37071:36;37048:7;37071:27;:36::i;:::-;37122:28;:26;:28::i;:::-;36989:172;;;;;;;;36877:292;;;;;:::o;82688:141::-;82750:4;82767:28;82782:12;82767:14;:28::i;81762:141::-;81824:4;81841:28;81856:12;81841:14;:28::i;67909:708::-;68068:12;;67960:4;;-1:-1:-1;;;;;68068:12:0;68054:10;:26;;;:54;;-1:-1:-1;68084:10:0;:24;68054:54;68050:124;;;68132:30;;-1:-1:-1;;;68132:30:0;;;;;;;;;;;68050:124;68258:5;;;68300:12;;;-1:-1:-1;;;;;68300:12:0;;;68258:5;68373:20;;;-1:-1:-1;;;;;;68373:20:0;;;;;;;-1:-1:-1;;;;;;68442:34:0;;;;;;68494:25;;;68258:5;;;;;;11946:34:1;;;68513:5:0;;;;;12011:2:1;11996:18;;11989:43;68258:5:0;68300:12;;68494:25;;11881:18:1;68494:25:0;;;;;;;68568:12;;68535:46;;;-1:-1:-1;;;;;11964:15:1;;;11946:34;;68568:12:0;;;12011:2:1;11996:18;;11989:43;68535:46:0;;11881:18:1;68535:46:0;;;;;;;9216:1;68594:15;;;;67909:708;:::o;76156:321::-;76252:4;76269:16;:14;:16::i;:::-;;76421:48;76448:20;76421:26;:48::i;84223:237::-;84345:4;84362:64;84386:8;84396:11;84409:16;84362:23;:64::i;:::-;-1:-1:-1;9216:1:0;84223:237;;;;;:::o;37605:170::-;37691:17;;37667:4;;-1:-1:-1;;;;;37691:17:0;:31;37723:14;:12;:14::i;:::-;37739:12;;37753:13;;37691:76;;-1:-1:-1;;;;;;37691:76:0;;;;;;;;;;14643:25:1;;;;14684:18;;;14677:34;;;;14727:18;;;14720:34;14616:18;;37691:76:0;14441:319:1;69838:307:0;69936:4;79299:11;;;;79291:34;;;;-1:-1:-1;;;79291:34:0;;;;;;;:::i;:::-;79350:5;79336:19;;-1:-1:-1;;79336:19:0;;;69953:16:::1;:14;:16::i;:::-;;70089:48;70112:24;70089:22;:48::i;55673:261::-:0;79299:11;;;;79291:34;;;;-1:-1:-1;;;79291:34:0;;;;;;;:::i;:::-;79350:5;79336:19;;-1:-1:-1;;79336:19:0;;;55753:16:::1;:14;:16::i;:::-;;55873:53;55890:10;55902;55914:11;55873:16;:53::i;:::-;-1:-1:-1::0;;79378:11:0;:18;;-1:-1:-1;;79378:18:0;79392:4;79378:18;;;55673:261::o;41240:780::-;41346:11;;41309:4;;41372:17;41368:645;;-1:-1:-1;;41545:27:0;;;41240:780::o;41368:645::-;41754:14;41771;:12;:14::i;:::-;41754:31;;41800:33;41863:13;;41848:12;;41836:9;:24;;;;:::i;:::-;:40;;;;:::i;:::-;41800:76;-1:-1:-1;41891:17:0;41953:12;41911:39;24015:4;41800:76;41911:39;:::i;:::-;:54;;;;:::i;:::-;41891:74;41240:780;-1:-1:-1;;;;;41240:780:0:o;41368:645::-;41315:705;41240:780;:::o;31987:1596::-;32161:11;;:60;;-1:-1:-1;;;32161:60:0;;32197:4;32161:60;;;16498:34:1;-1:-1:-1;;;;;16568:15:1;;;16548:18;;;16541:43;16620:15;;;16600:18;;;16593:43;16652:18;;;16645:34;;;32085:4:0;;;;32161:11;;;:27;;16432:19:1;;32161:60:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;32146:75;-1:-1:-1;32236:12:0;;32232:89;;32272:37;;-1:-1:-1;;;32272:37:0;;;;;1595:25:1;;;1568:18;;32272:37:0;1449:177:1;32232:89:0;32387:3;-1:-1:-1;;;;;32380:10:0;:3;-1:-1:-1;;;;;32380:10:0;;32376:70;;;32414:20;;-1:-1:-1;;;32414:20:0;;;;;;;;;;;32376:70;32523:22;32575:3;-1:-1:-1;;;;;32564:14:0;:7;-1:-1:-1;;;;;32564:14:0;;32560:166;;;-1:-1:-1;;;32560:166:0;;;-1:-1:-1;;;;;;32682:23:0;;;;;;;:18;:23;;;;;;;;:32;;;;;;;;;;32560:166;32804:17;32824:26;32844:6;32824:17;:26;:::i;:::-;-1:-1:-1;;;;;32881:18:0;;32861:17;32881:18;;;:13;:18;;;;;;32804:46;;-1:-1:-1;32861:17:0;32881:27;;32902:6;;32881:27;:::i;:::-;-1:-1:-1;;;;;32939:18:0;;32919:17;32939:18;;;:13;:18;;;;;;32861:47;;-1:-1:-1;32919:17:0;32939:27;;32960:6;;32939:27;:::i;:::-;-1:-1:-1;;;;;33100:18:0;;;;;;;:13;:18;;;;;;:33;;;33144:18;;;;;;:33;;;32919:47;-1:-1:-1;;;33250:35:0;;33246:115;;-1:-1:-1;;;;;33302:23:0;;;;;;;:18;:23;;;;;;;;:32;;;;;;;;;:47;;;33246:115;33432:3;-1:-1:-1;;;;;33418:26:0;33427:3;-1:-1:-1;;;;;33418:26:0;-1:-1:-1;;;;;;;;;;;33437:6:0;33418:26;;;;1595:25:1;;1583:2;1568:18;;1449:177;33418:26:0;;;;;;;;-1:-1:-1;9216:1:0;;31987:1596;-1:-1:-1;;;;;;;;;31987:1596:0:o;56173:283::-;79299:11;;;;79291:34;;;;-1:-1:-1;;;79291:34:0;;;;;;;:::i;:::-;79350:5;79336:19;;-1:-1:-1;;79336:19:0;;;56277:16:::1;:14;:16::i;:::-;;56397:51;56414:10;56426:8;56436:11;56397:16;:51::i;:::-;-1:-1:-1::0;;79378:11:0;:18;;-1:-1:-1;;79378:18:0;79392:4;79378:18;;;-1:-1:-1;56173:283:0:o;24737:174::-;24815:4;24832:18;24853:15;24858:1;24861:6;24853:4;:15::i;:::-;24832:36;;24886:17;24895:7;24886:8;:17::i;:::-;24879:24;24737:174;-1:-1:-1;;;;24737:174:0:o;85674:186::-;85793:10;;85822:30;;-1:-1:-1;;;85822:30:0;;85846:4;85822:30;;;4968:51:1;85738:4:0;;-1:-1:-1;;;;;85793:10:0;;;;85822:15;;4941:18:1;;85822:30:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;85815:37;;;85674:186;:::o;71509:284::-;71586:4;79299:11;;;;79291:34;;;;-1:-1:-1;;;79291:34:0;;;;;;;:::i;:::-;79350:5;79336:19;;-1:-1:-1;;79336:19:0;;;71603:16:::1;:14;:16::i;:::-;;71731:28;71749:9;71731:17;:28::i;:::-;;;9216:1;71770:15;;79378:11:::0;:18;;-1:-1:-1;;79378:18:0;79392:4;79378:18;;;71509:284;;-1:-1:-1;71509:284:0:o;74398:1389::-;74609:5;;74465:4;;;;74609:5;;;-1:-1:-1;;;;;74609:5:0;74595:10;:19;74591:85;;74638:26;;-1:-1:-1;;;74638:26:0;;;;;;;;;;;74591:85;37409:12;74780:18;;:38;74776:104;;74842:26;;-1:-1:-1;;;74842:26:0;;;;;;;;;;;74776:104;74986:12;74969:14;:12;:14::i;:::-;:29;74965:101;;;75022:32;;-1:-1:-1;;;75022:32:0;;;;;;;;;;;74965:101;75160:13;;75145:12;:28;75141:98;;;75197:30;;-1:-1:-1;;;75197:30:0;;;;;;;;;;;75141:98;75407:12;75391:13;;:28;;;;:::i;:::-;75493:13;:32;;;75659:5;;75493:32;;-1:-1:-1;75645:34:0;;75659:5;;;-1:-1:-1;;;;;75659:5:0;75666:12;75645:13;:34::i;:::-;75697:54;75713:5;;;;;;;;;-1:-1:-1;;;;;75713:5:0;75720:12;75734:16;75697:54;;;;;;;;:::i;48972:252::-;79299:11;;;;79291:34;;;;-1:-1:-1;;;79291:34:0;;;;;;;:::i;:::-;79350:5;79336:19;;-1:-1:-1;;79336:19:0;;;49058:16:::1;:14;:16::i;:::-;;49167:49;49187:10;49200:1;49203:12;49167:11;:49::i;:::-;-1:-1:-1::0;79378:11:0;:18;;-1:-1:-1;;79378:18:0;79392:4;79378:18;;;48972:252::o;39504:813::-;-1:-1:-1;;;;;39687:23:0;;39581:4;39687:23;;;:14;:23;;;;;39916:24;;39912:70;;-1:-1:-1;39969:1:0;;39504:813;-1:-1:-1;;39504:813:0:o;39912:70::-;40230:11;;40203:24;;40176;;40203:38;;;:::i;:::-;40176:65;;40281:14;:28;;;40259:19;:50;;;;:::i;76807:1201::-;77107:5;;76901:4;;;;77107:5;;;-1:-1:-1;;;;;77107:5:0;77093:10;:19;77089:91;;77136:32;;-1:-1:-1;;;77136:32:0;;;;;;;;;;;77089:91;37409:12;77284:18;;:38;77280:110;;77346:32;;-1:-1:-1;;;77346:32:0;;;;;;;;;;;77280:110;77484:17;;;;;;;;;-1:-1:-1;;;;;77484:17:0;77461:40;;77604:20;-1:-1:-1;;;;;77604:40:0;;:42;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;77596:83;;;;-1:-1:-1;;;77596:83:0;;11523:2:1;77596:83:0;;;11505:21:1;11562:2;11542:18;;;11535:30;11601;11581:18;;;11574:58;11649:18;;77596:83:0;11321:352:1;77596:83:0;77756:17;:40;;-1:-1:-1;;;;;;77756:40:0;-1:-1:-1;;;;;77756:40:0;;;;;;;;;77902:70;;;11964:15:1;;;11946:34;;12011:2;11996:18;;11989:43;;;;77902:70:0;;11881:18:1;77902:70:0;11678:360:1;45375:244:0;79299:11;;;;79291:34;;;;-1:-1:-1;;;79291:34:0;;;;;;;:::i;:::-;79350:5;79336:19;;-1:-1:-1;;79336:19:0;;;45447:16:::1;:14;:16::i;:::-;;45578:33;45588:10;45600;45578:9;:33::i;27472:133::-:0;-1:-1:-1;;;;;;;;;;;;27561:36:0;;;;;;;;27576:19;27581:1;:10;;;27593:1;27576:4;:19::i;:::-;27561:36;;27554:43;27472:133;-1:-1:-1;;;27472:133:0:o;25056:208::-;25154:4;25171:18;25192:15;25197:1;25200:6;25192:4;:15::i;:::-;25171:36;;25225:31;25230:17;25239:7;25230:8;:17::i;:::-;25249:6;25225:4;:31::i;64646:1932::-;64822:11;;:87;;-1:-1:-1;;;64822:87:0;;64855:4;64822:87;;;17704:34:1;-1:-1:-1;;;;;17774:15:1;;;17754:18;;;17747:43;17826:15;;;17806:18;;;17799:43;17878:15;;;17858:18;;;17851:43;17910:19;;;17903:35;;;64807:12:0;;64822:11;;:24;;17638:19:1;;64822:87:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;64807:102;-1:-1:-1;64924:12:0;;64920:95;;64960:43;;-1:-1:-1;;;64960:43:0;;;;;1595:25:1;;;1568:18;;64960:43:0;1449:177:1;64920:95:0;65088:10;-1:-1:-1;;;;;65076:22:0;:8;-1:-1:-1;;;;;65076:22:0;;65072:98;;;65122:36;;-1:-1:-1;;;65122:36:0;;;;;;;;;;;65072:98;65457:24;65484:62;65489:11;65502:43;;;;;;;;14069:6;65502:43;;;65484:4;:62::i;:::-;65457:89;-1:-1:-1;65557:26:0;65586:33;65457:89;65586:11;:33;:::i;:::-;65557:62;;65630:23;65656:45;;;;;;;;65671:28;:26;:28::i;:::-;65656:45;;65630:71;-1:-1:-1;65712:24:0;65739:53;65630:71;65772:19;65739:18;:53::i;:::-;65712:80;;65803:21;65843:19;65827:13;;:35;;;;:::i;:::-;66057:13;:32;;;66114:11;;65803:59;;-1:-1:-1;66114:33:0;;66128:19;;66114:33;:::i;:::-;66100:11;:47;-1:-1:-1;;;;;66184:23:0;;;;;;:13;:23;;;;;;:37;;66210:11;;66184:37;:::i;:::-;-1:-1:-1;;;;;66158:23:0;;;;;;;:13;:23;;;;;;:63;;;;66260:25;;;;;;;:49;;66288:21;;66260:49;:::i;:::-;-1:-1:-1;;;;;66232:25:0;;;;;;;:13;:25;;;;;;;:77;;;;66364:53;;;;;;-1:-1:-1;;;;;;;;;;;66364:53:0;;;66395:21;1595:25:1;;1583:2;1568:18;;1449:177;66364:53:0;;;;;;;;66433:54;;1595:25:1;;;66460:4:0;;-1:-1:-1;;;;;66433:54:0;;;-1:-1:-1;;;;;;;;;;;66433:54:0;1583:2:1;1568:18;66433:54:0;;;;;;;66503:67;66525:4;66532:19;66553:16;66503:67;;;;;;;;:::i;:::-;;;;;;;;64755:1823;;;;;;64646:1932;;;;:::o;52960:239::-;79299:11;;;;79291:34;;;;-1:-1:-1;;;79291:34:0;;;;;;;:::i;:::-;79350:5;79336:19;;-1:-1:-1;;79336:19:0;;;53036:16:::1;:14;:16::i;:::-;;53145:46;53165:10;53178:12;53145:11;:46::i;48438:242::-:0;79299:11;;;;79291:34;;;;-1:-1:-1;;;79291:34:0;;;;;;;:::i;:::-;79350:5;79336:19;;-1:-1:-1;;79336:19:0;;;48514:16:::1;:14;:16::i;:::-;;48623:49;48643:10;48656:12;48670:1;48623:11;:49::i;59557:633::-:0;79299:11;;;;79291:34;;;;-1:-1:-1;;;79291:34:0;;;;;;;:::i;:::-;79350:5;79336:19;;-1:-1:-1;;79336:19:0;;;59693:16:::1;:14;:16::i;:::-;;59722:10;59735:16;-1:-1:-1::0;;;;;59735:31:0::1;;:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;59722:46:::0;-1:-1:-1;59783:17:0;;59779:227:::1;;59948:46;::::0;-1:-1:-1;;;59948:46:0;;::::1;::::0;::::1;1595:25:1::0;;;1568:18;;59948:46:0::1;1449:177:1::0;59779:227:0::1;60109:73;60130:10;60142:8;60152:11;60165:16;60109:20;:73::i;:::-;-1:-1:-1::0;;79378:11:0;:18;;-1:-1:-1;;79378:18:0;79392:4;79378:18;;;-1:-1:-1;;59557:633:0:o;70413:840::-;70563:5;;70494:4;;70563:5;;;-1:-1:-1;;;;;70563:5:0;70549:10;:19;70545:87;;70592:28;;-1:-1:-1;;;70592:28:0;;;;;;;;;;;70545:87;37409:12;70717:18;;:38;70713:106;;70779:28;;-1:-1:-1;;;70779:28:0;;;;;;;;;;;70713:106;11739:4;70891:24;:51;70887:120;;;70966:29;;-1:-1:-1;;;70966:29:0;;;;;;;;;;;70887:120;71051:21;;;71083:48;;;;71149:68;;;18473:25:1;;;18529:2;18514:18;;18507:34;;;71149:68:0;;18446:18:1;71149:68:0;18299:248:1;56844:2319:0;57018:11;;:75;;-1:-1:-1;;;57018:75:0;;57057:4;57018:75;;;16498:34:1;-1:-1:-1;;;;;16568:15:1;;;16548:18;;;16541:43;16620:15;;;16600:18;;;16593:43;16652:18;;;16645:34;;;56939:4:0;;;;57018:11;;;:30;;16432:19:1;;57018:75:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;57003:90;-1:-1:-1;57108:12:0;;57104:92;;57144:40;;-1:-1:-1;;;57144:40:0;;;;;1595:25:1;;;1568:18;;57144:40:0;1449:177:1;57104:92:0;37409:12;57284:18;;:38;57280:105;;57346:27;;-1:-1:-1;;;57346:27:0;;;;;;;;;;;57280:105;57477:23;57503:37;57531:8;57503:27;:37::i;:::-;57477:63;;57619:21;-1:-1:-1;;57643:11:0;:29;:64;;57696:11;57643:64;;;57675:18;57643:64;57619:88;;58281:22;58306:37;58319:5;58326:16;58306:12;:37::i;:::-;58281:62;-1:-1:-1;58604:22:0;58629:38;58281:62;58629:18;:38;:::i;:::-;58604:63;;58678:20;58716:17;58701:12;;:32;;;;:::i;:::-;-1:-1:-1;;;;;58816:24:0;;;;;;;:14;:24;;;;;;;;;:54;;;58922:11;;58881:38;;;;:52;58944:12;:30;;;59035:83;;18867:15:1;;;18849:34;;18899:18;;18892:43;;;;18951:18;;18944:34;;;19009:2;18994:18;;18987:34;;;19052:3;19037:19;;19030:35;;;58944:30:0;;-1:-1:-1;59035:83:0;;18798:3:1;18783:19;59035:83:0;;;;;;;-1:-1:-1;59138:17:0;;56844:2319;-1:-1:-1;;;;;;;;56844:2319:0:o;24411:213::-;24593:12;;24468:4;;24593:23;;24015:4;;24593:23;:::i;72133:1453::-;72194:4;;;;37409:12;72418:18;;:38;72414:122;;72480:44;;-1:-1:-1;;;72480:44:0;;;;;1595:25:1;;;1568:18;;72480:44:0;1449:177:1;72414:122:0;73125:35;73138:10;73150:9;73125:12;:35::i;:::-;73107:53;;73208:15;73192:13;;:31;;;;:::i;:::-;73173:50;;73316:16;73300:13;:32;;;;73421:60;73435:10;73447:15;73464:16;73421:60;;;;;;;;:::i;:::-;;;;;;;;9216:1;;73562:15;;-1:-1:-1;72133:1453:0;-1:-1:-1;;;72133:1453:0:o;88553:930::-;88706:10;;88728:26;;-1:-1:-1;;;88728:26:0;;-1:-1:-1;;;;;10952:32:1;;;88728:26:0;;;10934:51:1;11001:18;;;10994:34;;;88706:10:0;;;;;;88728:14;;10907:18:1;;88728:26:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;88767:12;88821:16;88860:1;88855:152;;;;89030:2;89025:228;;;;89388:1;89385;89378:12;88855:152;-1:-1:-1;;88950:6:0;-1:-1:-1;88855:152:0;;89025:228;89127:2;89124:1;89121;89106:24;89169:1;89163:8;89152:19;;88814:595;;89438:7;89430:45;;;;-1:-1:-1;;;89430:45:0;;19278:2:1;89430:45:0;;;19260:21:1;19317:2;19297:18;;;19290:30;19356:27;19336:18;;;19329:55;19401:18;;89430:45:0;19076:349:1;89430:45:0;88635:848;;88553:930;;:::o;49784:2997::-;49901:19;;;:42;;-1:-1:-1;49924:19:0;;49901:42;49893:107;;;;-1:-1:-1;;;49893:107:0;;19632:2:1;49893:107:0;;;19614:21:1;19671:2;19651:18;;;19644:30;19710:34;19690:18;;;19683:62;-1:-1:-1;;;19761:18:1;;;19754:50;19821:19;;49893:107:0;19430:416:1;49893:107:0;50073:23;50099:46;;;;;;;;50114:28;:26;:28::i;:::-;50099:46;;50073:72;-1:-1:-1;50158:17:0;;50256:18;;50252:757;;50547:14;50532:29;;50591:48;50610:12;50624:14;50591:18;:48::i;:::-;50576:63;;50252:757;;;50919:34;50924:14;50940:12;50919:4;:34::i;:::-;50904:49;;50983:14;50968:29;;50252:757;51078:11;;:64;;-1:-1:-1;;;51078:64:0;;51063:12;;-1:-1:-1;;;;;51078:11:0;;:25;;:64;;51112:4;;51119:8;;51129:12;;51078:64;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;51063:79;-1:-1:-1;51157:12:0;;51153:87;;51193:35;;-1:-1:-1;;;51193:35:0;;;;;1595:25:1;;;1568:18;;51193:35:0;1449:177:1;51153:87:0;37409:12;51328:18;;:38;51324:100;;51390:22;;-1:-1:-1;;;51390:22:0;;;;;;;;;;;51324:100;51522:12;51505:14;:12;:14::i;:::-;:29;51501:99;;;51558:30;;-1:-1:-1;;;51558:30:0;;;;;;;;;;;51501:99;51958:12;51944:11;;:26;;;;:::i;:::-;51930:11;:40;-1:-1:-1;;;;;52007:23:0;;;;;;:13;:23;;;;;;:38;;52033:12;;52007:38;:::i;:::-;-1:-1:-1;;;;;51981:23:0;;;;;;:13;:23;;;;;:64;52421:37;51995:8;52445:12;52421:13;:37::i;:::-;52536:47;;1595:25:1;;;52563:4:0;;-1:-1:-1;;;;;52536:47:0;;;-1:-1:-1;;;;;;;;;;;52536:47:0;1583:2:1;1568:18;52536:47:0;;;;;;;52599:44;52606:8;52616:12;52630;52599:44;;;;;;;;:::i;:::-;;;;;;;;52696:11;;:77;;-1:-1:-1;;;52696:77:0;;52729:4;52696:77;;;20516:34:1;-1:-1:-1;;;;;20586:15:1;;;20566:18;;;20559:43;20618:18;;;20611:34;;;20661:18;;;20654:34;;;52696:11:0;;;;:24;;20450:19:1;;52696:77:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;49882:2899;;;;49784:2997;;;:::o;45960:2215::-;46087:11;;:58;;-1:-1:-1;;;46087:58:0;;46072:12;;-1:-1:-1;;;;;46087:11:0;;:23;;:58;;46119:4;;46126:6;;46134:10;;46087:58;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;46072:73;-1:-1:-1;46160:12:0;;46156:85;;46196:33;;-1:-1:-1;;;46196:33:0;;;;;1595:25:1;;;1568:18;;46196:33:0;1449:177:1;46156:85:0;37409:12;46329:18;;:38;46325:98;;46391:20;;-1:-1:-1;;;46391:20:0;;;;;;;;;;;46325:98;46435:23;46461:45;;;;;;;;46476:28;:26;:28::i;:::-;46461:45;;46435:71;-1:-1:-1;47115:21:0;47139:32;47152:6;47160:10;47139:12;:32::i;:::-;47115:56;;47364:15;47382:36;47387:16;47405:12;47382:4;:36::i;:::-;47364:54;;47752:10;47738:11;;:24;;;;:::i;:::-;47724:11;:38;-1:-1:-1;;;;;47797:21:0;;;;;;:13;:21;;;;;;:34;;47821:10;;47797:34;:::i;:::-;-1:-1:-1;;;;;47773:21:0;;;;;;:13;:21;;;;;;;:58;;;;47907:42;;;;;47787:6;;47920:16;;47938:10;;47907:42;:::i;:::-;;;;;;;;47965:43;;1595:25:1;;;-1:-1:-1;;;;;47965:43:0;;;47982:4;;-1:-1:-1;;;;;;;;;;;47965:43:0;1583:2:1;1568:18;47965:43:0;;;;;;;46021:2154;;;;45960:2215;;:::o;28209:90::-;28262:4;28286:5;28290:1;28286;:5;:::i;26785:90::-;26838:4;26862:5;26866:1;26862;:5;:::i;27613:121::-;27672:4;24015;27696:19;27701:1;27704;:10;;;27696:4;:19::i;:::-;:30;;;;:::i;53376:2138::-;53519:11;;:64;;-1:-1:-1;;;53519:64:0;;53504:12;;-1:-1:-1;;;;;53519:11:0;;:25;;:64;;53553:4;;53560:8;;53570:12;;53519:64;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;53504:79;-1:-1:-1;53598:12:0;;53594:87;;53634:35;;-1:-1:-1;;;53634:35:0;;;;;1595:25:1;;;1568:18;;53634:35:0;1449:177:1;53594:87:0;37409:12;53769:18;;:38;53765:100;;53831:22;;-1:-1:-1;;;53831:22:0;;;;;;;;;;;53765:100;53974:12;53957:14;:12;:14::i;:::-;:29;53953:93;;;54010:24;;-1:-1:-1;;;54010:24:0;;;;;;;;;;;53953:93;54293:23;54319:37;54347:8;54319:27;:37::i;:::-;54293:63;-1:-1:-1;54367:22:0;54392:33;54413:12;54293:63;54392:33;:::i;:::-;54367:58;;54436:20;54474:12;54459;;:27;;;;:::i;:::-;-1:-1:-1;;;;;54817:24:0;;;;;;:14;:24;;;;;:54;;;54923:11;;54882:38;;;;:52;54945:12;:30;;;54436:50;-1:-1:-1;55347:37:0;54832:8;55371:12;55347:13;:37::i;:::-;55440:66;;;-1:-1:-1;;;;;21336:32:1;;21318:51;;21400:2;21385:18;;21378:34;;;21428:18;;;21421:34;;;21486:2;21471:18;;21464:34;;;55440:66:0;;21305:3:1;21290:19;55440:66:0;;;;;;;53451:2063;;;;53376:2138;;:::o;60669:2605::-;60869:11;;:111;;-1:-1:-1;;;60869:111:0;;60912:4;60869:111;;;17704:34:1;-1:-1:-1;;;;;17774:15:1;;;17754:18;;;17747:43;17826:15;;;17806:18;;;17799:43;17878:15;;;17858:18;;;17851:43;17910:19;;;17903:35;;;60854:12:0;;60869:11;;:34;;17638:19:1;;60869:111:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;60854:126;-1:-1:-1;60995:12:0;;60991:90;;61031:38;;-1:-1:-1;;;61031:38:0;;;;;1595:25:1;;;1568:18;;61031:38:0;1449:177:1;60991:90:0;37409:12;61169:18;;:38;61165:103;;61231:25;;-1:-1:-1;;;61231:25:0;;;;;;;;;;;61165:103;37409:12;61373:16;-1:-1:-1;;;;;61373:35:0;;:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:57;61369:132;;61454:35;;-1:-1:-1;;;61454:35:0;;;;;;;;;;;61369:132;61574:10;-1:-1:-1;;;;;61562:22:0;:8;-1:-1:-1;;;;;61562:22:0;;61558:93;;;61608:31;;-1:-1:-1;;;61608:31:0;;;;;;;;;;;61558:93;61706:16;61702:84;;61746:28;;-1:-1:-1;;;61746:28:0;;;;;;;;;;;61702:84;-1:-1:-1;;61842:11:0;:29;61838:100;;;61895:31;;-1:-1:-1;;;61895:31:0;;;;;;;;;;;61838:100;61991:22;62016:51;62033:10;62045:8;62055:11;62016:16;:51::i;:::-;62325:11;;:102;;-1:-1:-1;;;62325:102:0;;61991:76;;-1:-1:-1;62282:21:0;;;;-1:-1:-1;;;;;62325:11:0;;:41;;:102;;62375:4;;62390:16;;61991:76;;62325:102;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;62281:146;;;;9216:1;62446:16;:28;62438:92;;;;-1:-1:-1;;;62438:92:0;;21961:2:1;62438:92:0;;;21943:21:1;22000:2;21980:18;;;21973:30;22039:34;22019:18;;;22012:62;-1:-1:-1;;;22090:18:1;;;22083:49;22149:19;;62438:92:0;21759:415:1;62438:92:0;62624:36;;-1:-1:-1;;;62624:36:0;;-1:-1:-1;;;;;4986:32:1;;;62624:36:0;;;4968:51:1;62664:11:0;;62624:26;;;;;;4941:18:1;;62624:36:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:51;;62616:88;;;;-1:-1:-1;;;62616:88:0;;22381:2:1;62616:88:0;;;22363:21:1;22420:2;22400:18;;;22393:30;22459:26;22439:18;;;22432:54;22503:18;;62616:88:0;22179:348:1;62616:88:0;-1:-1:-1;;;;;62837:42:0;;62874:4;62837:42;62833:273;;;62896:63;62918:4;62925:10;62937:8;62947:11;62896:13;:63::i;:::-;62833:273;;;63000:57;;-1:-1:-1;;;63000:57:0;;9216:1;;-1:-1:-1;;;;;63000:22:0;;;;;:57;;63023:10;;63035:8;;63045:11;;63000:57;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:69;62992:102;;;;-1:-1:-1;;;62992:102:0;;22734:2:1;62992:102:0;;;22716:21:1;22773:2;22753:18;;;22746:30;-1:-1:-1;;;22792:18:1;;;22785:50;22852:18;;62992:102:0;22532:344:1;62992:102:0;63170:96;;;-1:-1:-1;;;;;23196:15:1;;;23178:34;;23248:15;;;23243:2;23228:18;;23221:43;23280:18;;;23273:34;;;23343:15;;23338:2;23323:18;;23316:43;23390:3;23375:19;;23368:35;;;63170:96:0;;;;;;;23127:3:1;63170:96:0;;;60798:2476;;;;60669:2605;;;;:::o;86477:1372::-;86635:10;;86760:52;;-1:-1:-1;;;86760:52:0;;86806:4;86760:52;;;4968:51:1;86561:4:0;;-1:-1:-1;;;;;86635:10:0;;;;86561:4;;86635:10;;86760:37;;4941:18:1;;86760:52:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;86823:47;;-1:-1:-1;;;86823:47:0;;86739:73;;-1:-1:-1;;;;;;86823:18:0;;;;;:47;;86842:4;;86856;;86863:6;;86823:47;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;86883:12;86937:16;86976:1;86971:153;;;;87147:2;87142:229;;;;87507:1;87504;87497:12;86971:153;-1:-1:-1;;87067:6:0;-1:-1:-1;86971:153:0;;87142:229;87245:2;87242:1;87239;87224:24;87287:1;87281:8;87270:19;;86930:598;;87557:7;87549:44;;;;-1:-1:-1;;;87549:44:0;;23616:2:1;87549:44:0;;;23598:21:1;23655:2;23635:18;;;23628:30;23694:26;23674:18;;;23667:54;23738:18;;87549:44:0;23414:348:1;87549:44:0;87691:52;;-1:-1:-1;;;87691:52:0;;87737:4;87691:52;;;4968:51:1;87671:17:0;;-1:-1:-1;;;;;87691:37:0;;;;;4941:18:1;;87691:52:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;87671:72;-1:-1:-1;87761:28:0;87776:13;87671:72;87761:28;:::i;:::-;87754:35;86477:1372;-1:-1:-1;;;;;;;;86477:1372:0:o;28620:126::-;28679:4;28703:35;28708:17;28713:1;24015:4;28708;:17::i;:::-;28727:10;;29284:4;29308:5;29312:1;29308;:5;:::i;-1:-1:-1:-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14:597:1;126:4;155:2;184;173:9;166:21;216:6;210:13;259:6;254:2;243:9;239:18;232:34;284:1;294:140;308:6;305:1;302:13;294:140;;;403:14;;;399:23;;393:30;369:17;;;388:2;365:26;358:66;323:10;;294:140;;;452:6;449:1;446:13;443:91;;;522:1;517:2;508:6;497:9;493:22;489:31;482:42;443:91;-1:-1:-1;595:2:1;574:15;-1:-1:-1;;570:29:1;555:45;;;;602:2;551:54;;14:597;-1:-1:-1;;;14:597:1:o;616:131::-;-1:-1:-1;;;;;691:31:1;;681:42;;671:70;;737:1;734;727:12;671:70;616:131;:::o;752:315::-;820:6;828;881:2;869:9;860:7;856:23;852:32;849:52;;;897:1;894;887:12;849:52;936:9;923:23;955:31;980:5;955:31;:::i;:::-;1005:5;1057:2;1042:18;;;;1029:32;;-1:-1:-1;;;752:315:1:o;1264:180::-;1323:6;1376:2;1364:9;1355:7;1351:23;1347:32;1344:52;;;1392:1;1389;1382:12;1344:52;-1:-1:-1;1415:23:1;;1264:180;-1:-1:-1;1264:180:1:o;1631:247::-;1690:6;1743:2;1731:9;1722:7;1718:23;1714:32;1711:52;;;1759:1;1756;1749:12;1711:52;1798:9;1785:23;1817:31;1842:5;1817:31;:::i;1883:127::-;1944:10;1939:3;1935:20;1932:1;1925:31;1975:4;1972:1;1965:15;1999:4;1996:1;1989:15;2015:719;2058:5;2111:3;2104:4;2096:6;2092:17;2088:27;2078:55;;2129:1;2126;2119:12;2078:55;2165:6;2152:20;2191:18;2228:2;2224;2221:10;2218:36;;;2234:18;;:::i;:::-;2309:2;2303:9;2277:2;2363:13;;-1:-1:-1;;2359:22:1;;;2383:2;2355:31;2351:40;2339:53;;;2407:18;;;2427:22;;;2404:46;2401:72;;;2453:18;;:::i;:::-;2493:10;2489:2;2482:22;2528:2;2520:6;2513:18;2574:3;2567:4;2562:2;2554:6;2550:15;2546:26;2543:35;2540:55;;;2591:1;2588;2581:12;2540:55;2655:2;2648:4;2640:6;2636:17;2629:4;2621:6;2617:17;2604:54;2702:1;2695:4;2690:2;2682:6;2678:15;2674:26;2667:37;2722:6;2713:15;;;;;;2015:719;;;;:::o;2739:156::-;2805:20;;2865:4;2854:16;;2844:27;;2834:55;;2885:1;2882;2875:12;2834:55;2739:156;;;:::o;2900:1155::-;3084:6;3092;3100;3108;3116;3124;3132;3185:3;3173:9;3164:7;3160:23;3156:33;3153:53;;;3202:1;3199;3192:12;3153:53;3241:9;3228:23;3260:31;3285:5;3260:31;:::i;:::-;3310:5;-1:-1:-1;3367:2:1;3352:18;;3339:32;3380:33;3339:32;3380:33;:::i;:::-;3432:7;-1:-1:-1;3491:2:1;3476:18;;3463:32;3504:33;3463:32;3504:33;:::i;:::-;3556:7;-1:-1:-1;3610:2:1;3595:18;;3582:32;;-1:-1:-1;3665:3:1;3650:19;;3637:33;3689:18;3719:14;;;3716:34;;;3746:1;3743;3736:12;3716:34;3769:50;3811:7;3802:6;3791:9;3787:22;3769:50;:::i;:::-;3759:60;;3872:3;3861:9;3857:19;3844:33;3828:49;;3902:2;3892:8;3889:16;3886:36;;;3918:1;3915;3908:12;3886:36;;3941:52;3985:7;3974:8;3963:9;3959:24;3941:52;:::i;:::-;3931:62;;;4012:37;4044:3;4033:9;4029:19;4012:37;:::i;:::-;4002:47;;2900:1155;;;;;;;;;;:::o;4345:456::-;4422:6;4430;4438;4491:2;4479:9;4470:7;4466:23;4462:32;4459:52;;;4507:1;4504;4497:12;4459:52;4546:9;4533:23;4565:31;4590:5;4565:31;:::i;:::-;4615:5;-1:-1:-1;4672:2:1;4657:18;;4644:32;4685:33;4644:32;4685:33;:::i;:::-;4345:456;;4737:7;;-1:-1:-1;;;4791:2:1;4776:18;;;;4763:32;;4345:456::o;5943:1013::-;6118:6;6126;6134;6142;6150;6158;6211:3;6199:9;6190:7;6186:23;6182:33;6179:53;;;6228:1;6225;6218:12;6179:53;6267:9;6254:23;6286:31;6311:5;6286:31;:::i;:::-;6336:5;-1:-1:-1;6393:2:1;6378:18;;6365:32;6406:33;6365:32;6406:33;:::i;:::-;6458:7;-1:-1:-1;6512:2:1;6497:18;;6484:32;;-1:-1:-1;6567:2:1;6552:18;;6539:32;6590:18;6620:14;;;6617:34;;;6647:1;6644;6637:12;6617:34;6670:50;6712:7;6703:6;6692:9;6688:22;6670:50;:::i;:::-;6660:60;;6773:3;6762:9;6758:19;6745:33;6729:49;;6803:2;6793:8;6790:16;6787:36;;;6819:1;6816;6809:12;6787:36;;6842:52;6886:7;6875:8;6864:9;6860:24;6842:52;:::i;:::-;6832:62;;;6913:37;6945:3;6934:9;6930:19;6913:37;:::i;:::-;6903:47;;5943:1013;;;;;;;;:::o;7617:388::-;7685:6;7693;7746:2;7734:9;7725:7;7721:23;7717:32;7714:52;;;7762:1;7759;7752:12;7714:52;7801:9;7788:23;7820:31;7845:5;7820:31;:::i;:::-;7870:5;-1:-1:-1;7927:2:1;7912:18;;7899:32;7940:33;7899:32;7940:33;:::i;:::-;7992:7;7982:17;;;7617:388;;;;;:::o;8520:479::-;8620:6;8628;8636;8689:2;8677:9;8668:7;8664:23;8660:32;8657:52;;;8705:1;8702;8695:12;8657:52;8744:9;8731:23;8763:31;8788:5;8763:31;:::i;:::-;8813:5;-1:-1:-1;8865:2:1;8850:18;;8837:32;;-1:-1:-1;8921:2:1;8906:18;;8893:32;8934:33;8893:32;8934:33;:::i;:::-;8986:7;8976:17;;;8520:479;;;;;:::o;9004:380::-;9083:1;9079:12;;;;9126;;;9147:61;;9201:4;9193:6;9189:17;9179:27;;9147:61;9254:2;9246:6;9243:14;9223:18;9220:38;9217:161;;;9300:10;9295:3;9291:20;9288:1;9281:31;9335:4;9332:1;9325:15;9363:4;9360:1;9353:15;9217:161;;9004:380;;;:::o;9389:334::-;9591:2;9573:21;;;9630:2;9610:18;;;9603:30;-1:-1:-1;;;9664:2:1;9649:18;;9642:40;9714:2;9699:18;;9389:334::o;9728:184::-;9798:6;9851:2;9839:9;9830:7;9826:23;9822:32;9819:52;;;9867:1;9864;9857:12;9819:52;-1:-1:-1;9890:16:1;;9728:184;-1:-1:-1;9728:184:1:o;11039:277::-;11106:6;11159:2;11147:9;11138:7;11134:23;11130:32;11127:52;;;11175:1;11172;11165:12;11127:52;11207:9;11201:16;11260:5;11253:13;11246:21;11239:5;11236:32;11226:60;;11282:1;11279;11272:12;15122:127;15183:10;15178:3;15174:20;15171:1;15164:31;15214:4;15211:1;15204:15;15238:4;15235:1;15228:15;15254:125;15294:4;15322:1;15319;15316:8;15313:34;;;15327:18;;:::i;:::-;-1:-1:-1;15364:9:1;;15254:125::o;15384:128::-;15424:3;15455:1;15451:6;15448:1;15445:13;15442:39;;;15461:18;;:::i;:::-;-1:-1:-1;15497:9:1;;15384:128::o;15834:168::-;15874:7;15940:1;15936;15932:6;15928:14;15925:1;15922:21;15917:1;15910:9;15903:17;15899:45;15896:71;;;15947:18;;:::i;:::-;-1:-1:-1;15987:9:1;;15834:168::o;16007:217::-;16047:1;16073;16063:132;;16117:10;16112:3;16108:20;16105:1;16098:31;16152:4;16149:1;16142:15;16180:4;16177:1;16170:15;16063:132;-1:-1:-1;16209:9:1;;16007:217::o;16690:353::-;-1:-1:-1;;;;;16918:32:1;;;;16900:51;;16982:2;16967:18;;16960:34;;;;17025:2;17010:18;;17003:34;16888:2;16873:18;;16690:353::o;19851:383::-;-1:-1:-1;;;;;20117:15:1;;;20099:34;;20169:15;;;;20164:2;20149:18;;20142:43;20216:2;20201:18;;20194:34;;;;20049:2;20034:18;;19851:383::o;21509:245::-;21588:6;21596;21649:2;21637:9;21628:7;21624:23;21620:32;21617:52;;;21665:1;21662;21655:12;21617:52;-1:-1:-1;;21688:16:1;;21744:2;21729:18;;;21723:25;21688:16;;21723:25;;-1:-1:-1;21509:245:1:o
Swarm Source
ipfs://6986794797f3615ae938bfb57cf952b9655c64451480c72bc64a1f974150c385
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.