More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 1,032 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Redeem Underlyin... | 13910034 | 45 days ago | IN | 0 ETH | 0.00001838 | ||||
Redeem Underlyin... | 12444297 | 109 days ago | IN | 0 ETH | 0.00001789 | ||||
Redeem Underlyin... | 12444265 | 109 days ago | IN | 0 ETH | 0.00002407 | ||||
Redeem Underlyin... | 12444188 | 109 days ago | IN | 0 ETH | 0.00002053 | ||||
Redeem Underlyin... | 12037528 | 125 days ago | IN | 0 ETH | 0.00001239 | ||||
Redeem Underlyin... | 11506217 | 144 days ago | IN | 0 ETH | 0.00001955 | ||||
Redeem Underlyin... | 11487990 | 145 days ago | IN | 0 ETH | 0.00001648 | ||||
Redeem Underlyin... | 11101712 | 159 days ago | IN | 0 ETH | 0.00005796 | ||||
Redeem Underlyin... | 10951944 | 164 days ago | IN | 0 ETH | 0.00001852 | ||||
Redeem Underlyin... | 10951756 | 164 days ago | IN | 0 ETH | 0.00001499 | ||||
Redeem Underlyin... | 10789760 | 170 days ago | IN | 0 ETH | 0.00001247 | ||||
Redeem Underlyin... | 10719288 | 173 days ago | IN | 0 ETH | 0.00001989 | ||||
Redeem Underlyin... | 10684342 | 174 days ago | IN | 0 ETH | 0.000017 | ||||
Redeem Underlyin... | 10589019 | 177 days ago | IN | 0 ETH | 0.0000126 | ||||
Redeem Underlyin... | 10516302 | 180 days ago | IN | 0 ETH | 0.00001754 | ||||
Redeem Underlyin... | 10454913 | 182 days ago | IN | 0 ETH | 0.00001933 | ||||
Mint | 10450162 | 182 days ago | IN | 0.0005 ETH | 0.00000592 | ||||
Mint | 10450129 | 182 days ago | IN | 0.0005 ETH | 0.00000649 | ||||
Redeem Underlyin... | 10423598 | 183 days ago | IN | 0 ETH | 0.00001587 | ||||
Redeem Underlyin... | 10409215 | 183 days ago | IN | 0 ETH | 0.00003492 | ||||
Redeem Underlyin... | 10386918 | 183 days ago | IN | 0 ETH | 0.00001301 | ||||
Mint | 10282681 | 187 days ago | IN | 0.00000005 ETH | 0.00002025 | ||||
Mint | 10282117 | 187 days ago | IN | 0.0000001 ETH | 0.00001933 | ||||
Mint | 10281793 | 187 days ago | IN | 0.00000013 ETH | 0.00002013 | ||||
Mint | 10280915 | 187 days ago | IN | 0.00000124 ETH | 0.00001559 |
Latest 25 internal transactions (View All)
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
13910034 | 45 days ago | 0.05035123 ETH | ||||
13910027 | 45 days ago | 0.03673459 ETH | ||||
12986686 | 86 days ago | 0.00162691 ETH | ||||
12444297 | 109 days ago | 0.00239093 ETH | ||||
12444265 | 109 days ago | 0.01185564 ETH | ||||
12444188 | 109 days ago | 0.00086186 ETH | ||||
12037528 | 125 days ago | 0.00113262 ETH | ||||
11506217 | 144 days ago | 0.45127847 ETH | ||||
11487990 | 145 days ago | 0.01303594 ETH | ||||
11487973 | 145 days ago | 0.0070646 ETH | ||||
11101712 | 159 days ago | 0.00040882 ETH | ||||
11101704 | 159 days ago | 0.00035294 ETH | ||||
10951944 | 164 days ago | 0.00023083 ETH | ||||
10951756 | 164 days ago | 0.00301154 ETH | ||||
10789760 | 170 days ago | 0.01003639 ETH | ||||
10719288 | 173 days ago | 0.01509683 ETH | ||||
10719276 | 173 days ago | 0.01018154 ETH | ||||
10684342 | 174 days ago | 0.01609503 ETH | ||||
10684309 | 174 days ago | 0.01118176 ETH | ||||
10589019 | 177 days ago | 0.00060232 ETH | ||||
10516302 | 180 days ago | 0.01006432 ETH | ||||
10454913 | 182 days ago | 0.01646109 ETH | ||||
10423598 | 183 days ago | 0.00402619 ETH | ||||
10409215 | 183 days ago | 0.01219352 ETH | ||||
10386918 | 183 days ago | 0.00120796 ETH |
Loading...
Loading
Contract Name:
CEther
Compiler Version
v0.8.18+commit.87f61d96
Contract Source Code (Solidity)
/** *Submitted for verification at scrollscan.com on 2023-10-28 */ /** *Submitted for verification at scrollscan.com on 2023-10-18 */ // Sources flattened with hardhat v2.14.0 https://hardhat.org // SPDX-License-Identifier: BSD-3-Clause // File contracts/ComptrollerInterface.sol pragma solidity ^0.8.10; abstract contract ComptrollerInterface { /// @notice Indicator that this is a Comptroller contract (for inspection) bool public constant isComptroller = true; /*** Assets You Are In ***/ function enterMarkets(address[] calldata cTokens) virtual external returns (uint[] memory); function exitMarket(address cToken) virtual external returns (uint); /*** Policy Hooks ***/ function mintAllowed(address cToken, address minter, uint mintAmount) virtual external returns (uint); function mintVerify(address cToken, address minter, uint mintAmount, uint mintTokens) virtual external; function redeemAllowed(address cToken, address redeemer, uint redeemTokens) virtual external returns (uint); function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) virtual external; function borrowAllowed(address cToken, address borrower, uint borrowAmount) virtual external returns (uint); function borrowVerify(address cToken, address borrower, uint borrowAmount) virtual external; function repayBorrowAllowed( address cToken, address payer, address borrower, uint repayAmount) virtual external returns (uint); function repayBorrowVerify( address cToken, address payer, address borrower, uint repayAmount, uint borrowerIndex) virtual external; function liquidateBorrowAllowed( address cTokenBorrowed, address cTokenCollateral, address liquidator, address borrower, uint repayAmount) virtual external returns (uint); function liquidateBorrowVerify( address cTokenBorrowed, address cTokenCollateral, address liquidator, address borrower, uint repayAmount, uint seizeTokens) virtual external; function seizeAllowed( address cTokenCollateral, address cTokenBorrowed, address liquidator, address borrower, uint seizeTokens) virtual external returns (uint); function seizeVerify( address cTokenCollateral, address cTokenBorrowed, address liquidator, address borrower, uint seizeTokens) virtual external; function transferAllowed(address cToken, address src, address dst, uint transferTokens) virtual external returns (uint); function transferVerify(address cToken, address src, address dst, uint transferTokens) virtual external; /*** Liquidity/Liquidation Calculations ***/ function liquidateCalculateSeizeTokens( address cTokenBorrowed, address cTokenCollateral, uint repayAmount) virtual external view returns (uint, uint); } // File contracts/EIP20NonStandardInterface.sol pragma solidity ^0.8.10; /** * @title EIP20NonStandardInterface * @dev Version of ERC20 with no return values for `transfer` and `transferFrom` * See https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca */ interface EIP20NonStandardInterface { /** * @notice Get the total number of tokens in circulation * @return The supply of tokens */ function totalSupply() external view returns (uint256); /** * @notice Gets the balance of the specified address * @param owner The address from which the balance will be retrieved * @return balance The balance */ function balanceOf(address owner) external view returns (uint256 balance); /// /// !!!!!!!!!!!!!! /// !!! NOTICE !!! `transfer` does not return a value, in violation of the ERC-20 specification /// !!!!!!!!!!!!!! /// /** * @notice Transfer `amount` tokens from `msg.sender` to `dst` * @param dst The address of the destination account * @param amount The number of tokens to transfer */ function transfer(address dst, uint256 amount) external; /// /// !!!!!!!!!!!!!! /// !!! NOTICE !!! `transferFrom` does not return a value, in violation of the ERC-20 specification /// !!!!!!!!!!!!!! /// /** * @notice Transfer `amount` tokens from `src` to `dst` * @param src The address of the source account * @param dst The address of the destination account * @param amount The number of tokens to transfer */ function transferFrom(address src, address dst, uint256 amount) external; /** * @notice Approve `spender` to transfer up to `amount` from `src` * @dev This will overwrite the approval amount for `spender` * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve) * @param spender The address of the account which may transfer tokens * @param amount The number of tokens that are approved * @return success Whether or not the approval succeeded */ function approve(address spender, uint256 amount) external returns (bool success); /** * @notice Get the current allowance from `owner` for `spender` * @param owner The address of the account which owns the tokens to be spent * @param spender The address of the account which may transfer tokens * @return remaining The number of tokens allowed to be spent */ function allowance(address owner, address spender) external view returns (uint256 remaining); event Transfer(address indexed from, address indexed to, uint256 amount); event Approval(address indexed owner, address indexed spender, uint256 amount); } // File contracts/ErrorReporter.sol pragma solidity ^0.8.10; contract ComptrollerErrorReporter { enum Error { NO_ERROR, UNAUTHORIZED, COMPTROLLER_MISMATCH, INSUFFICIENT_SHORTFALL, INSUFFICIENT_LIQUIDITY, INVALID_CLOSE_FACTOR, INVALID_COLLATERAL_FACTOR, INVALID_LIQUIDATION_INCENTIVE, MARKET_NOT_ENTERED, // no longer possible MARKET_NOT_LISTED, MARKET_ALREADY_LISTED, MATH_ERROR, NONZERO_BORROW_BALANCE, PRICE_ERROR, REJECTION, SNAPSHOT_ERROR, TOO_MANY_ASSETS, TOO_MUCH_REPAY } enum FailureInfo { ACCEPT_ADMIN_PENDING_ADMIN_CHECK, ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK, EXIT_MARKET_BALANCE_OWED, EXIT_MARKET_REJECTION, SET_CLOSE_FACTOR_OWNER_CHECK, SET_CLOSE_FACTOR_VALIDATION, SET_COLLATERAL_FACTOR_OWNER_CHECK, SET_COLLATERAL_FACTOR_NO_EXISTS, SET_COLLATERAL_FACTOR_VALIDATION, SET_COLLATERAL_FACTOR_WITHOUT_PRICE, SET_IMPLEMENTATION_OWNER_CHECK, SET_LIQUIDATION_INCENTIVE_OWNER_CHECK, SET_LIQUIDATION_INCENTIVE_VALIDATION, SET_MAX_ASSETS_OWNER_CHECK, SET_PENDING_ADMIN_OWNER_CHECK, SET_PENDING_IMPLEMENTATION_OWNER_CHECK, SET_PRICE_ORACLE_OWNER_CHECK, SUPPORT_MARKET_EXISTS, SUPPORT_MARKET_OWNER_CHECK, SET_PAUSE_GUARDIAN_OWNER_CHECK } /** * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary * contract-specific code that enables us to report opaque error codes from upgradeable contracts. **/ event Failure(uint error, uint info, uint detail); /** * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator */ function fail(Error err, FailureInfo info) internal returns (uint) { emit Failure(uint(err), uint(info), 0); return uint(err); } /** * @dev use this when reporting an opaque error from an upgradeable collaborator contract */ function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) { emit Failure(uint(err), uint(info), opaqueError); return uint(err); } } contract TokenErrorReporter { uint public constant NO_ERROR = 0; // support legacy return codes error TransferComptrollerRejection(uint256 errorCode); error TransferNotAllowed(); error TransferNotEnough(); error TransferTooMuch(); error MintComptrollerRejection(uint256 errorCode); error MintFreshnessCheck(); error RedeemComptrollerRejection(uint256 errorCode); error RedeemFreshnessCheck(); error RedeemTransferOutNotPossible(); error BorrowComptrollerRejection(uint256 errorCode); error BorrowFreshnessCheck(); error BorrowCashNotAvailable(); error RepayBorrowComptrollerRejection(uint256 errorCode); error RepayBorrowFreshnessCheck(); error LiquidateComptrollerRejection(uint256 errorCode); error LiquidateFreshnessCheck(); error LiquidateCollateralFreshnessCheck(); error LiquidateAccrueBorrowInterestFailed(uint256 errorCode); error LiquidateAccrueCollateralInterestFailed(uint256 errorCode); error LiquidateLiquidatorIsBorrower(); error LiquidateCloseAmountIsZero(); error LiquidateCloseAmountIsUintMax(); error LiquidateRepayBorrowFreshFailed(uint256 errorCode); error LiquidateSeizeComptrollerRejection(uint256 errorCode); error LiquidateSeizeLiquidatorIsBorrower(); error AcceptAdminPendingAdminCheck(); error SetComptrollerOwnerCheck(); error SetPendingAdminOwnerCheck(); error SetReserveFactorAdminCheck(); error SetReserveFactorFreshCheck(); error SetReserveFactorBoundsCheck(); error AddReservesFactorFreshCheck(uint256 actualAddAmount); error ReduceReservesAdminCheck(); error ReduceReservesFreshCheck(); error ReduceReservesCashNotAvailable(); error ReduceReservesCashValidation(); error SetInterestRateModelOwnerCheck(); error SetInterestRateModelFreshCheck(); } // File contracts/InterestRateModel.sol pragma solidity ^0.8.10; /** * @title Loanshark's InterestRateModel Interface * @author Loanshark */ abstract contract InterestRateModel { /// @notice Indicator that this is an InterestRateModel contract (for inspection) bool public constant isInterestRateModel = true; /** * @notice Calculates the current borrow interest rate per block * @param cash The total amount of cash the market has * @param borrows The total amount of borrows the market has outstanding * @param reserves The total amount of reserves the market has * @return The borrow rate per block (as a percentage, and scaled by 1e18) */ function getBorrowRate(uint cash, uint borrows, uint reserves) virtual external view returns (uint); /** * @notice Calculates the current supply interest rate per block * @param cash The total amount of cash the market has * @param borrows The total amount of borrows the market has outstanding * @param reserves The total amount of reserves the market has * @param reserveFactorMantissa The current reserve factor the market has * @return The supply rate per block (as a percentage, and scaled by 1e18) */ function getSupplyRate(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) virtual external view returns (uint); } // File contracts/CTokenInterfaces.sol pragma solidity ^0.8.10; contract CTokenStorage { /** * @dev Guard variable for re-entrancy checks */ bool internal _notEntered; /** * @notice EIP-20 token name for this token */ string public name; /** * @notice EIP-20 token symbol for this token */ string public symbol; /** * @notice EIP-20 token decimals for this token */ uint8 public decimals; // Maximum borrow rate that can ever be applied (.0005% / block) uint internal constant borrowRateMaxMantissa = 0.0005e16; // Maximum fraction of interest that can be set aside for reserves uint internal constant reserveFactorMaxMantissa = 1e18; /** * @notice Administrator for this contract */ address payable public admin; /** * @notice Pending administrator for this contract */ address payable public pendingAdmin; /** * @notice Contract which oversees inter-cToken operations */ ComptrollerInterface public comptroller; /** * @notice Model which tells what the current interest rate should be */ InterestRateModel public interestRateModel; // Initial exchange rate used when minting the first CTokens (used when totalSupply = 0) uint internal initialExchangeRateMantissa; /** * @notice Fraction of interest currently set aside for reserves */ uint public reserveFactorMantissa; /** * @notice Block number that interest was last accrued at */ uint public accrualBlockNumber; /** * @notice Accumulator of the total earned interest rate since the opening of the market */ uint public borrowIndex; /** * @notice Total amount of outstanding borrows of the underlying in this market */ uint public totalBorrows; /** * @notice Total amount of reserves of the underlying held in this market */ uint public totalReserves; /** * @notice Total number of tokens in circulation */ uint public totalSupply; // Official record of token balances for each account mapping (address => uint) internal accountTokens; // Approved token transfer amounts on behalf of others mapping (address => mapping (address => uint)) internal transferAllowances; /** * @notice Container for borrow balance information * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action * @member interestIndex Global borrowIndex as of the most recent balance-changing action */ struct BorrowSnapshot { uint principal; uint interestIndex; } // Mapping of account addresses to outstanding borrow balances mapping(address => BorrowSnapshot) internal accountBorrows; /** * @notice Share of seized collateral that is added to reserves */ uint public constant protocolSeizeShareMantissa = 2.8e16; //2.8% } abstract contract CTokenInterface is CTokenStorage { /** * @notice Indicator that this is a CToken contract (for inspection) */ bool public constant isCToken = true; /*** Market Events ***/ /** * @notice Event emitted when interest is accrued */ event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows); /** * @notice Event emitted when tokens are minted */ event Mint(address minter, uint mintAmount, uint mintTokens); /** * @notice Event emitted when tokens are redeemed */ event Redeem(address redeemer, uint redeemAmount, uint redeemTokens); /** * @notice Event emitted when underlying is borrowed */ event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows); /** * @notice Event emitted when a borrow is repaid */ event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows); /** * @notice Event emitted when a borrow is liquidated */ event LiquidateBorrow(address liquidator, address borrower, uint repayAmount, address cTokenCollateral, uint seizeTokens); /*** Admin Events ***/ /** * @notice Event emitted when pendingAdmin is changed */ event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin); /** * @notice Event emitted when pendingAdmin is accepted, which means admin is updated */ event NewAdmin(address oldAdmin, address newAdmin); /** * @notice Event emitted when comptroller is changed */ event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller); /** * @notice Event emitted when interestRateModel is changed */ event NewMarketInterestRateModel(InterestRateModel oldInterestRateModel, InterestRateModel newInterestRateModel); /** * @notice Event emitted when the reserve factor is changed */ event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa); /** * @notice Event emitted when the reserves are added */ event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves); /** * @notice Event emitted when the reserves are reduced */ event ReservesReduced(address admin, uint reduceAmount, uint newTotalReserves); /** * @notice EIP20 Transfer event */ event Transfer(address indexed from, address indexed to, uint amount); /** * @notice EIP20 Approval event */ event Approval(address indexed owner, address indexed spender, uint amount); /*** User Interface ***/ function transfer(address dst, uint amount) virtual external returns (bool); function transferFrom(address src, address dst, uint amount) virtual external returns (bool); function approve(address spender, uint amount) virtual external returns (bool); function allowance(address owner, address spender) virtual external view returns (uint); function balanceOf(address owner) virtual external view returns (uint); function balanceOfUnderlying(address owner) virtual external returns (uint); function getAccountSnapshot(address account) virtual external view returns (uint, uint, uint, uint); function borrowRatePerBlock() virtual external view returns (uint); function supplyRatePerBlock() virtual external view returns (uint); function totalBorrowsCurrent() virtual external returns (uint); function borrowBalanceCurrent(address account) virtual external returns (uint); function borrowBalanceStored(address account) virtual external view returns (uint); function exchangeRateCurrent() virtual external returns (uint); function exchangeRateStored() virtual external view returns (uint); function getCash() virtual external view returns (uint); function accrueInterest() virtual external returns (uint); function seize(address liquidator, address borrower, uint seizeTokens) virtual external returns (uint); /*** Admin Functions ***/ function _setPendingAdmin(address payable newPendingAdmin) virtual external returns (uint); function _acceptAdmin() virtual external returns (uint); function _setComptroller(ComptrollerInterface newComptroller) virtual external returns (uint); function _setReserveFactor(uint newReserveFactorMantissa) virtual external returns (uint); function _reduceReserves(uint reduceAmount) virtual external returns (uint); function _setInterestRateModel(InterestRateModel newInterestRateModel) virtual external returns (uint); } contract CErc20Storage { /** * @notice Underlying asset for this CToken */ address public underlying; } abstract contract CErc20Interface is CErc20Storage { /*** User Interface ***/ function mint(uint mintAmount) virtual external returns (uint); function redeem(uint redeemTokens) virtual external returns (uint); function redeemUnderlying(uint redeemAmount) virtual external returns (uint); function borrow(uint borrowAmount) virtual external returns (uint); function repayBorrow(uint repayAmount) virtual external returns (uint); function repayBorrowBehalf(address borrower, uint repayAmount) virtual external returns (uint); function liquidateBorrow(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) virtual external returns (uint); function sweepToken(EIP20NonStandardInterface token) virtual external; /*** Admin Functions ***/ function _addReserves(uint addAmount) virtual external returns (uint); } contract CDelegationStorage { /** * @notice Implementation address for this contract */ address public implementation; } abstract contract CDelegatorInterface is CDelegationStorage { /** * @notice Emitted when implementation is changed */ event NewImplementation(address oldImplementation, address newImplementation); /** * @notice Called by the admin to update the implementation of the delegator * @param implementation_ The address of the new implementation for delegation * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation */ function _setImplementation(address implementation_, bool allowResign, bytes memory becomeImplementationData) virtual external; } abstract contract CDelegateInterface is CDelegationStorage { /** * @notice Called by the delegator on a delegate to initialize it for duty * @dev Should revert if any issues arise which make it unfit for delegation * @param data The encoded bytes data for any initialization */ function _becomeImplementation(bytes memory data) virtual external; /** * @notice Called by the delegator on a delegate to forfeit its responsibility */ function _resignImplementation() virtual external; } // File contracts/EIP20Interface.sol pragma solidity ^0.8.10; /** * @title ERC 20 Token Standard Interface * https://eips.ethereum.org/EIPS/eip-20 */ interface EIP20Interface { function name() external view returns (string memory); function symbol() external view returns (string memory); function decimals() external view returns (uint8); /** * @notice Get the total number of tokens in circulation * @return The supply of tokens */ function totalSupply() external view returns (uint256); /** * @notice Gets the balance of the specified address * @param owner The address from which the balance will be retrieved * @return balance The balance */ function balanceOf(address owner) external view returns (uint256 balance); /** * @notice Transfer `amount` tokens from `msg.sender` to `dst` * @param dst The address of the destination account * @param amount The number of tokens to transfer * @return success Whether or not the transfer succeeded */ function transfer(address dst, uint256 amount) external returns (bool success); /** * @notice Transfer `amount` tokens from `src` to `dst` * @param src The address of the source account * @param dst The address of the destination account * @param amount The number of tokens to transfer * @return success Whether or not the transfer succeeded */ function transferFrom(address src, address dst, uint256 amount) external returns (bool success); /** * @notice Approve `spender` to transfer up to `amount` from `src` * @dev This will overwrite the approval amount for `spender` * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve) * @param spender The address of the account which may transfer tokens * @param amount The number of tokens that are approved (-1 means infinite) * @return success Whether or not the approval succeeded */ function approve(address spender, uint256 amount) external returns (bool success); /** * @notice Get the current allowance from `owner` for `spender` * @param owner The address of the account which owns the tokens to be spent * @param spender The address of the account which may transfer tokens * @return remaining The number of tokens allowed to be spent (-1 means infinite) */ function allowance(address owner, address spender) external view returns (uint256 remaining); event Transfer(address indexed from, address indexed to, uint256 amount); event Approval(address indexed owner, address indexed spender, uint256 amount); } // File contracts/ExponentialNoError.sol pragma solidity ^0.8.10; /** * @title Exponential module for storing fixed-precision decimals * @author Loanshark * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places. * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is: * `Exp({mantissa: 5100000000000000000})`. */ contract ExponentialNoError { uint constant expScale = 1e18; uint constant doubleScale = 1e36; uint constant halfExpScale = expScale/2; uint constant mantissaOne = expScale; struct Exp { uint mantissa; } struct Double { uint mantissa; } /** * @dev Truncates the given exp to a whole number value. * For example, truncate(Exp{mantissa: 15 * expScale}) = 15 */ function truncate(Exp memory exp) pure internal returns (uint) { // Note: We are not using careful math here as we're performing a division that cannot fail return exp.mantissa / expScale; } /** * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer. */ function mul_ScalarTruncate(Exp memory a, uint scalar) pure internal returns (uint) { Exp memory product = mul_(a, scalar); return truncate(product); } /** * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer. */ function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) pure internal returns (uint) { Exp memory product = mul_(a, scalar); return add_(truncate(product), addend); } /** * @dev Checks if first Exp is less than second Exp. */ function lessThanExp(Exp memory left, Exp memory right) pure internal returns (bool) { return left.mantissa < right.mantissa; } /** * @dev Checks if left Exp <= right Exp. */ function lessThanOrEqualExp(Exp memory left, Exp memory right) pure internal returns (bool) { return left.mantissa <= right.mantissa; } /** * @dev Checks if left Exp > right Exp. */ function greaterThanExp(Exp memory left, Exp memory right) pure internal returns (bool) { return left.mantissa > right.mantissa; } /** * @dev returns true if Exp is exactly zero */ function isZeroExp(Exp memory value) pure internal returns (bool) { return value.mantissa == 0; } function safe224(uint n, string memory errorMessage) pure internal returns (uint224) { require(n < 2**224, errorMessage); return uint224(n); } function safe32(uint n, string memory errorMessage) pure internal returns (uint32) { require(n < 2**32, errorMessage); return uint32(n); } function add_(Exp memory a, Exp memory b) pure internal returns (Exp memory) { return Exp({mantissa: add_(a.mantissa, b.mantissa)}); } function add_(Double memory a, Double memory b) pure internal returns (Double memory) { return Double({mantissa: add_(a.mantissa, b.mantissa)}); } function add_(uint a, uint b) pure internal returns (uint) { return a + b; } function sub_(Exp memory a, Exp memory b) pure internal returns (Exp memory) { return Exp({mantissa: sub_(a.mantissa, b.mantissa)}); } function sub_(Double memory a, Double memory b) pure internal returns (Double memory) { return Double({mantissa: sub_(a.mantissa, b.mantissa)}); } function sub_(uint a, uint b) pure internal returns (uint) { return a - b; } function mul_(Exp memory a, Exp memory b) pure internal returns (Exp memory) { return Exp({mantissa: mul_(a.mantissa, b.mantissa) / expScale}); } function mul_(Exp memory a, uint b) pure internal returns (Exp memory) { return Exp({mantissa: mul_(a.mantissa, b)}); } function mul_(uint a, Exp memory b) pure internal returns (uint) { return mul_(a, b.mantissa) / expScale; } function mul_(Double memory a, Double memory b) pure internal returns (Double memory) { return Double({mantissa: mul_(a.mantissa, b.mantissa) / doubleScale}); } function mul_(Double memory a, uint b) pure internal returns (Double memory) { return Double({mantissa: mul_(a.mantissa, b)}); } function mul_(uint a, Double memory b) pure internal returns (uint) { return mul_(a, b.mantissa) / doubleScale; } function mul_(uint a, uint b) pure internal returns (uint) { return a * b; } function div_(Exp memory a, Exp memory b) pure internal returns (Exp memory) { return Exp({mantissa: div_(mul_(a.mantissa, expScale), b.mantissa)}); } function div_(Exp memory a, uint b) pure internal returns (Exp memory) { return Exp({mantissa: div_(a.mantissa, b)}); } function div_(uint a, Exp memory b) pure internal returns (uint) { return div_(mul_(a, expScale), b.mantissa); } function div_(Double memory a, Double memory b) pure internal returns (Double memory) { return Double({mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa)}); } function div_(Double memory a, uint b) pure internal returns (Double memory) { return Double({mantissa: div_(a.mantissa, b)}); } function div_(uint a, Double memory b) pure internal returns (uint) { return div_(mul_(a, doubleScale), b.mantissa); } function div_(uint a, uint b) pure internal returns (uint) { return a / b; } function fraction(uint a, uint b) pure internal returns (Double memory) { return Double({mantissa: div_(mul_(a, doubleScale), b)}); } } // File contracts/CToken.sol pragma solidity ^0.8.10; /** * @title The base contract with helpful constants * @author The Redstone Oracles team * @dev It mainly contains redstone-related values, which improve readability * of other contracts (e.g. CalldataExtractor and RedstoneConsumerBase) */ contract RedstoneConstants { // === Abbreviations === // BS - Bytes size // PTR - Pointer (memory location) // SIG - Signature // Solidity and YUL constants uint256 internal constant STANDARD_SLOT_BS = 32; uint256 internal constant FREE_MEMORY_PTR = 0x40; uint256 internal constant BYTES_ARR_LEN_VAR_BS = 32; uint256 internal constant FUNCTION_SIGNATURE_BS = 4; uint256 internal constant REVERT_MSG_OFFSET = 68; // Revert message structure described here: https://ethereum.stackexchange.com/a/66173/106364 uint256 internal constant STRING_ERR_MESSAGE_MASK = 0x08c379a000000000000000000000000000000000000000000000000000000000; // RedStone protocol consts uint256 internal constant SIG_BS = 65; uint256 internal constant TIMESTAMP_BS = 6; uint256 internal constant DATA_PACKAGES_COUNT_BS = 2; uint256 internal constant DATA_POINTS_COUNT_BS = 3; uint256 internal constant DATA_POINT_VALUE_BYTE_SIZE_BS = 4; uint256 internal constant DATA_POINT_SYMBOL_BS = 32; uint256 internal constant DEFAULT_DATA_POINT_VALUE_BS = 32; uint256 internal constant UNSIGNED_METADATA_BYTE_SIZE_BS = 3; uint256 internal constant REDSTONE_MARKER_BS = 9; // byte size of 0x000002ed57011e0000 uint256 internal constant REDSTONE_MARKER_MASK = 0x0000000000000000000000000000000000000000000000000002ed57011e0000; // Derived values (based on consts) uint256 internal constant TIMESTAMP_NEGATIVE_OFFSET_IN_DATA_PACKAGE_WITH_STANDARD_SLOT_BS = 104; // SIG_BS + DATA_POINTS_COUNT_BS + DATA_POINT_VALUE_BYTE_SIZE_BS + STANDARD_SLOT_BS uint256 internal constant DATA_PACKAGE_WITHOUT_DATA_POINTS_BS = 78; // DATA_POINT_VALUE_BYTE_SIZE_BS + TIMESTAMP_BS + DATA_POINTS_COUNT_BS + SIG_BS uint256 internal constant DATA_PACKAGE_WITHOUT_DATA_POINTS_AND_SIG_BS = 13; // DATA_POINT_VALUE_BYTE_SIZE_BS + TIMESTAMP_BS + DATA_POINTS_COUNT_BS uint256 internal constant REDSTONE_MARKER_BS_PLUS_STANDARD_SLOT_BS = 41; // REDSTONE_MARKER_BS + STANDARD_SLOT_BS // Error messages error CalldataOverOrUnderFlow(); error IncorrectUnsignedMetadataSize(); error InsufficientNumberOfUniqueSigners(uint256 receivedSignersCount, uint256 requiredSignersCount); error EachSignerMustProvideTheSameValue(); error EmptyCalldataPointersArr(); error InvalidCalldataPointer(); error CalldataMustHaveValidPayload(); error SignerNotAuthorised(address receivedSigner); } library SafeMath { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { return a + b; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { return a * b; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b <= a, errorMessage); return a - b; } } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a / b; } } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a % b; } } } /** * @title The base contract with the main logic of data extraction from calldata * @author The Redstone Oracles team * @dev This contract was created to reuse the same logic in the RedstoneConsumerBase * and the ProxyConnector contracts */ contract CalldataExtractor is RedstoneConstants { using SafeMath for uint256; error DataPackageTimestampMustNotBeZero(); error DataPackageTimestampsMustBeEqual(); error RedstonePayloadMustHaveAtLeastOneDataPackage(); function extractTimestampsAndAssertAllAreEqual() public pure returns (uint256 extractedTimestamp) { uint256 calldataNegativeOffset = _extractByteSizeOfUnsignedMetadata(); uint256 dataPackagesCount = _extractDataPackagesCountFromCalldata(calldataNegativeOffset); if (dataPackagesCount == 0) { revert RedstonePayloadMustHaveAtLeastOneDataPackage(); } calldataNegativeOffset += DATA_PACKAGES_COUNT_BS; for (uint256 dataPackageIndex = 0; dataPackageIndex < dataPackagesCount; dataPackageIndex++) { uint256 dataPackageByteSize = _getDataPackageByteSize(calldataNegativeOffset); // Extracting timestamp for the current data package uint48 dataPackageTimestamp; // uint48, because timestamp uses 6 bytes uint256 timestampNegativeOffset = (calldataNegativeOffset + TIMESTAMP_NEGATIVE_OFFSET_IN_DATA_PACKAGE_WITH_STANDARD_SLOT_BS); uint256 timestampOffset = msg.data.length - timestampNegativeOffset; assembly { dataPackageTimestamp := calldataload(timestampOffset) } if (dataPackageTimestamp == 0) { revert DataPackageTimestampMustNotBeZero(); } if (extractedTimestamp == 0) { extractedTimestamp = dataPackageTimestamp; } else if (dataPackageTimestamp != extractedTimestamp) { revert DataPackageTimestampsMustBeEqual(); } calldataNegativeOffset += dataPackageByteSize; } } function _getDataPackageByteSize(uint256 calldataNegativeOffset) internal pure returns (uint256) { ( uint256 dataPointsCount, uint256 eachDataPointValueByteSize ) = _extractDataPointsDetailsForDataPackage(calldataNegativeOffset); return dataPointsCount * (DATA_POINT_SYMBOL_BS + eachDataPointValueByteSize) + DATA_PACKAGE_WITHOUT_DATA_POINTS_BS; } function _extractByteSizeOfUnsignedMetadata() internal pure returns (uint256) { // Checking if the calldata ends with the RedStone marker bool hasValidRedstoneMarker; assembly { let calldataLast32Bytes := calldataload(sub(calldatasize(), STANDARD_SLOT_BS)) hasValidRedstoneMarker := eq( REDSTONE_MARKER_MASK, and(calldataLast32Bytes, REDSTONE_MARKER_MASK) ) } if (!hasValidRedstoneMarker) { revert CalldataMustHaveValidPayload(); } // Using uint24, because unsigned metadata byte size number has 3 bytes uint24 unsignedMetadataByteSize; if (REDSTONE_MARKER_BS_PLUS_STANDARD_SLOT_BS > msg.data.length) { revert CalldataOverOrUnderFlow(); } assembly { unsignedMetadataByteSize := calldataload( sub(calldatasize(), REDSTONE_MARKER_BS_PLUS_STANDARD_SLOT_BS) ) } uint256 calldataNegativeOffset = unsignedMetadataByteSize + UNSIGNED_METADATA_BYTE_SIZE_BS + REDSTONE_MARKER_BS; if (calldataNegativeOffset + DATA_PACKAGES_COUNT_BS > msg.data.length) { revert IncorrectUnsignedMetadataSize(); } return calldataNegativeOffset; } // We return uint16, because unsigned metadata byte size number has 2 bytes function _extractDataPackagesCountFromCalldata(uint256 calldataNegativeOffset) internal pure returns (uint16 dataPackagesCount) { uint256 calldataNegativeOffsetWithStandardSlot = calldataNegativeOffset + STANDARD_SLOT_BS; if (calldataNegativeOffsetWithStandardSlot > msg.data.length) { revert CalldataOverOrUnderFlow(); } assembly { dataPackagesCount := calldataload( sub(calldatasize(), calldataNegativeOffsetWithStandardSlot) ) } return dataPackagesCount; } function _extractDataPointValueAndDataFeedId( uint256 calldataNegativeOffsetForDataPackage, uint256 defaultDataPointValueByteSize, uint256 dataPointIndex ) internal pure virtual returns (bytes32 dataPointDataFeedId, uint256 dataPointValue) { uint256 negativeOffsetToDataPoints = calldataNegativeOffsetForDataPackage + DATA_PACKAGE_WITHOUT_DATA_POINTS_BS; uint256 dataPointNegativeOffset = negativeOffsetToDataPoints.add( (1 + dataPointIndex).mul((defaultDataPointValueByteSize + DATA_POINT_SYMBOL_BS)) ); uint256 dataPointCalldataOffset = msg.data.length.sub(dataPointNegativeOffset); assembly { dataPointDataFeedId := calldataload(dataPointCalldataOffset) dataPointValue := calldataload(add(dataPointCalldataOffset, DATA_POINT_SYMBOL_BS)) } } function _extractDataPointsDetailsForDataPackage(uint256 calldataNegativeOffsetForDataPackage) internal pure returns (uint256 dataPointsCount, uint256 eachDataPointValueByteSize) { // Using uint24, because data points count byte size number has 3 bytes uint24 dataPointsCount_; // Using uint32, because data point value byte size has 4 bytes uint32 eachDataPointValueByteSize_; // Extract data points count uint256 negativeCalldataOffset = calldataNegativeOffsetForDataPackage + SIG_BS; uint256 calldataOffset = msg.data.length.sub(negativeCalldataOffset + STANDARD_SLOT_BS); assembly { dataPointsCount_ := calldataload(calldataOffset) } // Extract each data point value size calldataOffset = calldataOffset.sub(DATA_POINTS_COUNT_BS); assembly { eachDataPointValueByteSize_ := calldataload(calldataOffset) } // Prepare returned values dataPointsCount = dataPointsCount_; eachDataPointValueByteSize = eachDataPointValueByteSize_; } } /** * @title The base contract for forwarding redstone payload to other contracts * @author The Redstone Oracles team */ contract ProxyConnector is RedstoneConstants, CalldataExtractor { error ProxyCalldataFailedWithoutErrMsg(); error ProxyCalldataFailedWithStringMessage(string message); error ProxyCalldataFailedWithCustomError(bytes result); function proxyCalldata( address contractAddress, bytes memory encodedFunction, bool forwardValue ) internal returns (bytes memory) { bytes memory message = _prepareMessage(encodedFunction); (bool success, bytes memory result) = contractAddress.call{value: forwardValue ? msg.value : 0}(message); return _prepareReturnValue(success, result); } function proxyDelegateCalldata(address contractAddress, bytes memory encodedFunction) internal returns (bytes memory) { bytes memory message = _prepareMessage(encodedFunction); (bool success, bytes memory result) = contractAddress.delegatecall(message); return _prepareReturnValue(success, result); } function proxyCalldataView(address contractAddress, bytes memory encodedFunction) internal view returns (bytes memory) { bytes memory message = _prepareMessage(encodedFunction); (bool success, bytes memory result) = contractAddress.staticcall(message); return _prepareReturnValue(success, result); } function _prepareMessage(bytes memory encodedFunction) private pure returns (bytes memory) { uint256 encodedFunctionBytesCount = encodedFunction.length; uint256 redstonePayloadByteSize = _getRedstonePayloadByteSize(); uint256 resultMessageByteSize = encodedFunctionBytesCount + redstonePayloadByteSize; if (redstonePayloadByteSize > msg.data.length) { revert CalldataOverOrUnderFlow(); } bytes memory message; assembly { message := mload(FREE_MEMORY_PTR) // sets message pointer to first free place in memory // Saving the byte size of the result message (it's a standard in EVM) mstore(message, resultMessageByteSize) // Copying function and its arguments for { let from := add(BYTES_ARR_LEN_VAR_BS, encodedFunction) let fromEnd := add(from, encodedFunctionBytesCount) let to := add(BYTES_ARR_LEN_VAR_BS, message) } lt (from, fromEnd) { from := add(from, STANDARD_SLOT_BS) to := add(to, STANDARD_SLOT_BS) } { // Copying data from encodedFunction to message (32 bytes at a time) mstore(to, mload(from)) } // Copying redstone payload to the message bytes calldatacopy( add(message, add(BYTES_ARR_LEN_VAR_BS, encodedFunctionBytesCount)), // address sub(calldatasize(), redstonePayloadByteSize), // offset redstonePayloadByteSize // bytes length to copy ) // Updating free memory pointer mstore( FREE_MEMORY_PTR, add( add(message, add(redstonePayloadByteSize, encodedFunctionBytesCount)), BYTES_ARR_LEN_VAR_BS ) ) } return message; } function _getRedstonePayloadByteSize() private pure returns (uint256) { uint256 calldataNegativeOffset = _extractByteSizeOfUnsignedMetadata(); uint256 dataPackagesCount = _extractDataPackagesCountFromCalldata(calldataNegativeOffset); calldataNegativeOffset += DATA_PACKAGES_COUNT_BS; for (uint256 dataPackageIndex = 0; dataPackageIndex < dataPackagesCount; dataPackageIndex++) { uint256 dataPackageByteSize = _getDataPackageByteSize(calldataNegativeOffset); calldataNegativeOffset += dataPackageByteSize; } return calldataNegativeOffset; } function _prepareReturnValue(bool success, bytes memory result) internal pure returns (bytes memory) { if (!success) { if (result.length == 0) { revert ProxyCalldataFailedWithoutErrMsg(); } else { bool isStringErrorMessage; assembly { let first32BytesOfResult := mload(add(result, BYTES_ARR_LEN_VAR_BS)) isStringErrorMessage := eq(first32BytesOfResult, STRING_ERR_MESSAGE_MASK) } if (isStringErrorMessage) { string memory receivedErrMsg; assembly { receivedErrMsg := add(result, REVERT_MSG_OFFSET) } revert ProxyCalldataFailedWithStringMessage(receivedErrMsg); } else { revert ProxyCalldataFailedWithCustomError(result); } } } return result; } } /** * @title Loanshark's CToken Contract * @notice Abstract base for CTokens * @author Loanshark */ abstract contract CToken is CTokenInterface, ExponentialNoError, TokenErrorReporter, ProxyConnector { constructor() { admin = payable(msg.sender); } /** * @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 */ /* Use Redstone */ bytes memory encodedFunction = abi.encodeWithSelector( ComptrollerInterface.redeemAllowed.selector, address(this), redeemer, redeemTokens ); bytes memory encodedResult = proxyCalldata( address(comptroller), encodedFunction, true ); uint allowed = abi.decode(encodedResult, (uint256)); 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 */ /* Use Redstone */ bytes memory encodedFunction = abi.encodeWithSelector( ComptrollerInterface.borrowAllowed.selector, address(this), borrower, borrowAmount ); bytes memory encodedResult = proxyCalldata( address(comptroller), encodedFunction, true ); uint allowed = abi.decode(encodedResult, (uint256)); 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 */ /* Use Redstone */ bytes memory encodedFunction = abi.encodeWithSelector( ComptrollerInterface.liquidateBorrowAllowed.selector, address(this), address(cTokenCollateral), liquidator, borrower, repayAmount ); bytes memory encodedResult = proxyCalldata( address(comptroller), encodedFunction, true ); uint allowed = abi.decode(encodedResult, (uint)); 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 */ /* Use Redstone */ bytes memory encodedFunction2 = abi.encodeWithSelector( ComptrollerInterface.liquidateCalculateSeizeTokens.selector, address(this), address(cTokenCollateral), actualRepayAmount ); bytes memory encodedResult2 = proxyCalldataView( address(comptroller), encodedFunction2 ); (uint amountSeizeError, uint seizeTokens) = abi.decode(encodedResult2, (uint, uint)); require(amountSeizeError == NO_ERROR, "LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED"); /* Revert if borrower collateral token balance < seizeTokens */ require(cTokenCollateral.balanceOf(borrower) >= seizeTokens, "LIQUIDATE_SEIZE_TOO_MUCH"); // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call if (address(cTokenCollateral) == address(this)) { seizeInternal(address(this), liquidator, borrower, seizeTokens); } else { require(cTokenCollateral.seize(liquidator, borrower, seizeTokens) == NO_ERROR, "token seizure failed"); } /* We emit a LiquidateBorrow event */ emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(cTokenCollateral), seizeTokens); } /** * @notice Transfers collateral tokens (this market) to the liquidator. * @dev Will fail unless called by another cToken during the process of liquidation. * Its absolutely critical to use msg.sender as the borrowed cToken and not a parameter. * @param liquidator The account receiving seized collateral * @param borrower The account having collateral seized * @param seizeTokens The number of cTokens to seize * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function seize(address liquidator, address borrower, uint seizeTokens) override external nonReentrant returns (uint) { seizeInternal(msg.sender, liquidator, borrower, seizeTokens); return NO_ERROR; } /** * @notice Transfers collateral tokens (this market) to the liquidator. * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another CToken. * Its absolutely critical to use msg.sender as the seizer cToken and not a parameter. * @param seizerToken The contract seizing the collateral (i.e. borrowed cToken) * @param liquidator The account receiving seized collateral * @param borrower The account having collateral seized * @param seizeTokens The number of cTokens to seize */ function seizeInternal(address seizerToken, address liquidator, address borrower, uint seizeTokens) internal { /* Fail if seize not allowed */ uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens); if (allowed != 0) { revert LiquidateSeizeComptrollerRejection(allowed); } /* Fail if borrower = liquidator */ if (borrower == liquidator) { revert LiquidateSeizeLiquidatorIsBorrower(); } /* * We calculate the new borrower and liquidator token balances, failing on underflow/overflow: * borrowerTokensNew = accountTokens[borrower] - seizeTokens * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens */ uint protocolSeizeTokens = mul_(seizeTokens, Exp({mantissa: protocolSeizeShareMantissa})); uint liquidatorSeizeTokens = seizeTokens - protocolSeizeTokens; Exp memory exchangeRate = Exp({mantissa: exchangeRateStoredInternal()}); uint protocolSeizeAmount = mul_ScalarTruncate(exchangeRate, protocolSeizeTokens); uint totalReservesNew = totalReserves + protocolSeizeAmount; ///////////////////////// // EFFECTS & INTERACTIONS // (No safe failures beyond this point) /* We write the calculated values into storage */ totalReserves = totalReservesNew; totalSupply = totalSupply - protocolSeizeTokens; accountTokens[borrower] = accountTokens[borrower] - seizeTokens; accountTokens[liquidator] = accountTokens[liquidator] + liquidatorSeizeTokens; /* Emit a Transfer event */ emit Transfer(borrower, liquidator, liquidatorSeizeTokens); emit Transfer(borrower, address(this), protocolSeizeTokens); emit ReservesAdded(address(this), protocolSeizeAmount, totalReservesNew); } /*** Admin Functions ***/ /** * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer. * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer. * @param newPendingAdmin New pending admin. * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function _setPendingAdmin(address payable newPendingAdmin) override external returns (uint) { // Check caller = admin if (msg.sender != admin) { revert SetPendingAdminOwnerCheck(); } // Save current value, if any, for inclusion in log address oldPendingAdmin = pendingAdmin; // Store pendingAdmin with value newPendingAdmin pendingAdmin = newPendingAdmin; // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin) emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin); return NO_ERROR; } /** * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin * @dev Admin function for pending admin to accept role and update admin * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function _acceptAdmin() override external returns (uint) { // Check caller is pendingAdmin and pendingAdmin ??address(0) if (msg.sender != pendingAdmin || msg.sender == address(0)) { revert AcceptAdminPendingAdminCheck(); } // Save current values for inclusion in log address oldAdmin = admin; address oldPendingAdmin = pendingAdmin; // Store admin with value pendingAdmin admin = pendingAdmin; // Clear the pending value pendingAdmin = payable(address(0)); emit NewAdmin(oldAdmin, admin); emit NewPendingAdmin(oldPendingAdmin, pendingAdmin); return NO_ERROR; } /** * @notice Sets a new comptroller for the market * @dev Admin function to set a new comptroller * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function _setComptroller(ComptrollerInterface newComptroller) override public returns (uint) { // Check caller is admin if (msg.sender != admin) { revert SetComptrollerOwnerCheck(); } ComptrollerInterface oldComptroller = comptroller; // Ensure invoke comptroller.isComptroller() returns true require(newComptroller.isComptroller(), "marker method returned false"); // Set market's comptroller to newComptroller comptroller = newComptroller; // Emit NewComptroller(oldComptroller, newComptroller) emit NewComptroller(oldComptroller, newComptroller); return NO_ERROR; } /** * @notice accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh * @dev Admin function to accrue interest and set a new reserve factor * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function _setReserveFactor(uint newReserveFactorMantissa) override external nonReentrant returns (uint) { accrueInterest(); // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to. return _setReserveFactorFresh(newReserveFactorMantissa); } /** * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual) * @dev Admin function to set a new reserve factor * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) { // Check caller is admin if (msg.sender != admin) { revert SetReserveFactorAdminCheck(); } // Verify market's block number equals current block number if (accrualBlockNumber != getBlockNumber()) { revert SetReserveFactorFreshCheck(); } // Check newReserveFactor ??maxReserveFactor if (newReserveFactorMantissa > reserveFactorMaxMantissa) { revert SetReserveFactorBoundsCheck(); } uint oldReserveFactorMantissa = reserveFactorMantissa; reserveFactorMantissa = newReserveFactorMantissa; emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa); return NO_ERROR; } /** * @notice Accrues interest and reduces reserves by transferring from msg.sender * @param addAmount Amount of addition to reserves * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) { accrueInterest(); // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to. _addReservesFresh(addAmount); return NO_ERROR; } /** * @notice Add reserves by transferring from caller * @dev Requires fresh interest accrual * @param addAmount Amount of addition to reserves * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees */ function _addReservesFresh(uint addAmount) internal returns (uint, uint) { // totalReserves + actualAddAmount uint totalReservesNew; uint actualAddAmount; // We fail gracefully unless market's block number equals current block number if (accrualBlockNumber != getBlockNumber()) { revert AddReservesFactorFreshCheck(actualAddAmount); } ///////////////////////// // EFFECTS & INTERACTIONS // (No safe failures beyond this point) /* * We call doTransferIn for the caller and the addAmount * Note: The cToken must handle variations between ERC-20 and ETH underlying. * On success, the cToken holds an additional addAmount of cash. * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred. * it returns the amount actually transferred, in case of a fee. */ actualAddAmount = doTransferIn(msg.sender, addAmount); totalReservesNew = totalReserves + actualAddAmount; // Store reserves[n+1] = reserves[n] + actualAddAmount totalReserves = totalReservesNew; /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */ emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew); /* Return (NO_ERROR, actualAddAmount) */ return (NO_ERROR, actualAddAmount); } /** * @notice Accrues interest and reduces reserves by transferring to admin * @param reduceAmount Amount of reduction to reserves * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function _reduceReserves(uint reduceAmount) override external nonReentrant returns (uint) { accrueInterest(); // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to. return _reduceReservesFresh(reduceAmount); } /** * @notice Reduces reserves by transferring to admin * @dev Requires fresh interest accrual * @param reduceAmount Amount of reduction to reserves * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function _reduceReservesFresh(uint reduceAmount) internal returns (uint) { // totalReserves - reduceAmount uint totalReservesNew; // Check caller is admin if (msg.sender != admin) { revert ReduceReservesAdminCheck(); } // We fail gracefully unless market's block number equals current block number if (accrualBlockNumber != getBlockNumber()) { revert ReduceReservesFreshCheck(); } // Fail gracefully if protocol has insufficient underlying cash if (getCashPrior() < reduceAmount) { revert ReduceReservesCashNotAvailable(); } // Check reduceAmount ??reserves[n] (totalReserves) if (reduceAmount > totalReserves) { revert ReduceReservesCashValidation(); } ///////////////////////// // EFFECTS & INTERACTIONS // (No safe failures beyond this point) totalReservesNew = totalReserves - reduceAmount; // Store reserves[n+1] = reserves[n] - reduceAmount totalReserves = totalReservesNew; // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred. doTransferOut(admin, reduceAmount); emit ReservesReduced(admin, reduceAmount, totalReservesNew); return NO_ERROR; } /** * @notice accrues interest and updates the interest rate model using _setInterestRateModelFresh * @dev Admin function to accrue interest and update the interest rate model * @param newInterestRateModel the new interest rate model to use * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function _setInterestRateModel(InterestRateModel newInterestRateModel) override public returns (uint) { accrueInterest(); // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to. return _setInterestRateModelFresh(newInterestRateModel); } /** * @notice updates the interest rate model (*requires fresh interest accrual) * @dev Admin function to update the interest rate model * @param newInterestRateModel the new interest rate model to use * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal returns (uint) { // Used to store old model for use in the event that is emitted on success InterestRateModel oldInterestRateModel; // Check caller is admin if (msg.sender != admin) { revert SetInterestRateModelOwnerCheck(); } // We fail gracefully unless market's block number equals current block number if (accrualBlockNumber != getBlockNumber()) { revert SetInterestRateModelFreshCheck(); } // Track the market's current interest rate model oldInterestRateModel = interestRateModel; // Ensure invoke newInterestRateModel.isInterestRateModel() returns true require(newInterestRateModel.isInterestRateModel(), "marker method returned false"); // Set the interest rate model to newInterestRateModel interestRateModel = newInterestRateModel; // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel) emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel); return NO_ERROR; } /*** Safe Token ***/ /** * @notice Gets balance of this contract in terms of the underlying * @dev This excludes the value of the current message, if any * @return The quantity of underlying owned by this contract */ function getCashPrior() virtual internal view returns (uint); /** * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee. * This may revert due to insufficient balance or insufficient allowance. */ function doTransferIn(address from, uint amount) virtual internal returns (uint); /** * @dev Performs a transfer out, ideally returning an explanatory error code upon failure rather than reverting. * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract. * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions. */ function doTransferOut(address payable to, uint amount) virtual internal; /*** Reentrancy Guard ***/ /** * @dev Prevents a contract from calling itself, directly or indirectly. */ modifier nonReentrant() { require(_notEntered, "re-entered"); _notEntered = false; _; _notEntered = true; // get a gas-refund post-Istanbul } } // File contracts/CErc20.sol pragma solidity ^0.8.10; interface CompLike { function delegate(address delegatee) external; } /** * @title Loanshark's CErc20 Contract * @notice CTokens which wrap an EIP-20 underlying * @author Loanshark */ 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 { // Creator of the contract is admin during initialization admin = payable(msg.sender); // 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); } } /** * @title Loanshark's CEther Contract * @notice CToken which wraps Ether * @author Loanshark */ contract CEther is CToken { /** * @notice Construct a new CEther 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_ ERC-20 name of this token * @param symbol_ ERC-20 symbol of this token * @param decimals_ ERC-20 decimal precision of this token * @param admin_ Address of the administrator of this token */ constructor(ComptrollerInterface comptroller_, InterestRateModel interestRateModel_, uint initialExchangeRateMantissa_, string memory name_, string memory symbol_, uint8 decimals_, address payable admin_) { // Creator of the contract is admin during initialization admin = payable(msg.sender); initialize(comptroller_, interestRateModel_, initialExchangeRateMantissa_, name_, symbol_, decimals_); // Set the proper admin now that initialization is done admin = admin_; } /*** User Interface ***/ /** * @notice Sender supplies assets into the market and receives cTokens in exchange * @dev Reverts upon any failure */ function mint() external payable { mintInternal(msg.value); } /** * @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) 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) 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) external returns (uint) { borrowInternal(borrowAmount); return NO_ERROR; } /** * @notice Sender repays their own borrow * @dev Reverts upon any failure */ function repayBorrow() external payable { repayBorrowInternal(msg.value); } /** * @notice Sender repays a borrow belonging to borrower * @dev Reverts upon any failure * @param borrower the account with the debt being payed off */ function repayBorrowBehalf(address borrower) external payable { repayBorrowBehalfInternal(borrower, msg.value); } function repayBorrowBehalfExplictAmount(address borrower, uint repayAmount) external payable { repayBorrowBehalfInternal(borrower, repayAmount); } /** * @notice The sender liquidates the borrowers collateral. * The collateral seized is transferred to the liquidator. * @dev Reverts upon any failure * @param borrower The borrower of this cToken to be liquidated * @param cTokenCollateral The market in which to seize collateral from the borrower */ function liquidateBorrow(address borrower, CToken cTokenCollateral) external payable { liquidateBorrowInternal(borrower, msg.value, cTokenCollateral); } /** * @notice The sender adds to reserves. * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function _addReserves() external payable returns (uint) { return _addReservesInternal(msg.value); } /** * @notice Send Ether to CEther to mint */ receive() external payable { mintInternal(msg.value); } /*** Safe Token ***/ /** * @notice Gets balance of this contract in terms of Ether, before this message * @dev This excludes the value of the current message, if any * @return The quantity of Ether owned by this contract */ function getCashPrior() override internal view returns (uint) { return address(this).balance - msg.value; } /** * @notice Perform the actual transfer in, which is a no-op * @param from Address sending the Ether * @param amount Amount of Ether being sent * @return The actual amount of Ether transferred */ function doTransferIn(address from, uint amount) override internal returns (uint) { // Sanity checks require(msg.sender == from, "sender mismatch"); require(msg.value == amount, "value mismatch"); return amount; } function doTransferOut(address payable to, uint amount) virtual override internal { /* Send the Ether, with minimal gas and revert on failure */ to.transfer(amount); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"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"},{"internalType":"address payable","name":"admin_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"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":[],"name":"CalldataMustHaveValidPayload","type":"error"},{"inputs":[],"name":"CalldataOverOrUnderFlow","type":"error"},{"inputs":[],"name":"DataPackageTimestampMustNotBeZero","type":"error"},{"inputs":[],"name":"DataPackageTimestampsMustBeEqual","type":"error"},{"inputs":[],"name":"EachSignerMustProvideTheSameValue","type":"error"},{"inputs":[],"name":"EmptyCalldataPointersArr","type":"error"},{"inputs":[],"name":"IncorrectUnsignedMetadataSize","type":"error"},{"inputs":[{"internalType":"uint256","name":"receivedSignersCount","type":"uint256"},{"internalType":"uint256","name":"requiredSignersCount","type":"uint256"}],"name":"InsufficientNumberOfUniqueSigners","type":"error"},{"inputs":[],"name":"InvalidCalldataPointer","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":"bytes","name":"result","type":"bytes"}],"name":"ProxyCalldataFailedWithCustomError","type":"error"},{"inputs":[{"internalType":"string","name":"message","type":"string"}],"name":"ProxyCalldataFailedWithStringMessage","type":"error"},{"inputs":[],"name":"ProxyCalldataFailedWithoutErrMsg","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":"RedstonePayloadMustHaveAtLeastOneDataPackage","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":"address","name":"receivedSigner","type":"address"}],"name":"SignerNotAuthorised","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":[],"name":"_addReserves","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","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":[],"name":"extractTimestampsAndAssertAllAreEqual","outputs":[{"internalType":"uint256","name":"extractedTimestamp","type":"uint256"}],"stateMutability":"pure","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":"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":"contract CToken","name":"cTokenCollateral","type":"address"}],"name":"liquidateBorrow","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"mint","outputs":[],"stateMutability":"payable","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":[],"name":"repayBorrow","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"borrower","type":"address"}],"name":"repayBorrowBehalf","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"borrower","type":"address"},{"internalType":"uint256","name":"repayAmount","type":"uint256"}],"name":"repayBorrowBehalfExplictAmount","outputs":[],"stateMutability":"payable","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":[],"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"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60806040523480156200001157600080fd5b50604051620043d1380380620043d18339810160408190526200003491620006bd565b60038054610100600160a81b03199081163361010002918216171790556200006187878787878762000094565b600380546001600160a01b0390921661010002610100600160a81b0319909216919091179055506200090e945050505050565b60035461010090046001600160a01b03163314620001055760405162461bcd60e51b8152602060048201526024808201527f6f6e6c792061646d696e206d617920696e697469616c697a6520746865206d616044820152631c9ad95d60e21b60648201526084015b60405180910390fd5b600954158015620001165750600a54155b620001705760405162461bcd60e51b815260206004820152602360248201527f6d61726b6574206d6179206f6e6c7920626520696e697469616c697a6564206f6044820152626e636560e81b6064820152608401620000fc565b600784905583620001dd5760405162461bcd60e51b815260206004820152603060248201527f696e697469616c2065786368616e67652072617465206d75737420626520677260448201526f32b0ba32b9103a3430b7103d32b9379760811b6064820152608401620000fc565b6000620001ea87620002f8565b905080156200023c5760405162461bcd60e51b815260206004820152601a60248201527f73657474696e6720636f6d7074726f6c6c6572206661696c65640000000000006044820152606401620000fc565b43600955670de0b6b3a7640000600a55620002578662000450565b90508015620002b45760405162461bcd60e51b815260206004820152602260248201527f73657474696e6720696e7465726573742072617465206d6f64656c206661696c604482015261195960f21b6064820152608401620000fc565b6001620002c2858262000817565b506002620002d1848262000817565b50506003805460ff90921660ff199283161790556000805490911660011790555050505050565b60035460009061010090046001600160a01b031633146200032c5760405163d219dc1f60e01b815260040160405180910390fd5b60055460408051623f1ee960e11b815290516001600160a01b0392831692851691627e3dd29160048083019260209291908290030181865afa15801562000377573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200039d9190620008e3565b620003eb5760405162461bcd60e51b815260206004820152601c60248201527f6d61726b6572206d6574686f642072657475726e65642066616c7365000000006044820152606401620000fc565b600580546001600160a01b0319166001600160a01b0385811691821790925560408051928416835260208301919091527f7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d91015b60405180910390a150600092915050565b600354600090819061010090046001600160a01b03163314620004865760405163407fded560e01b815260040160405180910390fd5b4360095414620004a957604051630be2a5cb60e11b815260040160405180910390fd5b600660009054906101000a90046001600160a01b03169050826001600160a01b0316632191f92a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000500573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005269190620008e3565b620005745760405162461bcd60e51b815260206004820152601c60248201527f6d61726b6572206d6574686f642072657475726e65642066616c7365000000006044820152606401620000fc565b600680546001600160a01b0319166001600160a01b0385811691821790925560408051928416835260208301919091527fedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f92691016200043f565b6001600160a01b0381168114620005e357600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200060e57600080fd5b81516001600160401b03808211156200062b576200062b620005e6565b604051601f8301601f19908116603f01168101908282118183101715620006565762000656620005e6565b816040528381526020925086838588010111156200067357600080fd5b600091505b8382101562000697578582018301518183018401529082019062000678565b600093810190920192909252949350505050565b8051620006b881620005cd565b919050565b600080600080600080600060e0888a031215620006d957600080fd5b8751620006e681620005cd565b6020890151909750620006f981620005cd565b604089015160608a015191975095506001600160401b03808211156200071e57600080fd5b6200072c8b838c01620005fc565b955060808a01519150808211156200074357600080fd5b50620007528a828b01620005fc565b93505060a088015160ff811681146200076a57600080fd5b91506200077a60c08901620006ab565b905092959891949750929550565b600181811c908216806200079d57607f821691505b602082108103620007be57634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200081257600081815260208120601f850160051c81016020861015620007ed5750805b601f850160051c820191505b818110156200080e57828155600101620007f9565b5050505b505050565b81516001600160401b03811115620008335762000833620005e6565b6200084b8162000844845462000788565b84620007c4565b602080601f8311600181146200088357600084156200086a5750858301515b600019600386901b1c1916600185901b1785556200080e565b600085815260208120601f198616915b82811015620008b45788860151825594840194600190910190840162000893565b5085821015620008d35787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b600060208284031215620008f657600080fd5b815180151581146200090757600080fd5b9392505050565b613ab3806200091e6000396000f3fe6080604052600436106102cd5760003560e01c80638f840ddd11610175578063c37f68e2116100dc578063f2b3abbd11610095578063f8f9da281161006f578063f8f9da281461084a578063fca7820b1461085f578063fcb641471461087f578063fe9c44ae1461088757600080fd5b8063f2b3abbd146107e5578063f3fdb15a14610805578063f851a4401461082557600080fd5b8063c37f68e2146106f7578063c5ebeaec14610737578063db006a7514610757578063dd62ed3e14610777578063e5974619146107bd578063e9c714f2146107d057600080fd5b8063aa5af0fd1161012e578063aa5af0fd14610664578063aae40a2a1461067a578063ae9d70b01461068d578063b2a02ff1146106a2578063b71d1a0c146106c2578063bd6d894d146106e257600080fd5b80638f840ddd146105c457806395d89b41146105da57806395dd9193146105ef57806399d8c1b41461060f578063a6afed951461062f578063a9059cbb1461064457600080fd5b80634576b5db116102345780636752e702116101ed57806370a08231116101c757806370a082311461054657806373acee981461057c5780637cb05b2914610591578063852a12e3146105a457600080fd5b80636752e7021461050057806369ab32501461051b5780636c540baf1461053057600080fd5b80634576b5db1461046d57806347bd37181461048d5780634e4d9fea146104a357806355a547d5146104ab5780635fe3b567146104c0578063601a0bf1146104e057600080fd5b8063182df0f511610286578063182df0f51461039f57806323b872dd146103b457806326782247146103d4578063313ce5671461040c5780633af9e669146104385780633b1d21a21461045857600080fd5b806306fdde03146102e2578063095ea7b31461030d5780631249c58b1461033d578063173b99041461034557806317bfdfbc1461036957806318160ddd1461038957600080fd5b366102dd576102db3461089c565b005b600080fd5b3480156102ee57600080fd5b506102f76108f4565b6040516103049190613556565b60405180910390f35b34801561031957600080fd5b5061032d61032836600461357e565b610982565b6040519015158152602001610304565b6102db6109f2565b34801561035157600080fd5b5061035b60085481565b604051908152602001610304565b34801561037557600080fd5b5061035b6103843660046135aa565b6109fd565b34801561039557600080fd5b5061035b600d5481565b3480156103ab57600080fd5b5061035b610a50565b3480156103c057600080fd5b5061032d6103cf3660046135c7565b610a5f565b3480156103e057600080fd5b506004546103f4906001600160a01b031681565b6040516001600160a01b039091168152602001610304565b34801561041857600080fd5b506003546104269060ff1681565b60405160ff9091168152602001610304565b34801561044457600080fd5b5061035b6104533660046135aa565b610aaf565b34801561046457600080fd5b5061035b610af5565b34801561047957600080fd5b5061035b6104883660046135aa565b610aff565b34801561049957600080fd5b5061035b600b5481565b6102db610c51565b3480156104b757600080fd5b5061035b610c5a565b3480156104cc57600080fd5b506005546103f4906001600160a01b031681565b3480156104ec57600080fd5b5061035b6104fb366004613608565b610d72565b34801561050c57600080fd5b5061035b666379da05b6000081565b34801561052757600080fd5b5061035b600081565b34801561053c57600080fd5b5061035b60095481565b34801561055257600080fd5b5061035b6105613660046135aa565b6001600160a01b03166000908152600e602052604090205490565b34801561058857600080fd5b5061035b610db1565b6102db61059f36600461357e565b610dfb565b3480156105b057600080fd5b5061035b6105bf366004613608565b610e09565b3480156105d057600080fd5b5061035b600c5481565b3480156105e657600080fd5b506102f7610e1c565b3480156105fb57600080fd5b5061035b61060a3660046135aa565b610e29565b34801561061b57600080fd5b506102db61062a3660046136c4565b610e34565b34801561063b57600080fd5b5061035b611081565b34801561065057600080fd5b5061032d61065f36600461357e565b61126e565b34801561067057600080fd5b5061035b600a5481565b6102db610688366004613770565b6112bd565b34801561069957600080fd5b5061035b6112c8565b3480156106ae57600080fd5b5061035b6106bd3660046135c7565b611360565b3480156106ce57600080fd5b5061035b6106dd3660046135aa565b6113af565b3480156106ee57600080fd5b5061035b61143c565b34801561070357600080fd5b506107176107123660046135aa565b61148c565b604080519485526020850193909352918301526060820152608001610304565b34801561074357600080fd5b5061035b610752366004613608565b6114cd565b34801561076357600080fd5b5061035b610772366004613608565b6114d8565b34801561078357600080fd5b5061035b610792366004613770565b6001600160a01b039182166000908152600f6020908152604080832093909416825291909152205490565b6102db6107cb3660046135aa565b6114e3565b3480156107dc57600080fd5b5061035b6114f0565b3480156107f157600080fd5b5061035b6108003660046135aa565b6115f7565b34801561081157600080fd5b506006546103f4906001600160a01b031681565b34801561083157600080fd5b506003546103f49061010090046001600160a01b031681565b34801561085657600080fd5b5061035b61160b565b34801561086b57600080fd5b5061035b61087a366004613608565b61165e565b61035b61169d565b34801561089357600080fd5b5061032d600181565b60005460ff166108c75760405162461bcd60e51b81526004016108be906137a9565b60405180910390fd5b6000805460ff191690556108d9611081565b506108e433826116a8565b506000805460ff19166001179055565b60018054610901906137cd565b80601f016020809104026020016040519081016040528092919081815260200182805461092d906137cd565b801561097a5780601f1061094f5761010080835404028352916020019161097a565b820191906000526020600020905b81548152906001019060200180831161095d57829003601f168201915b505050505081565b336000818152600f602090815260408083206001600160a01b03871680855292528083208590555191929182907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906109de9087815260200190565b60405180910390a360019150505b92915050565b6109fb3461089c565b565b6000805460ff16610a205760405162461bcd60e51b81526004016108be906137a9565b6000805460ff19169055610a32611081565b50610a3c82610e29565b90506000805460ff19166001179055919050565b6000610a5a61185e565b905090565b6000805460ff16610a825760405162461bcd60e51b81526004016108be906137a9565b6000805460ff19168155610a98338686866118c6565b1490506000805460ff191660011790559392505050565b6000806040518060200160405280610ac561143c565b90526001600160a01b0384166000908152600e6020526040902054909150610aee908290611af2565b9392505050565b6000610a5a611b12565b60035460009061010090046001600160a01b03163314610b325760405163d219dc1f60e01b815260040160405180910390fd5b60055460408051623f1ee960e11b815290516001600160a01b0392831692851691627e3dd29160048083019260209291908290030181865afa158015610b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ba09190613801565b610bec5760405162461bcd60e51b815260206004820152601c60248201527f6d61726b6572206d6574686f642072657475726e65642066616c73650000000060448201526064016108be565b600580546001600160a01b0319166001600160a01b0385811691821790925560408051928416835260208301919091527f7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d91015b60405180910390a150600092915050565b6109fb34611b1e565b600080610c65611b6f565b90506000610c7282611c16565b61ffff16905080600003610c9957604051632154bfcf60e21b815260040160405180910390fd5b610ca4600283613839565b915060005b81811015610d6c576000610cbc84611c50565b9050600080610ccc606887613839565b90506000610cda823661384c565b9050803592508265ffffffffffff16600003610d0957604051630336dc9d60e41b815260040160405180910390fd5b87600003610d21578265ffffffffffff169750610d49565b878365ffffffffffff1614610d495760405163d9d1f46560e01b815260040160405180910390fd5b610d538488613839565b9650505050508080610d649061385f565b915050610ca9565b50505090565b6000805460ff16610d955760405162461bcd60e51b81526004016108be906137a9565b6000805460ff19169055610da7611081565b50610a3c82611c84565b6000805460ff16610dd45760405162461bcd60e51b81526004016108be906137a9565b6000805460ff19169055610de6611081565b5050600b546000805460ff1916600117905590565b610e058282611d9f565b5050565b6000610e1482611df1565b506000919050565b60028054610901906137cd565b60006109ec82611e32565b60035461010090046001600160a01b03163314610e9f5760405162461bcd60e51b8152602060048201526024808201527f6f6e6c792061646d696e206d617920696e697469616c697a6520746865206d616044820152631c9ad95d60e21b60648201526084016108be565b600954158015610eaf5750600a54155b610f075760405162461bcd60e51b815260206004820152602360248201527f6d61726b6574206d6179206f6e6c7920626520696e697469616c697a6564206f6044820152626e636560e81b60648201526084016108be565b600784905583610f725760405162461bcd60e51b815260206004820152603060248201527f696e697469616c2065786368616e67652072617465206d75737420626520677260448201526f32b0ba32b9103a3430b7103d32b9379760811b60648201526084016108be565b6000610f7d87610aff565b90508015610fcd5760405162461bcd60e51b815260206004820152601a60248201527f73657474696e6720636f6d7074726f6c6c6572206661696c656400000000000060448201526064016108be565b43600955670de0b6b3a7640000600a55610fe686611e7e565b905080156110415760405162461bcd60e51b815260206004820152602260248201527f73657474696e6720696e7465726573742072617465206d6f64656c206661696c604482015261195960f21b60648201526084016108be565b600161104d85826138c6565b50600261105a84826138c6565b50506003805460ff90921660ff199283161790556000805490911660011790555050505050565b60095460009043908181036110995760009250505090565b60006110a3611b12565b600b54600c54600a546006546040516315f2405360e01b81526004810186905260248101859052604481018490529495509293919290916000916001600160a01b0316906315f2405390606401602060405180830381865afa15801561110d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111319190613986565b905065048c273950008111156111895760405162461bcd60e51b815260206004820152601c60248201527f626f72726f772072617465206973206162737572646c7920686967680000000060448201526064016108be565b6000611195878961384c565b905060006111b160405180602001604052808581525083611ff3565b905060006111bf8288611af2565b905060006111cd8883613839565b905060006111ec6040518060200160405280600854815250848a612024565b905060006111fb85898a612024565b60098e9055600a819055600b849055600c839055604080518d815260208101879052908101829052606081018590529091507f4dec04e750ca11537cabcd8a9eab06494de08da3735bc8871cd41250e190bc049060800160405180910390a160009d505050505050505050505050505090565b6000805460ff166112915760405162461bcd60e51b81526004016108be906137a9565b6000805460ff191681556112a7338086866118c6565b1490506000805460ff1916600117905592915050565b610e05823483612045565b6006546000906001600160a01b031663b81688166112e4611b12565b600b54600c546008546040516001600160e01b031960e087901b16815260048101949094526024840192909252604483015260648201526084015b602060405180830381865afa15801561133c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a5a9190613986565b6000805460ff166113835760405162461bcd60e51b81526004016108be906137a9565b6000805460ff1916905561139933858585612123565b50600080805460ff191660011790559392505050565b60035460009061010090046001600160a01b031633146113e257604051635cb56c2b60e01b815260040160405180910390fd5b600480546001600160a01b038481166001600160a01b031983168117909355604080519190921680825260208201939093527fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a99101610c40565b6000805460ff1661145f5760405162461bcd60e51b81526004016108be906137a9565b6000805460ff19169055611471611081565b5061147a610a50565b90506000805460ff1916600117905590565b6001600160a01b0381166000908152600e602052604081205481908190819081906114b687611e32565b6114be61185e565b93509350935093509193509193565b6000610e148261239b565b6000610e14826123da565b6114ed8134611d9f565b50565b6004546000906001600160a01b03163314158061150b575033155b1561152957604051631ba24f2960e21b815260040160405180910390fd5b60038054600480546001600160a01b03808216610100818102610100600160a81b0319871617968790556001600160a01b031990931690935560408051948390048216808652929095041660208401529290917ff9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc910160405180910390a1600454604080516001600160a01b03808516825290921660208301527fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9910160405180910390a160009250505090565b6000611601611081565b506109ec82611e7e565b6006546000906001600160a01b03166315f24053611627611b12565b600b54600c546040516001600160e01b031960e086901b16815260048101939093526024830191909152604482015260640161131f565b6000805460ff166116815760405162461bcd60e51b81526004016108be906137a9565b6000805460ff19169055611693611081565b50610a3c8261241b565b6000610a5a346124d7565b600554604051634ef4c3e160e01b81526000916001600160a01b031690634ef4c3e1906116dd9030908790879060040161399f565b6020604051808303816000875af11580156116fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117209190613986565b90508015611744576040516349abd4fd60e01b8152600481018290526024016108be565b4360095414611766576040516338d8859760e01b815260040160405180910390fd5b6000604051806020016040528061177b61185e565b90529050600061178b858561252e565b9050600061179982846125c0565b905080600d546117a99190613839565b600d556001600160a01b0386166000908152600e60205260409020546117d0908290613839565b6001600160a01b0387166000908152600e60205260409081902091909155517f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f90611820908890859085906139c3565b60405180910390a16040518181526001600160a01b038716903090600080516020613a5e8339815191529060200160405180910390a3505050505050565b600d5460009080820361187357505060075490565b600061187d611b12565b90506000600c54600b54836118929190613839565b61189c919061384c565b90506000836118b3670de0b6b3a7640000846139e4565b6118bd91906139fb565b95945050505050565b6005546040516317b9b84b60e31b81523060048201526001600160a01b038581166024830152848116604483015260648201849052600092839291169063bdcdc258906084016020604051808303816000875af115801561192b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061194f9190613986565b905080156119735760405163089d427760e11b8152600481018290526024016108be565b836001600160a01b0316856001600160a01b0316036119a557604051638cd22d1960e01b815260040160405180910390fd5b6000856001600160a01b0316876001600160a01b0316036119c957506000196119f1565b506001600160a01b038086166000908152600f60209081526040808320938a16835292905220545b60006119fd858361384c565b6001600160a01b0388166000908152600e602052604081205491925090611a2590879061384c565b6001600160a01b0388166000908152600e602052604081205491925090611a4d908890613839565b6001600160a01b03808b166000908152600e6020526040808220869055918b1681522081905590506000198414611aa7576001600160a01b03808a166000908152600f60209081526040808320938e168352929052208390555b876001600160a01b0316896001600160a01b0316600080516020613a5e83398151915289604051611ada91815260200190565b60405180910390a35060009998505050505050505050565b600080611aff8484611ff3565b9050611b0a816125de565b949350505050565b6000610a5a344761384c565b60005460ff16611b405760405162461bcd60e51b81526004016108be906137a9565b6000805460ff19169055611b52611081565b50611b5e3333836125f6565b50506000805460ff19166001179055565b60006602ed57011e0000601f1936013581161480611ba0576040516373bb264f60e11b815260040160405180910390fd5b60003660291115611bc457604051632bcb7bc560e11b815260040160405180910390fd5b5060281936013560006009611bdf600362ffffff8516613839565b611be99190613839565b905036611bf7600283613839565b1115610aee5760405163c30a7bd760e01b815260040160405180910390fd5b600080611c24602084613839565b905036811115611c4757604051632bcb7bc560e11b815260040160405180910390fd5b36033592915050565b6000806000611c5e8461279f565b9092509050604e611c70826020613839565b611c7a90846139e4565b611b0a9190613839565b600354600090819061010090046001600160a01b03163314611cb957604051630f7e5e6d60e41b815260040160405180910390fd5b4360095414611cdb57604051630dff50cb60e41b815260040160405180910390fd5b82611ce4611b12565b1015611d0357604051633345e99960e01b815260040160405180910390fd5b600c54831115611d26576040516378d2980560e11b815260040160405180910390fd5b82600c54611d34919061384c565b600c819055600354909150611d579061010090046001600160a01b0316846127f6565b7f3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e600360019054906101000a90046001600160a01b03168483604051610c40939291906139c3565b60005460ff16611dc15760405162461bcd60e51b81526004016108be906137a9565b6000805460ff19169055611dd3611081565b50611ddf3383836125f6565b50506000805460ff1916600117905550565b60005460ff16611e135760405162461bcd60e51b81526004016108be906137a9565b6000805460ff19169055611e25611081565b506108e433600083612831565b6001600160a01b038116600090815260106020526040812080548203611e5b5750600092915050565b600a548154600091611e6c916139e4565b9050816001015481611b0a91906139fb565b600354600090819061010090046001600160a01b03163314611eb35760405163407fded560e01b815260040160405180910390fd5b4360095414611ed557604051630be2a5cb60e11b815260040160405180910390fd5b600660009054906101000a90046001600160a01b03169050826001600160a01b0316632191f92a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f4f9190613801565b611f9b5760405162461bcd60e51b815260206004820152601c60248201527f6d61726b6572206d6574686f642072657475726e65642066616c73650000000060448201526064016108be565b600680546001600160a01b0319166001600160a01b0385811691821790925560408051928416835260208301919091527fedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f9269101610c40565b604080516020810190915260008152604051806020016040528061201b856000015185612b1f565b90529392505050565b6000806120318585611ff3565b90506118bd61203f826125de565b84612b2b565b60005460ff166120675760405162461bcd60e51b81526004016108be906137a9565b6000805460ff19169055612079611081565b506000816001600160a01b031663a6afed956040518163ffffffff1660e01b81526004016020604051808303816000875af11580156120bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120e09190613986565b9050801561210457604051633eea49b760e11b8152600481018290526024016108be565b61211033858585612b37565b50506000805460ff191660011790555050565b60055460405163d02f735160e01b81523060048201526001600160a01b0386811660248301528581166044830152848116606483015260848201849052600092169063d02f73519060a4016020604051808303816000875af115801561218d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121b19190613986565b905080156121d5576040516363e00e3360e11b8152600481018290526024016108be565b836001600160a01b0316836001600160a01b03160361220757604051633a94626760e11b815260040160405180910390fd5b6000612228836040518060200160405280666379da05b60000815250612fff565b90506000612236828561384c565b90506000604051806020016040528061224d61185e565b90529050600061225d8285611af2565b9050600081600c5461226f9190613839565b600c819055600d5490915061228590869061384c565b600d556001600160a01b0388166000908152600e60205260409020546122ac90889061384c565b6001600160a01b03808a166000908152600e602052604080822093909355908b16815220546122dc908590613839565b6001600160a01b03808b166000818152600e602052604090819020939093559151908a1690600080516020613a5e8339815191529061231e9088815260200190565b60405180910390a360405185815230906001600160a01b038a1690600080516020613a5e8339815191529060200160405180910390a37fa91e67c5ea634cd43a12c5a482724b03de01e85ca68702a53d0c2f45cb7c1dc5308383604051612387939291906139c3565b60405180910390a150505050505050505050565b60005460ff166123bd5760405162461bcd60e51b81526004016108be906137a9565b6000805460ff191690556123cf611081565b506108e43382613022565b60005460ff166123fc5760405162461bcd60e51b81526004016108be906137a9565b6000805460ff1916905561240e611081565b506108e433826000612831565b60035460009061010090046001600160a01b0316331461244e57604051631205b57b60e11b815260040160405180910390fd5b436009541461247057604051637dfca6b760e11b815260040160405180910390fd5b670de0b6b3a76400008211156124995760405163717220f360e11b815260040160405180910390fd5b600880549083905560408051828152602081018590527faaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f8214609101610c40565b6000805460ff166124fa5760405162461bcd60e51b81526004016108be906137a9565b6000805460ff1916905561250c611081565b50612516826131d2565b5050600090506000805460ff19166001179055919050565b6000336001600160a01b0384161461257a5760405162461bcd60e51b815260206004820152600f60248201526e0e6cadcc8cae440dad2e6dac2e8c6d608b1b60448201526064016108be565b8134146125ba5760405162461bcd60e51b815260206004820152600e60248201526d0ecc2d8eaca40dad2e6dac2e8c6d60931b60448201526064016108be565b50919050565b6000610aee6125d784670de0b6b3a7640000612b1f565b8351613266565b80516000906109ec90670de0b6b3a7640000906139fb565b600554604051631200453160e11b81523060048201526001600160a01b03858116602483015284811660448301526064820184905260009283929116906324008a62906084016020604051808303816000875af115801561265b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061267f9190613986565b905080156126a357604051638c81362d60e01b8152600481018290526024016108be565b43600954146126c55760405163c9021e2f60e01b815260040160405180910390fd5b60006126d085611e32565b9050600060001985146126e357846126e5565b815b905060006126f3888361252e565b90506000612701828561384c565b9050600082600b54612713919061384c565b6001600160a01b038a8116600081815260106020908152604091829020878155600a54600190910155600b8590558151938f168452830191909152810185905260608101849052608081018290529091507f1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a19060a00160405180910390a1509098975050505050505050565b6000808080806127b0604187613839565b905060006127c96127c2602084613839565b3690613272565b8035945090506127da816003613272565b62ffffff9490941697933563ffffffff16965092945050505050565b6040516001600160a01b0383169082156108fc029083906000818181858888f1935050505015801561282c573d6000803e3d6000fd5b505050565b81158061283c575080155b6128a55760405162461bcd60e51b815260206004820152603460248201527f6f6e65206f662072656465656d546f6b656e73496e206f722072656465656d416044820152736d6f756e74496e206d757374206265207a65726f60601b60648201526084016108be565b600060405180602001604052806128ba61185e565b9052905060008084156128db578491506128d48386611af2565b90506128eb565b6128e584846125c0565b91508390505b600063eabe7d9160e01b30888560405160240161290a9392919061399f565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915260055490915060009061295a906001600160a01b031683600161327e565b90506000818060200190518101906129729190613986565b905080156129965760405163480f424760e01b8152600481018290526024016108be565b43600954146129b8576040516397b5cfcd60e01b815260040160405180910390fd5b836129c1611b12565b10156129e0576040516391240a1b60e01b815260040160405180910390fd5b84600d546129ee919061384c565b600d556001600160a01b0389166000908152600e6020526040902054612a1590869061384c565b6001600160a01b038a166000908152600e6020526040902055612a3889856127f6565b60405185815230906001600160a01b038b1690600080516020613a5e8339815191529060200160405180910390a37fe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a929898587604051612a99939291906139c3565b60405180910390a16005546040516351dff98960e01b81523060048201526001600160a01b038b811660248301526044820187905260648201889052909116906351dff98990608401600060405180830381600087803b158015612afc57600080fd5b505af1158015612b10573d6000803e3d6000fd5b50505050505050505050505050565b6000610aee82846139e4565b6000610aee8284613839565b604080513060248201526001600160a01b0383811660448301528681166064830152858116608483015260a48083018690528351808403909101815260c49092019092526020810180516001600160e01b0316632fe3f38f60e11b1790526005549091600091612baa911683600161327e565b9050600081806020019051810190612bc29190613986565b90508015612be657604051630a14d17960e11b8152600481018290526024016108be565b4360095414612c08576040516380965b1b60e01b815260040160405180910390fd5b43846001600160a01b0316636c540baf6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c6b9190613986565b14612c8957604051631046f38d60e31b815260040160405180910390fd5b866001600160a01b0316866001600160a01b031603612cbb57604051631bd1a62160e21b815260040160405180910390fd5b84600003612cdc5760405163d29da7ef60e01b815260040160405180910390fd5b6000198503612cfe57604051635982c5bb60e11b815260040160405180910390fd5b6000612d0b8888886125f6565b9050600063c488847b60e01b308784604051602401612d2c9392919061399f565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152600554909150600090612d7a906001600160a01b031683613312565b905060008082806020019051810190612d939190613a1d565b9150915060008214612e035760405162461bcd60e51b815260206004820152603360248201527f4c49515549444154455f434f4d5054524f4c4c45525f43414c43554c4154455f604482015272105353d5539517d4d152569157d19052531151606a1b60648201526084016108be565b6040516370a0823160e01b81526001600160a01b038c811660048301528291908b16906370a0823190602401602060405180830381865afa158015612e4c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e709190613986565b1015612ebe5760405162461bcd60e51b815260206004820152601860248201527f4c49515549444154455f5345495a455f544f4f5f4d554348000000000000000060448201526064016108be565b306001600160a01b038a1603612edf57612eda308d8d84612123565b612f98565b6000896001600160a01b031663b2a02ff18e8e856040518463ffffffff1660e01b8152600401612f119392919061399f565b6020604051808303816000875af1158015612f30573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f549190613986565b14612f985760405162461bcd60e51b81526020600482015260146024820152731d1bdad95b881cd95a5e9d5c994819985a5b195960621b60448201526064016108be565b604080516001600160a01b038e811682528d811660208301528183018890528b1660608201526080810183905290517f298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb529181900360a00190a1505050505050505050505050565b6000670de0b6b3a7640000613018848460000151612b1f565b610aee91906139fb565b600063da3d454c60e01b3084846040516024016130419392919061399f565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152600554909150600090613091906001600160a01b031683600161327e565b90506000818060200190518101906130a99190613986565b905080156130cd5760405163918db40f60e01b8152600481018290526024016108be565b43600954146130ef57604051630e8d8c6160e21b815260040160405180910390fd5b836130f8611b12565b1015613117576040516348c2588160e01b815260040160405180910390fd5b600061312286611e32565b905060006131308683613839565b9050600086600b546131429190613839565b6001600160a01b0389166000908152601060205260409020838155600a54600190910155600b819055905061317788886127f6565b604080516001600160a01b038a16815260208101899052908101839052606081018290527f13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab809060800160405180910390a15050505050505050565b600080808043600954146131fc576040516338acf79960e01b8152600481018290526024016108be565b613206338661252e565b905080600c546132169190613839565b915081600c819055507fa91e67c5ea634cd43a12c5a482724b03de01e85ca68702a53d0c2f45cb7c1dc5338284604051613252939291906139c3565b60405180910390a160009590945092505050565b6000610aee82846139fb565b6000610aee828461384c565b6060600061328b84613395565b9050600080866001600160a01b0316856132a65760006132a8565b345b846040516132b69190613a41565b60006040518083038185875af1925050503d80600081146132f3576040519150601f19603f3d011682016040523d82523d6000602084013e6132f8565b606091505b50915091506133078282613424565b979650505050505050565b6060600061331f83613395565b9050600080856001600160a01b03168360405161333c9190613a41565b600060405180830381855afa9150503d8060008114613377576040519150601f19603f3d011682016040523d82523d6000602084013e61337c565b606091505b509150915061338b8282613424565b9695505050505050565b805160609060006133a461349b565b905060006133b28284613839565b9050368211156133d557604051632bcb7bc560e11b815260040160405180910390fd5b6060604051905081815285602001848101826020015b818310156134035782518152602092830192016133eb565b50505082833603856020018301379190920181016020016040529392505050565b6060826125ba57815160000361344d57604051632b3ff13d60e11b815260040160405180910390fd5b602082015162461bcd60e51b148015613480576040516301efd04f60e31b815260448401906108be908290600401613556565b8260405163fd36fde360e01b81526004016108be9190613556565b6000806134a6611b6f565b905060006134b382611c16565b61ffff1690506134c4600283613839565b915060005b818110156134fe5760006134dc84611c50565b90506134e88185613839565b93505080806134f69061385f565b9150506134c9565b509092915050565b60005b83811015613521578181015183820152602001613509565b50506000910152565b60008151808452613542816020860160208601613506565b601f01601f19169290920160200192915050565b602081526000610aee602083018461352a565b6001600160a01b03811681146114ed57600080fd5b6000806040838503121561359157600080fd5b823561359c81613569565b946020939093013593505050565b6000602082840312156135bc57600080fd5b8135610aee81613569565b6000806000606084860312156135dc57600080fd5b83356135e781613569565b925060208401356135f781613569565b929592945050506040919091013590565b60006020828403121561361a57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261364857600080fd5b813567ffffffffffffffff8082111561366357613663613621565b604051601f8301601f19908116603f0116810190828211818310171561368b5761368b613621565b816040528381528660208588010111156136a457600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c087890312156136dd57600080fd5b86356136e881613569565b955060208701356136f881613569565b945060408701359350606087013567ffffffffffffffff8082111561371c57600080fd5b6137288a838b01613637565b9450608089013591508082111561373e57600080fd5b5061374b89828a01613637565b92505060a087013560ff8116811461376257600080fd5b809150509295509295509295565b6000806040838503121561378357600080fd5b823561378e81613569565b9150602083013561379e81613569565b809150509250929050565b6020808252600a90820152691c994b595b9d195c995960b21b604082015260600190565b600181811c908216806137e157607f821691505b6020821081036125ba57634e487b7160e01b600052602260045260246000fd5b60006020828403121561381357600080fd5b81518015158114610aee57600080fd5b634e487b7160e01b600052601160045260246000fd5b808201808211156109ec576109ec613823565b818103818111156109ec576109ec613823565b60006001820161387157613871613823565b5060010190565b601f82111561282c57600081815260208120601f850160051c8101602086101561389f5750805b601f850160051c820191505b818110156138be578281556001016138ab565b505050505050565b815167ffffffffffffffff8111156138e0576138e0613621565b6138f4816138ee84546137cd565b84613878565b602080601f83116001811461392957600084156139115750858301515b600019600386901b1c1916600185901b1785556138be565b600085815260208120601f198616915b8281101561395857888601518255948401946001909101908401613939565b50858210156139765787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60006020828403121561399857600080fd5b5051919050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b039390931683526020830191909152604082015260600190565b80820281158282048414176109ec576109ec613823565b600082613a1857634e487b7160e01b600052601260045260246000fd5b500490565b60008060408385031215613a3057600080fd5b505080516020909101519092909150565b60008251613a53818460208701613506565b919091019291505056feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa264697066735822122061ce236ad864ae6dc6f33942e810f5f9735ae223ac2e8c38d33d45a26ba23d6b64736f6c63430008120033000000000000000000000000945cd438038c1b46029aa111d5785c6580ec0d4e0000000000000000000000001f97e1a35b12ab603ca44ad83e66bc2a4cc7169200000000000000000000000000000000000000000000000006f05b59d3b2000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000080000000000000000000000002254957426f17d301df996e1351a82bf79dd99a90000000000000000000000000000000000000000000000000000000000000004634554480000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046345544800000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x6080604052600436106102cd5760003560e01c80638f840ddd11610175578063c37f68e2116100dc578063f2b3abbd11610095578063f8f9da281161006f578063f8f9da281461084a578063fca7820b1461085f578063fcb641471461087f578063fe9c44ae1461088757600080fd5b8063f2b3abbd146107e5578063f3fdb15a14610805578063f851a4401461082557600080fd5b8063c37f68e2146106f7578063c5ebeaec14610737578063db006a7514610757578063dd62ed3e14610777578063e5974619146107bd578063e9c714f2146107d057600080fd5b8063aa5af0fd1161012e578063aa5af0fd14610664578063aae40a2a1461067a578063ae9d70b01461068d578063b2a02ff1146106a2578063b71d1a0c146106c2578063bd6d894d146106e257600080fd5b80638f840ddd146105c457806395d89b41146105da57806395dd9193146105ef57806399d8c1b41461060f578063a6afed951461062f578063a9059cbb1461064457600080fd5b80634576b5db116102345780636752e702116101ed57806370a08231116101c757806370a082311461054657806373acee981461057c5780637cb05b2914610591578063852a12e3146105a457600080fd5b80636752e7021461050057806369ab32501461051b5780636c540baf1461053057600080fd5b80634576b5db1461046d57806347bd37181461048d5780634e4d9fea146104a357806355a547d5146104ab5780635fe3b567146104c0578063601a0bf1146104e057600080fd5b8063182df0f511610286578063182df0f51461039f57806323b872dd146103b457806326782247146103d4578063313ce5671461040c5780633af9e669146104385780633b1d21a21461045857600080fd5b806306fdde03146102e2578063095ea7b31461030d5780631249c58b1461033d578063173b99041461034557806317bfdfbc1461036957806318160ddd1461038957600080fd5b366102dd576102db3461089c565b005b600080fd5b3480156102ee57600080fd5b506102f76108f4565b6040516103049190613556565b60405180910390f35b34801561031957600080fd5b5061032d61032836600461357e565b610982565b6040519015158152602001610304565b6102db6109f2565b34801561035157600080fd5b5061035b60085481565b604051908152602001610304565b34801561037557600080fd5b5061035b6103843660046135aa565b6109fd565b34801561039557600080fd5b5061035b600d5481565b3480156103ab57600080fd5b5061035b610a50565b3480156103c057600080fd5b5061032d6103cf3660046135c7565b610a5f565b3480156103e057600080fd5b506004546103f4906001600160a01b031681565b6040516001600160a01b039091168152602001610304565b34801561041857600080fd5b506003546104269060ff1681565b60405160ff9091168152602001610304565b34801561044457600080fd5b5061035b6104533660046135aa565b610aaf565b34801561046457600080fd5b5061035b610af5565b34801561047957600080fd5b5061035b6104883660046135aa565b610aff565b34801561049957600080fd5b5061035b600b5481565b6102db610c51565b3480156104b757600080fd5b5061035b610c5a565b3480156104cc57600080fd5b506005546103f4906001600160a01b031681565b3480156104ec57600080fd5b5061035b6104fb366004613608565b610d72565b34801561050c57600080fd5b5061035b666379da05b6000081565b34801561052757600080fd5b5061035b600081565b34801561053c57600080fd5b5061035b60095481565b34801561055257600080fd5b5061035b6105613660046135aa565b6001600160a01b03166000908152600e602052604090205490565b34801561058857600080fd5b5061035b610db1565b6102db61059f36600461357e565b610dfb565b3480156105b057600080fd5b5061035b6105bf366004613608565b610e09565b3480156105d057600080fd5b5061035b600c5481565b3480156105e657600080fd5b506102f7610e1c565b3480156105fb57600080fd5b5061035b61060a3660046135aa565b610e29565b34801561061b57600080fd5b506102db61062a3660046136c4565b610e34565b34801561063b57600080fd5b5061035b611081565b34801561065057600080fd5b5061032d61065f36600461357e565b61126e565b34801561067057600080fd5b5061035b600a5481565b6102db610688366004613770565b6112bd565b34801561069957600080fd5b5061035b6112c8565b3480156106ae57600080fd5b5061035b6106bd3660046135c7565b611360565b3480156106ce57600080fd5b5061035b6106dd3660046135aa565b6113af565b3480156106ee57600080fd5b5061035b61143c565b34801561070357600080fd5b506107176107123660046135aa565b61148c565b604080519485526020850193909352918301526060820152608001610304565b34801561074357600080fd5b5061035b610752366004613608565b6114cd565b34801561076357600080fd5b5061035b610772366004613608565b6114d8565b34801561078357600080fd5b5061035b610792366004613770565b6001600160a01b039182166000908152600f6020908152604080832093909416825291909152205490565b6102db6107cb3660046135aa565b6114e3565b3480156107dc57600080fd5b5061035b6114f0565b3480156107f157600080fd5b5061035b6108003660046135aa565b6115f7565b34801561081157600080fd5b506006546103f4906001600160a01b031681565b34801561083157600080fd5b506003546103f49061010090046001600160a01b031681565b34801561085657600080fd5b5061035b61160b565b34801561086b57600080fd5b5061035b61087a366004613608565b61165e565b61035b61169d565b34801561089357600080fd5b5061032d600181565b60005460ff166108c75760405162461bcd60e51b81526004016108be906137a9565b60405180910390fd5b6000805460ff191690556108d9611081565b506108e433826116a8565b506000805460ff19166001179055565b60018054610901906137cd565b80601f016020809104026020016040519081016040528092919081815260200182805461092d906137cd565b801561097a5780601f1061094f5761010080835404028352916020019161097a565b820191906000526020600020905b81548152906001019060200180831161095d57829003601f168201915b505050505081565b336000818152600f602090815260408083206001600160a01b03871680855292528083208590555191929182907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906109de9087815260200190565b60405180910390a360019150505b92915050565b6109fb3461089c565b565b6000805460ff16610a205760405162461bcd60e51b81526004016108be906137a9565b6000805460ff19169055610a32611081565b50610a3c82610e29565b90506000805460ff19166001179055919050565b6000610a5a61185e565b905090565b6000805460ff16610a825760405162461bcd60e51b81526004016108be906137a9565b6000805460ff19168155610a98338686866118c6565b1490506000805460ff191660011790559392505050565b6000806040518060200160405280610ac561143c565b90526001600160a01b0384166000908152600e6020526040902054909150610aee908290611af2565b9392505050565b6000610a5a611b12565b60035460009061010090046001600160a01b03163314610b325760405163d219dc1f60e01b815260040160405180910390fd5b60055460408051623f1ee960e11b815290516001600160a01b0392831692851691627e3dd29160048083019260209291908290030181865afa158015610b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ba09190613801565b610bec5760405162461bcd60e51b815260206004820152601c60248201527f6d61726b6572206d6574686f642072657475726e65642066616c73650000000060448201526064016108be565b600580546001600160a01b0319166001600160a01b0385811691821790925560408051928416835260208301919091527f7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d91015b60405180910390a150600092915050565b6109fb34611b1e565b600080610c65611b6f565b90506000610c7282611c16565b61ffff16905080600003610c9957604051632154bfcf60e21b815260040160405180910390fd5b610ca4600283613839565b915060005b81811015610d6c576000610cbc84611c50565b9050600080610ccc606887613839565b90506000610cda823661384c565b9050803592508265ffffffffffff16600003610d0957604051630336dc9d60e41b815260040160405180910390fd5b87600003610d21578265ffffffffffff169750610d49565b878365ffffffffffff1614610d495760405163d9d1f46560e01b815260040160405180910390fd5b610d538488613839565b9650505050508080610d649061385f565b915050610ca9565b50505090565b6000805460ff16610d955760405162461bcd60e51b81526004016108be906137a9565b6000805460ff19169055610da7611081565b50610a3c82611c84565b6000805460ff16610dd45760405162461bcd60e51b81526004016108be906137a9565b6000805460ff19169055610de6611081565b5050600b546000805460ff1916600117905590565b610e058282611d9f565b5050565b6000610e1482611df1565b506000919050565b60028054610901906137cd565b60006109ec82611e32565b60035461010090046001600160a01b03163314610e9f5760405162461bcd60e51b8152602060048201526024808201527f6f6e6c792061646d696e206d617920696e697469616c697a6520746865206d616044820152631c9ad95d60e21b60648201526084016108be565b600954158015610eaf5750600a54155b610f075760405162461bcd60e51b815260206004820152602360248201527f6d61726b6574206d6179206f6e6c7920626520696e697469616c697a6564206f6044820152626e636560e81b60648201526084016108be565b600784905583610f725760405162461bcd60e51b815260206004820152603060248201527f696e697469616c2065786368616e67652072617465206d75737420626520677260448201526f32b0ba32b9103a3430b7103d32b9379760811b60648201526084016108be565b6000610f7d87610aff565b90508015610fcd5760405162461bcd60e51b815260206004820152601a60248201527f73657474696e6720636f6d7074726f6c6c6572206661696c656400000000000060448201526064016108be565b43600955670de0b6b3a7640000600a55610fe686611e7e565b905080156110415760405162461bcd60e51b815260206004820152602260248201527f73657474696e6720696e7465726573742072617465206d6f64656c206661696c604482015261195960f21b60648201526084016108be565b600161104d85826138c6565b50600261105a84826138c6565b50506003805460ff90921660ff199283161790556000805490911660011790555050505050565b60095460009043908181036110995760009250505090565b60006110a3611b12565b600b54600c54600a546006546040516315f2405360e01b81526004810186905260248101859052604481018490529495509293919290916000916001600160a01b0316906315f2405390606401602060405180830381865afa15801561110d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111319190613986565b905065048c273950008111156111895760405162461bcd60e51b815260206004820152601c60248201527f626f72726f772072617465206973206162737572646c7920686967680000000060448201526064016108be565b6000611195878961384c565b905060006111b160405180602001604052808581525083611ff3565b905060006111bf8288611af2565b905060006111cd8883613839565b905060006111ec6040518060200160405280600854815250848a612024565b905060006111fb85898a612024565b60098e9055600a819055600b849055600c839055604080518d815260208101879052908101829052606081018590529091507f4dec04e750ca11537cabcd8a9eab06494de08da3735bc8871cd41250e190bc049060800160405180910390a160009d505050505050505050505050505090565b6000805460ff166112915760405162461bcd60e51b81526004016108be906137a9565b6000805460ff191681556112a7338086866118c6565b1490506000805460ff1916600117905592915050565b610e05823483612045565b6006546000906001600160a01b031663b81688166112e4611b12565b600b54600c546008546040516001600160e01b031960e087901b16815260048101949094526024840192909252604483015260648201526084015b602060405180830381865afa15801561133c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a5a9190613986565b6000805460ff166113835760405162461bcd60e51b81526004016108be906137a9565b6000805460ff1916905561139933858585612123565b50600080805460ff191660011790559392505050565b60035460009061010090046001600160a01b031633146113e257604051635cb56c2b60e01b815260040160405180910390fd5b600480546001600160a01b038481166001600160a01b031983168117909355604080519190921680825260208201939093527fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a99101610c40565b6000805460ff1661145f5760405162461bcd60e51b81526004016108be906137a9565b6000805460ff19169055611471611081565b5061147a610a50565b90506000805460ff1916600117905590565b6001600160a01b0381166000908152600e602052604081205481908190819081906114b687611e32565b6114be61185e565b93509350935093509193509193565b6000610e148261239b565b6000610e14826123da565b6114ed8134611d9f565b50565b6004546000906001600160a01b03163314158061150b575033155b1561152957604051631ba24f2960e21b815260040160405180910390fd5b60038054600480546001600160a01b03808216610100818102610100600160a81b0319871617968790556001600160a01b031990931690935560408051948390048216808652929095041660208401529290917ff9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc910160405180910390a1600454604080516001600160a01b03808516825290921660208301527fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9910160405180910390a160009250505090565b6000611601611081565b506109ec82611e7e565b6006546000906001600160a01b03166315f24053611627611b12565b600b54600c546040516001600160e01b031960e086901b16815260048101939093526024830191909152604482015260640161131f565b6000805460ff166116815760405162461bcd60e51b81526004016108be906137a9565b6000805460ff19169055611693611081565b50610a3c8261241b565b6000610a5a346124d7565b600554604051634ef4c3e160e01b81526000916001600160a01b031690634ef4c3e1906116dd9030908790879060040161399f565b6020604051808303816000875af11580156116fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117209190613986565b90508015611744576040516349abd4fd60e01b8152600481018290526024016108be565b4360095414611766576040516338d8859760e01b815260040160405180910390fd5b6000604051806020016040528061177b61185e565b90529050600061178b858561252e565b9050600061179982846125c0565b905080600d546117a99190613839565b600d556001600160a01b0386166000908152600e60205260409020546117d0908290613839565b6001600160a01b0387166000908152600e60205260409081902091909155517f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f90611820908890859085906139c3565b60405180910390a16040518181526001600160a01b038716903090600080516020613a5e8339815191529060200160405180910390a3505050505050565b600d5460009080820361187357505060075490565b600061187d611b12565b90506000600c54600b54836118929190613839565b61189c919061384c565b90506000836118b3670de0b6b3a7640000846139e4565b6118bd91906139fb565b95945050505050565b6005546040516317b9b84b60e31b81523060048201526001600160a01b038581166024830152848116604483015260648201849052600092839291169063bdcdc258906084016020604051808303816000875af115801561192b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061194f9190613986565b905080156119735760405163089d427760e11b8152600481018290526024016108be565b836001600160a01b0316856001600160a01b0316036119a557604051638cd22d1960e01b815260040160405180910390fd5b6000856001600160a01b0316876001600160a01b0316036119c957506000196119f1565b506001600160a01b038086166000908152600f60209081526040808320938a16835292905220545b60006119fd858361384c565b6001600160a01b0388166000908152600e602052604081205491925090611a2590879061384c565b6001600160a01b0388166000908152600e602052604081205491925090611a4d908890613839565b6001600160a01b03808b166000908152600e6020526040808220869055918b1681522081905590506000198414611aa7576001600160a01b03808a166000908152600f60209081526040808320938e168352929052208390555b876001600160a01b0316896001600160a01b0316600080516020613a5e83398151915289604051611ada91815260200190565b60405180910390a35060009998505050505050505050565b600080611aff8484611ff3565b9050611b0a816125de565b949350505050565b6000610a5a344761384c565b60005460ff16611b405760405162461bcd60e51b81526004016108be906137a9565b6000805460ff19169055611b52611081565b50611b5e3333836125f6565b50506000805460ff19166001179055565b60006602ed57011e0000601f1936013581161480611ba0576040516373bb264f60e11b815260040160405180910390fd5b60003660291115611bc457604051632bcb7bc560e11b815260040160405180910390fd5b5060281936013560006009611bdf600362ffffff8516613839565b611be99190613839565b905036611bf7600283613839565b1115610aee5760405163c30a7bd760e01b815260040160405180910390fd5b600080611c24602084613839565b905036811115611c4757604051632bcb7bc560e11b815260040160405180910390fd5b36033592915050565b6000806000611c5e8461279f565b9092509050604e611c70826020613839565b611c7a90846139e4565b611b0a9190613839565b600354600090819061010090046001600160a01b03163314611cb957604051630f7e5e6d60e41b815260040160405180910390fd5b4360095414611cdb57604051630dff50cb60e41b815260040160405180910390fd5b82611ce4611b12565b1015611d0357604051633345e99960e01b815260040160405180910390fd5b600c54831115611d26576040516378d2980560e11b815260040160405180910390fd5b82600c54611d34919061384c565b600c819055600354909150611d579061010090046001600160a01b0316846127f6565b7f3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e600360019054906101000a90046001600160a01b03168483604051610c40939291906139c3565b60005460ff16611dc15760405162461bcd60e51b81526004016108be906137a9565b6000805460ff19169055611dd3611081565b50611ddf3383836125f6565b50506000805460ff1916600117905550565b60005460ff16611e135760405162461bcd60e51b81526004016108be906137a9565b6000805460ff19169055611e25611081565b506108e433600083612831565b6001600160a01b038116600090815260106020526040812080548203611e5b5750600092915050565b600a548154600091611e6c916139e4565b9050816001015481611b0a91906139fb565b600354600090819061010090046001600160a01b03163314611eb35760405163407fded560e01b815260040160405180910390fd5b4360095414611ed557604051630be2a5cb60e11b815260040160405180910390fd5b600660009054906101000a90046001600160a01b03169050826001600160a01b0316632191f92a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f4f9190613801565b611f9b5760405162461bcd60e51b815260206004820152601c60248201527f6d61726b6572206d6574686f642072657475726e65642066616c73650000000060448201526064016108be565b600680546001600160a01b0319166001600160a01b0385811691821790925560408051928416835260208301919091527fedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f9269101610c40565b604080516020810190915260008152604051806020016040528061201b856000015185612b1f565b90529392505050565b6000806120318585611ff3565b90506118bd61203f826125de565b84612b2b565b60005460ff166120675760405162461bcd60e51b81526004016108be906137a9565b6000805460ff19169055612079611081565b506000816001600160a01b031663a6afed956040518163ffffffff1660e01b81526004016020604051808303816000875af11580156120bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120e09190613986565b9050801561210457604051633eea49b760e11b8152600481018290526024016108be565b61211033858585612b37565b50506000805460ff191660011790555050565b60055460405163d02f735160e01b81523060048201526001600160a01b0386811660248301528581166044830152848116606483015260848201849052600092169063d02f73519060a4016020604051808303816000875af115801561218d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121b19190613986565b905080156121d5576040516363e00e3360e11b8152600481018290526024016108be565b836001600160a01b0316836001600160a01b03160361220757604051633a94626760e11b815260040160405180910390fd5b6000612228836040518060200160405280666379da05b60000815250612fff565b90506000612236828561384c565b90506000604051806020016040528061224d61185e565b90529050600061225d8285611af2565b9050600081600c5461226f9190613839565b600c819055600d5490915061228590869061384c565b600d556001600160a01b0388166000908152600e60205260409020546122ac90889061384c565b6001600160a01b03808a166000908152600e602052604080822093909355908b16815220546122dc908590613839565b6001600160a01b03808b166000818152600e602052604090819020939093559151908a1690600080516020613a5e8339815191529061231e9088815260200190565b60405180910390a360405185815230906001600160a01b038a1690600080516020613a5e8339815191529060200160405180910390a37fa91e67c5ea634cd43a12c5a482724b03de01e85ca68702a53d0c2f45cb7c1dc5308383604051612387939291906139c3565b60405180910390a150505050505050505050565b60005460ff166123bd5760405162461bcd60e51b81526004016108be906137a9565b6000805460ff191690556123cf611081565b506108e43382613022565b60005460ff166123fc5760405162461bcd60e51b81526004016108be906137a9565b6000805460ff1916905561240e611081565b506108e433826000612831565b60035460009061010090046001600160a01b0316331461244e57604051631205b57b60e11b815260040160405180910390fd5b436009541461247057604051637dfca6b760e11b815260040160405180910390fd5b670de0b6b3a76400008211156124995760405163717220f360e11b815260040160405180910390fd5b600880549083905560408051828152602081018590527faaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f8214609101610c40565b6000805460ff166124fa5760405162461bcd60e51b81526004016108be906137a9565b6000805460ff1916905561250c611081565b50612516826131d2565b5050600090506000805460ff19166001179055919050565b6000336001600160a01b0384161461257a5760405162461bcd60e51b815260206004820152600f60248201526e0e6cadcc8cae440dad2e6dac2e8c6d608b1b60448201526064016108be565b8134146125ba5760405162461bcd60e51b815260206004820152600e60248201526d0ecc2d8eaca40dad2e6dac2e8c6d60931b60448201526064016108be565b50919050565b6000610aee6125d784670de0b6b3a7640000612b1f565b8351613266565b80516000906109ec90670de0b6b3a7640000906139fb565b600554604051631200453160e11b81523060048201526001600160a01b03858116602483015284811660448301526064820184905260009283929116906324008a62906084016020604051808303816000875af115801561265b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061267f9190613986565b905080156126a357604051638c81362d60e01b8152600481018290526024016108be565b43600954146126c55760405163c9021e2f60e01b815260040160405180910390fd5b60006126d085611e32565b9050600060001985146126e357846126e5565b815b905060006126f3888361252e565b90506000612701828561384c565b9050600082600b54612713919061384c565b6001600160a01b038a8116600081815260106020908152604091829020878155600a54600190910155600b8590558151938f168452830191909152810185905260608101849052608081018290529091507f1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a19060a00160405180910390a1509098975050505050505050565b6000808080806127b0604187613839565b905060006127c96127c2602084613839565b3690613272565b8035945090506127da816003613272565b62ffffff9490941697933563ffffffff16965092945050505050565b6040516001600160a01b0383169082156108fc029083906000818181858888f1935050505015801561282c573d6000803e3d6000fd5b505050565b81158061283c575080155b6128a55760405162461bcd60e51b815260206004820152603460248201527f6f6e65206f662072656465656d546f6b656e73496e206f722072656465656d416044820152736d6f756e74496e206d757374206265207a65726f60601b60648201526084016108be565b600060405180602001604052806128ba61185e565b9052905060008084156128db578491506128d48386611af2565b90506128eb565b6128e584846125c0565b91508390505b600063eabe7d9160e01b30888560405160240161290a9392919061399f565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915260055490915060009061295a906001600160a01b031683600161327e565b90506000818060200190518101906129729190613986565b905080156129965760405163480f424760e01b8152600481018290526024016108be565b43600954146129b8576040516397b5cfcd60e01b815260040160405180910390fd5b836129c1611b12565b10156129e0576040516391240a1b60e01b815260040160405180910390fd5b84600d546129ee919061384c565b600d556001600160a01b0389166000908152600e6020526040902054612a1590869061384c565b6001600160a01b038a166000908152600e6020526040902055612a3889856127f6565b60405185815230906001600160a01b038b1690600080516020613a5e8339815191529060200160405180910390a37fe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a929898587604051612a99939291906139c3565b60405180910390a16005546040516351dff98960e01b81523060048201526001600160a01b038b811660248301526044820187905260648201889052909116906351dff98990608401600060405180830381600087803b158015612afc57600080fd5b505af1158015612b10573d6000803e3d6000fd5b50505050505050505050505050565b6000610aee82846139e4565b6000610aee8284613839565b604080513060248201526001600160a01b0383811660448301528681166064830152858116608483015260a48083018690528351808403909101815260c49092019092526020810180516001600160e01b0316632fe3f38f60e11b1790526005549091600091612baa911683600161327e565b9050600081806020019051810190612bc29190613986565b90508015612be657604051630a14d17960e11b8152600481018290526024016108be565b4360095414612c08576040516380965b1b60e01b815260040160405180910390fd5b43846001600160a01b0316636c540baf6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c6b9190613986565b14612c8957604051631046f38d60e31b815260040160405180910390fd5b866001600160a01b0316866001600160a01b031603612cbb57604051631bd1a62160e21b815260040160405180910390fd5b84600003612cdc5760405163d29da7ef60e01b815260040160405180910390fd5b6000198503612cfe57604051635982c5bb60e11b815260040160405180910390fd5b6000612d0b8888886125f6565b9050600063c488847b60e01b308784604051602401612d2c9392919061399f565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152600554909150600090612d7a906001600160a01b031683613312565b905060008082806020019051810190612d939190613a1d565b9150915060008214612e035760405162461bcd60e51b815260206004820152603360248201527f4c49515549444154455f434f4d5054524f4c4c45525f43414c43554c4154455f604482015272105353d5539517d4d152569157d19052531151606a1b60648201526084016108be565b6040516370a0823160e01b81526001600160a01b038c811660048301528291908b16906370a0823190602401602060405180830381865afa158015612e4c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e709190613986565b1015612ebe5760405162461bcd60e51b815260206004820152601860248201527f4c49515549444154455f5345495a455f544f4f5f4d554348000000000000000060448201526064016108be565b306001600160a01b038a1603612edf57612eda308d8d84612123565b612f98565b6000896001600160a01b031663b2a02ff18e8e856040518463ffffffff1660e01b8152600401612f119392919061399f565b6020604051808303816000875af1158015612f30573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f549190613986565b14612f985760405162461bcd60e51b81526020600482015260146024820152731d1bdad95b881cd95a5e9d5c994819985a5b195960621b60448201526064016108be565b604080516001600160a01b038e811682528d811660208301528183018890528b1660608201526080810183905290517f298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb529181900360a00190a1505050505050505050505050565b6000670de0b6b3a7640000613018848460000151612b1f565b610aee91906139fb565b600063da3d454c60e01b3084846040516024016130419392919061399f565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152600554909150600090613091906001600160a01b031683600161327e565b90506000818060200190518101906130a99190613986565b905080156130cd5760405163918db40f60e01b8152600481018290526024016108be565b43600954146130ef57604051630e8d8c6160e21b815260040160405180910390fd5b836130f8611b12565b1015613117576040516348c2588160e01b815260040160405180910390fd5b600061312286611e32565b905060006131308683613839565b9050600086600b546131429190613839565b6001600160a01b0389166000908152601060205260409020838155600a54600190910155600b819055905061317788886127f6565b604080516001600160a01b038a16815260208101899052908101839052606081018290527f13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab809060800160405180910390a15050505050505050565b600080808043600954146131fc576040516338acf79960e01b8152600481018290526024016108be565b613206338661252e565b905080600c546132169190613839565b915081600c819055507fa91e67c5ea634cd43a12c5a482724b03de01e85ca68702a53d0c2f45cb7c1dc5338284604051613252939291906139c3565b60405180910390a160009590945092505050565b6000610aee82846139fb565b6000610aee828461384c565b6060600061328b84613395565b9050600080866001600160a01b0316856132a65760006132a8565b345b846040516132b69190613a41565b60006040518083038185875af1925050503d80600081146132f3576040519150601f19603f3d011682016040523d82523d6000602084013e6132f8565b606091505b50915091506133078282613424565b979650505050505050565b6060600061331f83613395565b9050600080856001600160a01b03168360405161333c9190613a41565b600060405180830381855afa9150503d8060008114613377576040519150601f19603f3d011682016040523d82523d6000602084013e61337c565b606091505b509150915061338b8282613424565b9695505050505050565b805160609060006133a461349b565b905060006133b28284613839565b9050368211156133d557604051632bcb7bc560e11b815260040160405180910390fd5b6060604051905081815285602001848101826020015b818310156134035782518152602092830192016133eb565b50505082833603856020018301379190920181016020016040529392505050565b6060826125ba57815160000361344d57604051632b3ff13d60e11b815260040160405180910390fd5b602082015162461bcd60e51b148015613480576040516301efd04f60e31b815260448401906108be908290600401613556565b8260405163fd36fde360e01b81526004016108be9190613556565b6000806134a6611b6f565b905060006134b382611c16565b61ffff1690506134c4600283613839565b915060005b818110156134fe5760006134dc84611c50565b90506134e88185613839565b93505080806134f69061385f565b9150506134c9565b509092915050565b60005b83811015613521578181015183820152602001613509565b50506000910152565b60008151808452613542816020860160208601613506565b601f01601f19169290920160200192915050565b602081526000610aee602083018461352a565b6001600160a01b03811681146114ed57600080fd5b6000806040838503121561359157600080fd5b823561359c81613569565b946020939093013593505050565b6000602082840312156135bc57600080fd5b8135610aee81613569565b6000806000606084860312156135dc57600080fd5b83356135e781613569565b925060208401356135f781613569565b929592945050506040919091013590565b60006020828403121561361a57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261364857600080fd5b813567ffffffffffffffff8082111561366357613663613621565b604051601f8301601f19908116603f0116810190828211818310171561368b5761368b613621565b816040528381528660208588010111156136a457600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c087890312156136dd57600080fd5b86356136e881613569565b955060208701356136f881613569565b945060408701359350606087013567ffffffffffffffff8082111561371c57600080fd5b6137288a838b01613637565b9450608089013591508082111561373e57600080fd5b5061374b89828a01613637565b92505060a087013560ff8116811461376257600080fd5b809150509295509295509295565b6000806040838503121561378357600080fd5b823561378e81613569565b9150602083013561379e81613569565b809150509250929050565b6020808252600a90820152691c994b595b9d195c995960b21b604082015260600190565b600181811c908216806137e157607f821691505b6020821081036125ba57634e487b7160e01b600052602260045260246000fd5b60006020828403121561381357600080fd5b81518015158114610aee57600080fd5b634e487b7160e01b600052601160045260246000fd5b808201808211156109ec576109ec613823565b818103818111156109ec576109ec613823565b60006001820161387157613871613823565b5060010190565b601f82111561282c57600081815260208120601f850160051c8101602086101561389f5750805b601f850160051c820191505b818110156138be578281556001016138ab565b505050505050565b815167ffffffffffffffff8111156138e0576138e0613621565b6138f4816138ee84546137cd565b84613878565b602080601f83116001811461392957600084156139115750858301515b600019600386901b1c1916600185901b1785556138be565b600085815260208120601f198616915b8281101561395857888601518255948401946001909101908401613939565b50858210156139765787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60006020828403121561399857600080fd5b5051919050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b039390931683526020830191909152604082015260600190565b80820281158282048414176109ec576109ec613823565b600082613a1857634e487b7160e01b600052601260045260246000fd5b500490565b60008060408385031215613a3057600080fd5b505080516020909101519092909150565b60008251613a53818460208701613506565b919091019291505056feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa264697066735822122061ce236ad864ae6dc6f33942e810f5f9735ae223ac2e8c38d33d45a26ba23d6b64736f6c63430008120033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000945cd438038c1b46029aa111d5785c6580ec0d4e0000000000000000000000001f97e1a35b12ab603ca44ad83e66bc2a4cc7169200000000000000000000000000000000000000000000000006f05b59d3b2000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000080000000000000000000000002254957426f17d301df996e1351a82bf79dd99a90000000000000000000000000000000000000000000000000000000000000004634554480000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046345544800000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : comptroller_ (address): 0x945cd438038C1B46029Aa111D5785C6580EC0D4e
Arg [1] : interestRateModel_ (address): 0x1F97e1A35b12ab603ca44ad83e66BC2a4Cc71692
Arg [2] : initialExchangeRateMantissa_ (uint256): 500000000000000000
Arg [3] : name_ (string): cETH
Arg [4] : symbol_ (string): cETH
Arg [5] : decimals_ (uint8): 8
Arg [6] : admin_ (address): 0x2254957426F17D301df996e1351a82BF79dD99A9
-----Encoded View---------------
11 Constructor Arguments found :
Arg [0] : 000000000000000000000000945cd438038c1b46029aa111d5785c6580ec0d4e
Arg [1] : 0000000000000000000000001f97e1a35b12ab603ca44ad83e66bc2a4cc71692
Arg [2] : 00000000000000000000000000000000000000000000000006f05b59d3b20000
Arg [3] : 00000000000000000000000000000000000000000000000000000000000000e0
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000120
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000008
Arg [6] : 0000000000000000000000002254957426f17d301df996e1351a82bf79dd99a9
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000004
Arg [8] : 6345544800000000000000000000000000000000000000000000000000000000
Arg [9] : 0000000000000000000000000000000000000000000000000000000000000004
Arg [10] : 6345544800000000000000000000000000000000000000000000000000000000
Deployed Bytecode Sourcemap
113151:5527:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;117562:23;117575:9;117562:12;:23::i;:::-;113151:5527;;;;;11954:18;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;56440:246;;;;;;;;;;-1:-1:-1;56440:246:0;;;;;:::i;:::-;;:::i;:::-;;;1391:14:1;;1384:22;1366:41;;1354:2;1339:18;56440:246:0;1226:187:1;114511:75:0;;;:::i;13177:33::-;;;;;;;;;;;;;;;;;;;1564:25:1;;;1552:2;1537:18;13177:33:0;1418:177:1;60159:174:0;;;;;;;;;;-1:-1:-1;60159:174:0;;;;;:::i;:::-;;:::i;13822:23::-;;;;;;;;;;;;;;;;62306:120;;;;;;;;;;;;;:::i;55769:192::-;;;;;;;;;;-1:-1:-1;55769:192:0;;;;;:::i;:::-;;:::i;12627:35::-;;;;;;;;;;-1:-1:-1;12627:35:0;;;;-1:-1:-1;;;;;12627:35:0;;;;;;-1:-1:-1;;;;;2493:32:1;;;2475:51;;2463:2;2448:18;12627:35:0;2313:219:1;12150:21:0;;;;;;;;;;-1:-1:-1;12150:21:0;;;;;;;;;;;2709:4:1;2697:17;;;2679:36;;2667:2;2652:18;12150:21:0;2537:184:1;57735:232:0;;;;;;;;;;-1:-1:-1;57735:232:0;;;;;:::i;:::-;;:::i;63626:97::-;;;;;;;;;;;;;:::i;91759:693::-;;;;;;;;;;-1:-1:-1;91759:693:0;;;;;:::i;:::-;;:::i;13586:24::-;;;;;;;;;;;;;;;;116088:89;;;:::i;40509:1448::-;;;;;;;;;;;;;:::i;12753:39::-;;;;;;;;;;-1:-1:-1;12753:39:0;;;;-1:-1:-1;;;;;12753:39:0;;;96756:280;;;;;;;;;;-1:-1:-1;96756:280:0;;;;;:::i;:::-;;:::i;14717:56::-;;;;;;;;;;;;14767:6;14717:56;;8374:33;;;;;;;;;;;;8406:1;8374:33;;13300:30;;;;;;;;;;;;;;;;57358:121;;;;;;;;;;-1:-1:-1;57358:121:0;;;;;:::i;:::-;-1:-1:-1;;;;;57451:20:0;57424:7;57451:20;;;:13;:20;;;;;;;57358:121;59726:142;;;;;;;;;;;;;:::i;116503:160::-;;;;;;:::i;:::-;;:::i;115425:152::-;;;;;;;;;;-1:-1:-1;115425:152:0;;;;;:::i;:::-;;:::i;13716:25::-;;;;;;;;;;;;;;;;12050:20;;;;;;;;;;;;;:::i;60542:144::-;;;;;;;;;;-1:-1:-1;60542:144:0;;;;;:::i;:::-;;:::i;51452:1505::-;;;;;;;;;;-1:-1:-1;51452:1505:0;;;;;:::i;:::-;;:::i;63971:2570::-;;;;;;;;;;;;;:::i;55280:182::-;;;;;;;;;;-1:-1:-1;55280:182:0;;;;;:::i;:::-;;:::i;13451:23::-;;;;;;;;;;;;;;;;117015:166;;;;;;:::i;:::-;;:::i;59387:193::-;;;;;;;;;;;;;:::i;86754:224::-;;;;;;;;;;-1:-1:-1;86754:224:0;;;;;:::i;:::-;;:::i;89946:604::-;;;;;;;;;;-1:-1:-1;89946:604:0;;;;;:::i;:::-;;:::i;61908:148::-;;;;;;;;;;;;;:::i;58313:292::-;;;;;;;;;;-1:-1:-1;58313:292:0;;;;;:::i;:::-;;:::i;:::-;;;;6295:25:1;;;6351:2;6336:18;;6329:34;;;;6379:18;;;6372:34;6437:2;6422:18;;6415:34;6282:3;6267:19;58313:292:0;6064:391:1;115845:132:0;;;;;;;;;;-1:-1:-1;115845:132:0;;;;;:::i;:::-;;:::i;114937:::-;;;;;;;;;;-1:-1:-1;114937:132:0;;;;;:::i;:::-;;:::i;57016:152::-;;;;;;;;;;-1:-1:-1;57016:152:0;;;;;:::i;:::-;-1:-1:-1;;;;;57126:25:0;;;57099:7;57126:25;;;:18;:25;;;;;;;;:34;;;;;;;;;;;;;57016:152;116368:127;;;;;;:::i;:::-;;:::i;90828:706::-;;;;;;;;;;;;;:::i;99069:321::-;;;;;;;;;;-1:-1:-1;99069:321:0;;;;;:::i;:::-;;:::i;12894:42::-;;;;;;;;;;-1:-1:-1;12894:42:0;;;;-1:-1:-1;;;;;12894:42:0;;;12516:28;;;;;;;;;;-1:-1:-1;12516:28:0;;;;;;;-1:-1:-1;;;;;12516:28:0;;;59041:170;;;;;;;;;;;;;:::i;92755:307::-;;;;;;;;;;-1:-1:-1;92755:307:0;;;;;:::i;:::-;;:::i;117340:113::-;;;:::i;14938:36::-;;;;;;;;;;;;14970:4;14938:36;;66811:244;102212:11;;;;102204:34;;;;-1:-1:-1;;;102204:34:0;;;;;;;:::i;:::-;;;;;;;;;102263:5;102249:19;;-1:-1:-1;;102249:19:0;;;66883:16:::1;:14;:16::i;:::-;;67014:33;67024:10;67036;67014:9;:33::i;:::-;-1:-1:-1::0;102291:11:0;:18;;-1:-1:-1;;102291:18:0;102305:4;102291:18;;;66811:244::o;11954:18::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;56440:246::-;56548:10;56517:4;56569:23;;;:18;:23;;;;;;;;-1:-1:-1;;;;;56569:32:0;;;;;;;;;;:41;;;56626:30;56517:4;;56548:10;;;56626:30;;;;56604:6;1564:25:1;;1552:2;1537:18;;1418:177;56626:30:0;;;;;;;;56674:4;56667:11;;;56440:246;;;;;:::o;114511:75::-;114555:23;114568:9;114555:12;:23::i;:::-;114511:75::o;60159:174::-;60246:4;102212:11;;;;102204:34;;;;-1:-1:-1;;;102204:34:0;;;;;;;:::i;:::-;102263:5;102249:19;;-1:-1:-1;;102249:19:0;;;60263:16:::1;:14;:16::i;:::-;;60297:28;60317:7;60297:19;:28::i;:::-;60290:35;;102291:11:::0;:18;;-1:-1:-1;;102291:18:0;102305:4;102291:18;;;60159:174;;-1:-1:-1;60159:174:0:o;62306:120::-;62366:4;62390:28;:26;:28::i;:::-;62383:35;;62306:120;:::o;55769:192::-;55873:4;102212:11;;;;102204:34;;;;-1:-1:-1;;;102204:34:0;;;;;;;:::i;:::-;102263:5;102249:19;;-1:-1:-1;;102249:19:0;;;55897:44:::1;55912:10;55924:3:::0;55929;55934:6;55897:14:::1;:44::i;:::-;:56;55890:63;;102291:11:::0;:18;;-1:-1:-1;;102291:18:0;102305:4;102291:18;;;55769:192;;-1:-1:-1;;;55769:192:0:o;57735:232::-;57806:4;57823:23;57849:38;;;;;;;;57864:21;:19;:21::i;:::-;57849:38;;-1:-1:-1;;;;;57938:20:0;;;;;;:13;:20;;;;;;57823:64;;-1:-1:-1;57905:54:0;;57823:64;;57905:18;:54::i;:::-;57898:61;57735:232;-1:-1:-1;;;57735:232:0:o;63626:97::-;63677:4;63701:14;:12;:14::i;91759:693::-;91915:5;;91846:4;;91915:5;;;-1:-1:-1;;;;;91915:5:0;91901:10;:19;91897:85;;91944:26;;-1:-1:-1;;;91944:26:0;;;;;;;;;;;91897:85;92032:11;;92129:30;;;-1:-1:-1;;;92129:30:0;;;;-1:-1:-1;;;;;92032:11:0;;;;92129:28;;;;;:30;;;;;;;;;;;;;;:28;:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;92121:71;;;;-1:-1:-1;;;92121:71:0;;8571:2:1;92121:71:0;;;8553:21:1;8610:2;8590:18;;;8583:30;8649;8629:18;;;8622:58;8697:18;;92121:71:0;8369:352:1;92121:71:0;92260:11;:28;;-1:-1:-1;;;;;;92260:28:0;-1:-1:-1;;;;;92260:28:0;;;;;;;;;92370:46;;;9012:15:1;;;8994:34;;9059:2;9044:18;;9037:43;;;;92370:46:0;;8929:18:1;92370:46:0;;;;;;;;-1:-1:-1;8406:1:0;;91759:693;-1:-1:-1;;91759:693:0:o;116088:89::-;116139:30;116159:9;116139:19;:30::i;40509:1448::-;40579:26;40614:30;40647:36;:34;:36::i;:::-;40614:69;;40690:25;40718:61;40756:22;40718:37;:61::i;:::-;40690:89;;;;40792:17;40813:1;40792:22;40788:98;;40832:46;;-1:-1:-1;;;40832:46:0;;;;;;;;;;;40788:98;40894:48;31917:1;40894:48;;:::i;:::-;;;40954:24;40949:1003;41003:17;40984:16;:36;40949:1003;;;41051:27;41081:47;41105:22;41081:23;:47::i;:::-;41051:77;-1:-1:-1;41199:27:0;;41312:88;32569:3;41312:22;:88;:::i;:::-;41277:124;-1:-1:-1;41410:23:0;41436:41;41277:124;41436:8;:41;:::i;:::-;41410:67;;41543:15;41530:29;41506:53;;41582:20;:25;;41606:1;41582:25;41578:94;;41627:35;;-1:-1:-1;;;41627:35:0;;;;;;;;;;;41578:94;41686:18;41708:1;41686:23;41682:207;;41743:20;41722:41;;;;41682:207;;;41807:18;41783:20;:42;;;41779:110;;41845:34;;-1:-1:-1;;;41845:34:0;;;;;;;;;;;41779:110;41899:45;41925:19;41899:45;;:::i;:::-;;;41042:910;;;;41022:18;;;;;:::i;:::-;;;;40949:1003;;;;40607:1350;;40509:1448;:::o;96756:280::-;96840:4;102212:11;;;;102204:34;;;;-1:-1:-1;;;102204:34:0;;;;;;;:::i;:::-;102263:5;102249:19;;-1:-1:-1;;102249:19:0;;;96857:16:::1;:14;:16::i;:::-;;96994:34;97015:12;96994:20;:34::i;59726:142::-:0;59797:4;102212:11;;;;102204:34;;;;-1:-1:-1;;;102204:34:0;;;;;;;:::i;:::-;102263:5;102249:19;;-1:-1:-1;;102249:19:0;;;59814:16:::1;:14;:16::i;:::-;-1:-1:-1::0;;59848:12:0::1;::::0;102291:11;:18;;-1:-1:-1;;102291:18:0;102305:4;102291:18;;;59726:142;:::o;116503:160::-;116607:48;116633:8;116643:11;116607:25;:48::i;:::-;116503:160;;:::o;115425:152::-;115488:4;115505:38;115530:12;115505:24;:38::i;:::-;-1:-1:-1;8406:1:0;;115425:152;-1:-1:-1;115425:152:0:o;12050:20::-;;;;;;;:::i;60542:144::-;60618:4;60642:36;60670:7;60642:27;:36::i;51452:1505::-;51806:5;;;;;-1:-1:-1;;;;;51806:5:0;51792:10;:19;51784:68;;;;-1:-1:-1;;;51784:68:0;;9828:2:1;51784:68:0;;;9810:21:1;9867:2;9847:18;;;9840:30;9906:34;9886:18;;;9879:62;-1:-1:-1;;;9957:18:1;;;9950:34;10001:19;;51784:68:0;9626:400:1;51784:68:0;51871:18;;:23;:43;;;;-1:-1:-1;51898:11:0;;:16;51871:43;51863:91;;;;-1:-1:-1;;;51863:91:0;;10233:2:1;51863:91:0;;;10215:21:1;10272:2;10252:18;;;10245:30;10311:34;10291:18;;;10284:62;-1:-1:-1;;;10362:18:1;;;10355:33;10405:19;;51863:91:0;10031:399:1;51863:91:0;52005:27;:58;;;52082:31;52074:92;;;;-1:-1:-1;;;52074:92:0;;10637:2:1;52074:92:0;;;10619:21:1;10676:2;10656:18;;;10649:30;10715:34;10695:18;;;10688:62;-1:-1:-1;;;10766:18:1;;;10759:46;10822:19;;52074:92:0;10435:412:1;52074:92:0;52211:8;52222:29;52238:12;52222:15;:29::i;:::-;52211:40;-1:-1:-1;52270:15:0;;52262:54;;;;-1:-1:-1;;;52262:54:0;;11054:2:1;52262:54:0;;;11036:21:1;11093:2;11073:18;;;11066:30;11132:28;11112:18;;;11105:56;11178:18;;52262:54:0;10852:350:1;52262:54:0;58845:12;52435:18;:37;25286:4;52483:11;:25;52608:46;52635:18;52608:26;:46::i;:::-;52602:52;-1:-1:-1;52673:15:0;;52665:62;;;;-1:-1:-1;;;52665:62:0;;11409:2:1;52665:62:0;;;11391:21:1;11448:2;11428:18;;;11421:30;11487:34;11467:18;;;11460:62;-1:-1:-1;;;11538:18:1;;;11531:32;11580:19;;52665:62:0;11207:398:1;52665:62:0;52740:4;:12;52747:5;52740:4;:12;:::i;:::-;-1:-1:-1;52763:6:0;:16;52772:7;52763:6;:16;:::i;:::-;-1:-1:-1;;52790:8:0;:20;;;;;;-1:-1:-1;;52790:20:0;;;;;;:8;52931:18;;;;;52790:20;52931:18;;;-1:-1:-1;;;;;51452:1505:0:o;63971:2570::-;64180:18;;64030:4;;58845:12;;64268:45;;;64264:93;;8406:1;64330:15;;;;63971:2570;:::o;64264:93::-;64424:14;64441;:12;:14::i;:::-;64486:12;;64530:13;;64578:11;;64686:17;;:71;;-1:-1:-1;;;64686:71:0;;;;;14016:25:1;;;14057:18;;;14050:34;;;14100:18;;;14093:34;;;64424:31:0;;-1:-1:-1;64486:12:0;;64530:13;;64578:11;;64466:17;;-1:-1:-1;;;;;64686:17:0;;:31;;13989:18:1;;64686:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;64660:97;;12297:9;64776:18;:43;;64768:84;;;;-1:-1:-1;;;64768:84:0;;14529:2:1;64768:84:0;;;14511:21:1;14568:2;14548:18;;;14541:30;14607;14587:18;;;14580:58;14655:18;;64768:84:0;14327:352:1;64768:84:0;64942:15;64960:44;64981:23;64960:18;:44;:::i;:::-;64942:62;;65496:31;65530:53;65535:35;;;;;;;;65550:18;65535:35;;;65572:10;65530:4;:53::i;:::-;65496:87;;65594:24;65621:54;65640:20;65662:12;65621:18;:54::i;:::-;65594:81;-1:-1:-1;65686:20:0;65709:34;65731:12;65594:81;65709:34;:::i;:::-;65686:57;;65754:21;65778:101;65804:38;;;;;;;;65819:21;;65804:38;;;65844:19;65865:13;65778:25;:101::i;:::-;65754:125;;65890:19;65912:83;65938:20;65960:16;65978;65912:25;:83::i;:::-;66199:18;:39;;;66249:11;:28;;;66288:12;:30;;;66329:13;:32;;;66426:79;;;6295:25:1;;;6351:2;6336:18;;6329:34;;;6379:18;;;6372:34;;;6437:2;6422:18;;6415:34;;;66249:28:0;;-1:-1:-1;66426:79:0;;6282:3:1;6267:19;66426:79:0;;;;;;;8406:1;66518:15;;;;;;;;;;;;;;;63971:2570;:::o;55280:182::-;55367:4;102212:11;;;;102204:34;;;;-1:-1:-1;;;102204:34:0;;;;;;;:::i;:::-;102263:5;102249:19;;-1:-1:-1;;102249:19:0;;;55391:51:::1;55406:10;::::0;55430:3;55435:6;55391:14:::1;:51::i;:::-;:63;55384:70;;102291:11:::0;:18;;-1:-1:-1;;102291:18:0;102305:4;102291:18;;;55280:182;;-1:-1:-1;;55280:182:0:o;117015:166::-;117111:62;117135:8;117145:9;117156:16;117111:23;:62::i;59387:193::-;59473:17;;59449:4;;-1:-1:-1;;;;;59473:17:0;:31;59505:14;:12;:14::i;:::-;59521:12;;59535:13;;59550:21;;59473:99;;-1:-1:-1;;;;;;59473:99:0;;;;;;;;;;6295:25:1;;;;6336:18;;;6329:34;;;;6379:18;;;6372:34;6422:18;;;6415:34;6267:19;;59473:99:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;86754:224::-;86865:4;102212:11;;;;102204:34;;;;-1:-1:-1;;;102204:34:0;;;;;;;:::i;:::-;102263:5;102249:19;;-1:-1:-1;;102249:19:0;;;86882:60:::1;86896:10;86908::::0;86920:8;86930:11;86882:13:::1;:60::i;:::-;-1:-1:-1::0;8406:1:0::1;102291:11:::0;:18;;-1:-1:-1;;102291:18:0;102305:4;102291:18;;;86754:224;;-1:-1:-1;;;86754:224:0:o;89946:604::-;90100:5;;90032:4;;90100:5;;;-1:-1:-1;;;;;90100:5:0;90086:10;:19;90082:86;;90129:27;;-1:-1:-1;;;90129:27:0;;;;;;;;;;;90082:86;90267:12;;;-1:-1:-1;;;;;90350:30:0;;;-1:-1:-1;;;;;;90350:30:0;;;;;;;90465:49;;;90267:12;;;;8994:34:1;;;9059:2;9044:18;;9037:43;;;;90465:49:0;;8929:18:1;90465:49:0;8726:360:1;61908:148:0;61977:4;102212:11;;;;102204:34;;;;-1:-1:-1;;;102204:34:0;;;;;;;:::i;:::-;102263:5;102249:19;;-1:-1:-1;;102249:19:0;;;61994:16:::1;:14;:16::i;:::-;;62028:20;:18;:20::i;:::-;62021:27;;102291:11:::0;:18;;-1:-1:-1;;102291:18:0;102305:4;102291:18;;;61908:148;:::o;58313:292::-;-1:-1:-1;;;;;58470:22:0;;58390:4;58470:22;;;:13;:22;;;;;;58390:4;;;;;;;;58507:36;58484:7;58507:27;:36::i;:::-;58558:28;:26;:28::i;:::-;58425:172;;;;;;;;58313:292;;;;;:::o;115845:132::-;115898:4;115915:28;115930:12;115915:14;:28::i;114937:132::-;114990:4;115007:28;115022:12;115007:14;:28::i;116368:127::-;116441:46;116467:8;116477:9;116441:25;:46::i;:::-;116368:127;:::o;90828:706::-;90985:12;;90879:4;;-1:-1:-1;;;;;90985:12:0;90971:10;:26;;;:54;;-1:-1:-1;91001:10:0;:24;90971:54;90967:124;;;91049:30;;-1:-1:-1;;;91049:30:0;;;;;;;;;;;90967:124;91175:5;;;91217:12;;;-1:-1:-1;;;;;91217:12:0;;;91175:5;91290:20;;;-1:-1:-1;;;;;;91290:20:0;;;;;;;-1:-1:-1;;;;;;91359:34:0;;;;;;91411:25;;;91175:5;;;;;;8994:34:1;;;91430:5:0;;;;;9059:2:1;9044:18;;9037:43;91175:5:0;91217:12;;91411:25;;8929:18:1;91411:25:0;;;;;;;91485:12;;91452:46;;;-1:-1:-1;;;;;9012:15:1;;;8994:34;;91485:12:0;;;9059:2:1;9044:18;;9037:43;91452:46:0;;8929:18:1;91452:46:0;;;;;;;8406:1;91511:15;;;;90828:706;:::o;99069:321::-;99165:4;99182:16;:14;:16::i;:::-;;99334:48;99361:20;99334:26;:48::i;59041:170::-;59127:17;;59103:4;;-1:-1:-1;;;;;59127:17:0;:31;59159:14;:12;:14::i;:::-;59175:12;;59189:13;;59127:76;;-1:-1:-1;;;;;;59127:76:0;;;;;;;;;;14016:25:1;;;;14057:18;;;14050:34;;;;14100:18;;;14093:34;13989:18;;59127:76:0;13814:319:1;92755:307:0;92853:4;102212:11;;;;102204:34;;;;-1:-1:-1;;;102204:34:0;;;;;;;:::i;:::-;102263:5;102249:19;;-1:-1:-1;;102249:19:0;;;92870:16:::1;:14;:16::i;:::-;;93006:48;93029:24;93006:22;:48::i;117340:113::-:0;117390:4;117414:31;117435:9;117414:20;:31::i;67396:2215::-;67523:11;;:58;;-1:-1:-1;;;67523:58:0;;67508:12;;-1:-1:-1;;;;;67523:11:0;;:23;;:58;;67555:4;;67562:6;;67570:10;;67523:58;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;67508:73;-1:-1:-1;67596:12:0;;67592:85;;67632:33;;-1:-1:-1;;;67632:33:0;;;;;1564:25:1;;;1537:18;;67632:33:0;1418:177:1;67592:85:0;58845:12;67765:18;;:38;67761:98;;67827:20;;-1:-1:-1;;;67827:20:0;;;;;;;;;;;67761:98;67871:23;67897:45;;;;;;;;67912:28;:26;:28::i;:::-;67897:45;;67871:71;-1:-1:-1;68551:21:0;68575:32;68588:6;68596:10;68575:12;:32::i;:::-;68551:56;;68800:15;68818:36;68823:16;68841:12;68818:4;:36::i;:::-;68800:54;;69188:10;69174:11;;:24;;;;:::i;:::-;69160:11;:38;-1:-1:-1;;;;;69233:21:0;;;;;;:13;:21;;;;;;:34;;69257:10;;69233:34;:::i;:::-;-1:-1:-1;;;;;69209:21:0;;;;;;:13;:21;;;;;;;:58;;;;69343:42;;;;;69223:6;;69356:16;;69374:10;;69343:42;:::i;:::-;;;;;;;;69401:43;;1564:25:1;;;-1:-1:-1;;;;;69401:43:0;;;69418:4;;-1:-1:-1;;;;;;;;;;;69401:43:0;1552:2:1;1537:18;69401:43:0;;;;;;;67457:2154;;;;67396:2215;;:::o;62676:780::-;62782:11;;62745:4;;62808:17;;;62804:645;;-1:-1:-1;;62981:27:0;;;62676:780::o;62804:645::-;63190:14;63207;:12;:14::i;:::-;63190:31;;63236:33;63299:13;;63284:12;;63272:9;:24;;;;:::i;:::-;:40;;;;:::i;:::-;63236:76;-1:-1:-1;63327:17:0;63389:12;63347:39;25286:4;63236:76;63347:39;:::i;:::-;:54;;;;:::i;:::-;63327:74;62676:780;-1:-1:-1;;;;;62676:780:0:o;53423:1596::-;53597:11;;:60;;-1:-1:-1;;;53597:60:0;;53633:4;53597:60;;;16395:34:1;-1:-1:-1;;;;;16465:15:1;;;16445:18;;;16438:43;16517:15;;;16497:18;;;16490:43;16549:18;;;16542:34;;;53521:4:0;;;;53597:11;;;:27;;16329:19:1;;53597:60:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;53582:75;-1:-1:-1;53672:12:0;;53668:89;;53708:37;;-1:-1:-1;;;53708:37:0;;;;;1564:25:1;;;1537:18;;53708:37:0;1418:177:1;53668:89:0;53823:3;-1:-1:-1;;;;;53816:10:0;:3;-1:-1:-1;;;;;53816:10:0;;53812:70;;53850:20;;-1:-1:-1;;;53850:20:0;;;;;;;;;;;53812:70;53959:22;54011:3;-1:-1:-1;;;;;54000:14:0;:7;-1:-1:-1;;;;;54000:14:0;;53996:166;;-1:-1:-1;;;53996:166:0;;;-1:-1:-1;;;;;;54118:23:0;;;;;;;:18;:23;;;;;;;;:32;;;;;;;;;;53996:166;54240:17;54260:26;54280:6;54260:17;:26;:::i;:::-;-1:-1:-1;;;;;54317:18:0;;54297:17;54317:18;;;:13;:18;;;;;;54240:46;;-1:-1:-1;54297:17:0;54317:27;;54338:6;;54317:27;:::i;:::-;-1:-1:-1;;;;;54375:18:0;;54355:17;54375:18;;;:13;:18;;;;;;54297:47;;-1:-1:-1;54355:17:0;54375:27;;54396:6;;54375:27;:::i;:::-;-1:-1:-1;;;;;54536:18:0;;;;;;;:13;:18;;;;;;:33;;;54580:18;;;;;;:33;;;54355:47;-1:-1:-1;;;54686:35:0;;54682:115;;-1:-1:-1;;;;;54738:23:0;;;;;;;:18;:23;;;;;;;;:32;;;;;;;;;:47;;;54682:115;54868:3;-1:-1:-1;;;;;54854:26:0;54863:3;-1:-1:-1;;;;;54854:26:0;-1:-1:-1;;;;;;;;;;;54873:6:0;54854:26;;;;1564:25:1;;1552:2;1537:18;;1418:177;54854:26:0;;;;;;;;-1:-1:-1;8406:1:0;;53423:1596;-1:-1:-1;;;;;;;;;53423:1596:0:o;26008:174::-;26086:4;26103:18;26124:15;26129:1;26132:6;26124:4;:15::i;:::-;26103:36;;26157:17;26166:7;26157:8;:17::i;:::-;26150:24;26008:174;-1:-1:-1;;;;26008:174:0:o;117861:121::-;117917:4;117941:33;117965:9;117941:21;:33;:::i;77841:261::-;102212:11;;;;102204:34;;;;-1:-1:-1;;;102204:34:0;;;;;;;:::i;:::-;102263:5;102249:19;;-1:-1:-1;;102249:19:0;;;77921:16:::1;:14;:16::i;:::-;;78041:53;78058:10;78070;78082:11;78041:16;:53::i;:::-;-1:-1:-1::0;;102291:11:0;:18;;-1:-1:-1;;102291:18:0;102305:4;102291:18;;;77841:261::o;42371:1200::-;42440:7;42752:20;-1:-1:-1;;42615:14:0;42611:37;42598:51;42727:46;;42683:99;;42795:83;;42840:30;;-1:-1:-1;;;42840:30:0;;;;;;;;;;;42795:83;42963:31;43048:8;33031:2;43005:58;43001:113;;;43081:25;;-1:-1:-1;;;43081:25:0;;;;;;;;;;;43001:113;-1:-1:-1;;;43193:14:0;43189:61;43166:93;43272:30;32273:1;43305:64;32220:1;43305:64;;;;:::i;:::-;:92;;;;:::i;:::-;43272:125;-1:-1:-1;43458:8:0;43408:47;31917:1;43272:125;43408:47;:::i;:::-;:65;43404:126;;;43491:31;;-1:-1:-1;;;43491:31:0;;;;;;;;;;;43656:540;43773:24;;43858:41;31302:2;43858:22;:41;:::i;:::-;43809:90;-1:-1:-1;43951:8:0;43910:56;;43906:111;;;43984:25;;-1:-1:-1;;;43984:25:0;;;;;;;;;;;43906:111;44089:14;44085:59;44062:91;;43656:540;-1:-1:-1;;43656:540:0:o;41963:402::-;42051:7;42076:23;42108:34;42152:63;42192:22;42152:39;:63::i;:::-;42067:148;;-1:-1:-1;42067:148:0;-1:-1:-1;32725:2:0;42264:49;42067:148;32091:2;42264:49;:::i;:::-;42238:76;;:15;:76;:::i;:::-;:121;;;;:::i;97313:1387::-;97524:5;;97380:4;;;;97524:5;;;-1:-1:-1;;;;;97524:5:0;97510:10;:19;97506:85;;97553:26;;-1:-1:-1;;;97553:26:0;;;;;;;;;;;97506:85;58845:12;97695:18;;:38;97691:104;;97757:26;;-1:-1:-1;;;97757:26:0;;;;;;;;;;;97691:104;97901:12;97884:14;:12;:14::i;:::-;:29;97880:101;;;97937:32;;-1:-1:-1;;;97937:32:0;;;;;;;;;;;97880:101;98073:13;;98058:12;:28;98054:98;;;98110:30;;-1:-1:-1;;;98110:30:0;;;;;;;;;;;98054:98;98320:12;98304:13;;:28;;;;:::i;:::-;98406:13;:32;;;98572:5;;98406:32;;-1:-1:-1;98558:34:0;;98572:5;;;-1:-1:-1;;;;;98572:5:0;98579:12;98558:13;:34::i;:::-;98610:54;98626:5;;;;;;;;;-1:-1:-1;;;;;98626:5:0;98633:12;98647:16;98610:54;;;;;;;;:::i;78341:283::-;102212:11;;;;102204:34;;;;-1:-1:-1;;;102204:34:0;;;;;;;:::i;:::-;102263:5;102249:19;;-1:-1:-1;;102249:19:0;;;78445:16:::1;:14;:16::i;:::-;;78565:51;78582:10;78594:8;78604:11;78565:16;:51::i;:::-;-1:-1:-1::0;;102291:11:0;:18;;-1:-1:-1;;102291:18:0;102305:4;102291:18;;;-1:-1:-1;78341:283:0:o;70408:252::-;102212:11;;;;102204:34;;;;-1:-1:-1;;;102204:34:0;;;;;;;:::i;:::-;102263:5;102249:19;;-1:-1:-1;;102249:19:0;;;70494:16:::1;:14;:16::i;:::-;;70603:49;70623:10;70636:1;70639:12;70603:11;:49::i;60940:813::-:0;-1:-1:-1;;;;;61123:23:0;;61017:4;61123:23;;;:14;:23;;;;;61352:24;;:29;;61348:70;;-1:-1:-1;61405:1:0;;60940:813;-1:-1:-1;;60940:813:0:o;61348:70::-;61666:11;;61639:24;;61612;;61639:38;;;:::i;:::-;61612:65;;61717:14;:28;;;61695:19;:50;;;;:::i;99720:1201::-;100020:5;;99814:4;;;;100020:5;;;-1:-1:-1;;;;;100020:5:0;100006:10;:19;100002:91;;100049:32;;-1:-1:-1;;;100049:32:0;;;;;;;;;;;100002:91;58845:12;100197:18;;:38;100193:110;;100259:32;;-1:-1:-1;;;100259:32:0;;;;;;;;;;;100193:110;100397:17;;;;;;;;;-1:-1:-1;;;;;100397:17:0;100374:40;;100517:20;-1:-1:-1;;;;;100517:40:0;;:42;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;100509:83;;;;-1:-1:-1;;;100509:83:0;;8571:2:1;100509:83:0;;;8553:21:1;8610:2;8590:18;;;8583:30;8649;8629:18;;;8622:58;8697:18;;100509:83:0;8369:352:1;100509:83:0;100669:17;:40;;-1:-1:-1;;;;;;100669:40:0;-1:-1:-1;;;;;100669:40:0;;;;;;;;;100815:70;;;9012:15:1;;;8994:34;;9059:2;9044:18;;9037:43;;;;100815:70:0;;8929:18:1;100815:70:0;8726:360:1;28743:133:0;-1:-1:-1;;;;;;;;;;;;28832:36:0;;;;;;;;28847:19;28852:1;:10;;;28864:1;28847:4;:19::i;:::-;28832:36;;28825:43;28743:133;-1:-1:-1;;;28743:133:0:o;26327:208::-;26425:4;26442:18;26463:15;26468:1;26471:6;26463:4;:15::i;:::-;26442:36;;26496:31;26501:17;26510:7;26501:8;:17::i;:::-;26520:6;26496:4;:31::i;81725:633::-;102212:11;;;;102204:34;;;;-1:-1:-1;;;102204:34:0;;;;;;;:::i;:::-;102263:5;102249:19;;-1:-1:-1;;102249:19:0;;;81861:16:::1;:14;:16::i;:::-;;81890:10;81903:16;-1:-1:-1::0;;;;;81903:31:0::1;;:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;81890:46:::0;-1:-1:-1;81951:17:0;;81947:227:::1;;82116:46;::::0;-1:-1:-1;;;82116:46:0;;::::1;::::0;::::1;1564:25:1::0;;;1537:18;;82116:46:0::1;1418:177:1::0;81947:227:0::1;82277:73;82298:10;82310:8;82320:11;82333:16;82277:20;:73::i;:::-;-1:-1:-1::0;;102291:11:0;:18;;-1:-1:-1;;102291:18:0;102305:4;102291:18;;;-1:-1:-1;;81725:633:0:o;87565:1932::-;87741:11;;:87;;-1:-1:-1;;;87741:87:0;;87774:4;87741:87;;;17601:34:1;-1:-1:-1;;;;;17671:15:1;;;17651:18;;;17644:43;17723:15;;;17703:18;;;17696:43;17775:15;;;17755:18;;;17748:43;17807:19;;;17800:35;;;87726:12:0;;87741:11;;:24;;17535:19:1;;87741:87:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;87726:102;-1:-1:-1;87843:12:0;;87839:95;;87879:43;;-1:-1:-1;;;87879:43:0;;;;;1564:25:1;;;1537:18;;87879:43:0;1418:177:1;87839:95:0;88007:10;-1:-1:-1;;;;;87995:22:0;:8;-1:-1:-1;;;;;87995:22:0;;87991:98;;88041:36;;-1:-1:-1;;;88041:36:0;;;;;;;;;;;87991:98;88376:24;88403:62;88408:11;88421:43;;;;;;;;14767:6;88421:43;;;88403:4;:62::i;:::-;88376:89;-1:-1:-1;88476:26:0;88505:33;88376:89;88505:11;:33;:::i;:::-;88476:62;;88549:23;88575:45;;;;;;;;88590:28;:26;:28::i;:::-;88575:45;;88549:71;-1:-1:-1;88631:24:0;88658:53;88549:71;88691:19;88658:18;:53::i;:::-;88631:80;;88722:21;88762:19;88746:13;;:35;;;;:::i;:::-;88976:13;:32;;;89033:11;;88722:59;;-1:-1:-1;89033:33:0;;89047:19;;89033:33;:::i;:::-;89019:11;:47;-1:-1:-1;;;;;89103:23:0;;;;;;:13;:23;;;;;;:37;;89129:11;;89103:37;:::i;:::-;-1:-1:-1;;;;;89077:23:0;;;;;;;:13;:23;;;;;;:63;;;;89179:25;;;;;;;:49;;89207:21;;89179:49;:::i;:::-;-1:-1:-1;;;;;89151:25:0;;;;;;;:13;:25;;;;;;;:77;;;;89283:53;;;;;;-1:-1:-1;;;;;;;;;;;89283:53:0;;;89314:21;1564:25:1;;1552:2;1537:18;;1418:177;89283:53:0;;;;;;;;89352:54;;1564:25:1;;;89379:4:0;;-1:-1:-1;;;;;89352:54:0;;;-1:-1:-1;;;;;;;;;;;89352:54:0;1552:2:1;1537:18;89352:54:0;;;;;;;89422:67;89444:4;89451:19;89472:16;89422:67;;;;;;;;:::i;:::-;;;;;;;;87674:1823;;;;;;87565:1932;;;;:::o;74761:239::-;102212:11;;;;102204:34;;;;-1:-1:-1;;;102204:34:0;;;;;;;:::i;:::-;102263:5;102249:19;;-1:-1:-1;;102249:19:0;;;74837:16:::1;:14;:16::i;:::-;;74946:46;74966:10;74979:12;74946:11;:46::i;69874:242::-:0;102212:11;;;;102204:34;;;;-1:-1:-1;;;102204:34:0;;;;;;;:::i;:::-;102263:5;102249:19;;-1:-1:-1;;102249:19:0;;;69950:16:::1;:14;:16::i;:::-;;70059:49;70079:10;70092:12;70106:1;70059:11;:49::i;93330:838::-:0;93480:5;;93411:4;;93480:5;;;-1:-1:-1;;;;;93480:5:0;93466:10;:19;93462:87;;93509:28;;-1:-1:-1;;;93509:28:0;;;;;;;;;;;93462:87;58845:12;93634:18;;:38;93630:106;;93696:28;;-1:-1:-1;;;93696:28:0;;;;;;;;;;;93630:106;12437:4;93806:24;:51;93802:120;;;93881:29;;-1:-1:-1;;;93881:29:0;;;;;;;;;;;93802:120;93966:21;;;93998:48;;;;94064:68;;;18020:25:1;;;18076:2;18061:18;;18054:34;;;94064:68:0;;17993:18:1;94064:68:0;17846:248:1;94424:284:0;94501:4;102212:11;;;;102204:34;;;;-1:-1:-1;;;102204:34:0;;;;;;;:::i;:::-;102263:5;102249:19;;-1:-1:-1;;102249:19:0;;;94518:16:::1;:14;:16::i;:::-;;94646:28;94664:9;94646:17;:28::i;:::-;;;8406:1;94685:15;;102291:11:::0;:18;;-1:-1:-1;;102291:18:0;102305:4;102291:18;;;94424:284;;-1:-1:-1;94424:284:0:o;118223:254::-;118299:4;118350:10;-1:-1:-1;;;;;118350:18:0;;;118342:46;;;;-1:-1:-1;;;118342:46:0;;18301:2:1;118342:46:0;;;18283:21:1;18340:2;18320:18;;;18313:30;-1:-1:-1;;;18359:18:1;;;18352:45;18414:18;;118342:46:0;18099:339:1;118342:46:0;118420:6;118407:9;:19;118399:46;;;;-1:-1:-1;;;118399:46:0;;18645:2:1;118399:46:0;;;18627:21:1;18684:2;18664:18;;;18657:30;-1:-1:-1;;;18703:18:1;;;18696:44;18757:18;;118399:46:0;18443:338:1;118399:46:0;-1:-1:-1;118463:6:0;118223:254;-1:-1:-1;118223:254:0:o;29891:126::-;29950:4;29974:35;29979:17;29984:1;25286:4;29979;:17::i;:::-;29998:10;;29974:4;:35::i;25682:213::-;25864:12;;25739:4;;25864:23;;25286:4;;25864:23;:::i;79012:2319::-;79186:11;;:75;;-1:-1:-1;;;79186:75:0;;79225:4;79186:75;;;16395:34:1;-1:-1:-1;;;;;16465:15:1;;;16445:18;;;16438:43;16517:15;;;16497:18;;;16490:43;16549:18;;;16542:34;;;79107:4:0;;;;79186:11;;;:30;;16329:19:1;;79186:75:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;79171:90;-1:-1:-1;79276:12:0;;79272:92;;79312:40;;-1:-1:-1;;;79312:40:0;;;;;1564:25:1;;;1537:18;;79312:40:0;1418:177:1;79272:92:0;58845:12;79452:18;;:38;79448:105;;79514:27;;-1:-1:-1;;;79514:27:0;;;;;;;;;;;79448:105;79645:23;79671:37;79699:8;79671:27;:37::i;:::-;79645:63;;79787:21;-1:-1:-1;;79811:11:0;:29;:64;;79864:11;79811:64;;;79843:18;79811:64;79787:88;;80449:22;80474:37;80487:5;80494:16;80474:12;:37::i;:::-;80449:62;-1:-1:-1;80772:22:0;80797:38;80449:62;80797:18;:38;:::i;:::-;80772:63;;80846:20;80884:17;80869:12;;:32;;;;:::i;:::-;-1:-1:-1;;;;;80984:24:0;;;;;;;:14;:24;;;;;;;;;:54;;;81090:11;;81049:38;;;;:52;81112:12;:30;;;81203:83;;19101:15:1;;;19083:34;;19133:18;;19126:43;;;;19185:18;;19178:34;;;19243:2;19228:18;;19221:34;;;19286:3;19271:19;;19264:35;;;81112:30:0;;-1:-1:-1;81203:83:0;;19032:3:1;19017:19;81203:83:0;;;;;;;-1:-1:-1;81306:17:0;;79012:2319;-1:-1:-1;;;;;;;;79012:2319:0:o;45023:1053::-;45156:23;;;;;45515:45;31812:2;45515:36;:45;:::i;:::-;45482:78;-1:-1:-1;45567:22:0;45592:62;45612:41;31302:2;45482:78;45612:41;:::i;:::-;45592:8;;:19;:62::i;:::-;45699:28;;;-1:-1:-1;45567:87:0;-1:-1:-1;45802:40:0;45567:87;31972:1;45802:18;:40::i;:::-;45973:34;;;;;;45898:28;;46014:56;;;-1:-1:-1;45973:34:0;;-1:-1:-1;;;;;45023:1053:0:o;118485:190::-;118648:19;;-1:-1:-1;;;;;118648:11:0;;;:19;;;;;118660:6;;118648:19;;;;118660:6;118648:11;:19;;;;;;;;;;;;;;;;;;;;;118485:190;;:::o;71220:3362::-;71337:19;;;:42;;-1:-1:-1;71360:19:0;;71337:42;71329:107;;;;-1:-1:-1;;;71329:107:0;;19512:2:1;71329:107:0;;;19494:21:1;19551:2;19531:18;;;19524:30;19590:34;19570:18;;;19563:62;-1:-1:-1;;;19641:18:1;;;19634:50;19701:19;;71329:107:0;19310:416:1;71329:107:0;71509:23;71535:46;;;;;;;;71550:28;:26;:28::i;:::-;71535:46;;71509:72;-1:-1:-1;71594:17:0;;71692:18;;71688:757;;71983:14;71968:29;;72027:48;72046:12;72060:14;72027:18;:48::i;:::-;72012:63;;71688:757;;;72355:34;72360:14;72376:12;72355:4;:34::i;:::-;72340:49;;72419:14;72404:29;;71688:757;72527:28;72595:43;;;72661:4;72682:8;72706:12;72558:171;;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;72558:171:0;;;;;;;;;;;;;;-1:-1:-1;;;;;72558:171:0;-1:-1:-1;;;;;;72558:171:0;;;;;;;;;;72807:11;;72558:171;;-1:-1:-1;;;72771:108:0;;-1:-1:-1;;;;;72807:11:0;72558:171;72807:11;72771:13;:108::i;:::-;72742:137;;72892:12;72918:13;72907:36;;;;;;;;;;;;:::i;:::-;72892:51;-1:-1:-1;72958:12:0;;72954:87;;72994:35;;-1:-1:-1;;;72994:35:0;;;;;1564:25:1;;;1537:18;;72994:35:0;1418:177:1;72954:87:0;58845:12;73129:18;;:38;73125:100;;73191:22;;-1:-1:-1;;;73191:22:0;;;;;;;;;;;73125:100;73323:12;73306:14;:12;:14::i;:::-;:29;73302:99;;;73359:30;;-1:-1:-1;;;73359:30:0;;;;;;;;;;;73302:99;73759:12;73745:11;;:26;;;;:::i;:::-;73731:11;:40;-1:-1:-1;;;;;73808:23:0;;;;;;:13;:23;;;;;;:38;;73834:12;;73808:38;:::i;:::-;-1:-1:-1;;;;;73782:23:0;;;;;;:13;:23;;;;;:64;74222:37;73796:8;74246:12;74222:13;:37::i;:::-;74337:47;;1564:25:1;;;74364:4:0;;-1:-1:-1;;;;;74337:47:0;;;-1:-1:-1;;;;;;;;;;;74337:47:0;1552:2:1;1537:18;74337:47:0;;;;;;;74400:44;74407:8;74417:12;74431;74400:44;;;;;;;;:::i;:::-;;;;;;;;74497:11;;:77;;-1:-1:-1;;;74497:77:0;;74530:4;74497:77;;;20404:34:1;-1:-1:-1;;;;;20474:15:1;;;20454:18;;;20447:43;20506:18;;;20499:34;;;20549:18;;;20542:34;;;74497:11:0;;;;:24;;20338:19:1;;74497:77:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;71318:3264;;;;;;71220:3362;;;:::o;29480:90::-;29533:4;29557:5;29561:1;29557;:5;:::i;28056:90::-;28109:4;28133:5;28137:1;28133;:5;:::i;82837:3356::-;83081:244;;;83193:4;83081:244;;;17601:34:1;-1:-1:-1;;;;;17671:15:1;;;17651:18;;;17644:43;17723:15;;;17703:18;;;17696:43;17775:15;;;17755:18;;;17748:43;17807:19;;;;17800:35;;;83081:244:0;;;;;;;;;;17535:19:1;;;;83081:244:0;;;;;;;;-1:-1:-1;;;;;83081:244:0;-1:-1:-1;;;83081:244:0;;;83403:11;;83081:244;;-1:-1:-1;;83367:108:0;;83403:11;83081:244;83403:11;83367:13;:108::i;:::-;83338:137;;83488:12;83514:13;83503:33;;;;;;;;;;;;:::i;:::-;83488:48;-1:-1:-1;83553:12:0;;83549:90;;83589:38;;-1:-1:-1;;;83589:38:0;;;;;1564:25:1;;;1537:18;;83589:38:0;1418:177:1;83549:90:0;58845:12;83727:18;;:38;83723:103;;83789:25;;-1:-1:-1;;;83789:25:0;;;;;;;;;;;83723:103;58845:12;83931:16;-1:-1:-1;;;;;83931:35:0;;:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:57;83927:132;;84012:35;;-1:-1:-1;;;84012:35:0;;;;;;;;;;;83927:132;84132:10;-1:-1:-1;;;;;84120:22:0;:8;-1:-1:-1;;;;;84120:22:0;;84116:93;;84166:31;;-1:-1:-1;;;84166:31:0;;;;;;;;;;;84116:93;84264:11;84279:1;84264:16;84260:84;;84304:28;;-1:-1:-1;;;84304:28:0;;;;;;;;;;;84260:84;-1:-1:-1;;84400:11:0;:29;84396:100;;84453:31;;-1:-1:-1;;;84453:31:0;;;;;;;;;;;84396:100;84549:22;84574:51;84591:10;84603:8;84613:11;84574:16;:51::i;:::-;84549:76;;84867:29;84936:59;;;85018:4;85047:16;85080:17;84899:209;;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;84899:209:0;;;;;;;;;;;;;;-1:-1:-1;;;;;84899:209:0;-1:-1:-1;;;;;;84899:209:0;;;;;;;;;;85191:11;;84899:209;;-1:-1:-1;;;85151:94:0;;-1:-1:-1;;;;;85191:11:0;84899:209;85151:17;:94::i;:::-;85121:124;;85259:21;85282:16;85313:14;85302:40;;;;;;;;;;;;:::i;:::-;85258:84;;;;8406:1;85365:16;:28;85357:92;;;;-1:-1:-1;;;85357:92:0;;21039:2:1;85357:92:0;;;21021:21:1;21078:2;21058:18;;;21051:30;21117:34;21097:18;;;21090:62;-1:-1:-1;;;21168:18:1;;;21161:49;21227:19;;85357:92:0;20837:415:1;85357:92:0;85543:36;;-1:-1:-1;;;85543:36:0;;-1:-1:-1;;;;;2493:32:1;;;85543:36:0;;;2475:51:1;85583:11:0;;85543:26;;;;;;2448:18:1;;85543:36:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:51;;85535:88;;;;-1:-1:-1;;;85535:88:0;;21667:2:1;85535:88:0;;;21649:21:1;21706:2;21686:18;;;21679:30;21745:26;21725:18;;;21718:54;21789:18;;85535:88:0;21465:348:1;85535:88:0;85793:4;-1:-1:-1;;;;;85756:42:0;;;85752:273;;85815:63;85837:4;85844:10;85856:8;85866:11;85815:13;:63::i;:::-;85752:273;;;8406:1;85919:16;-1:-1:-1;;;;;85919:22:0;;85942:10;85954:8;85964:11;85919:57;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:69;85911:102;;;;-1:-1:-1;;;85911:102:0;;22020:2:1;85911:102:0;;;22002:21:1;22059:2;22039:18;;;22032:30;-1:-1:-1;;;22078:18:1;;;22071:50;22138:18;;85911:102:0;21818:344:1;85911:102:0;86089:96;;;-1:-1:-1;;;;;22482:15:1;;;22464:34;;22534:15;;;22529:2;22514:18;;22507:43;22566:18;;;22559:34;;;22629:15;;22624:2;22609:18;;22602:43;22676:3;22661:19;;22654:35;;;86089:96:0;;;;;;;22413:3:1;86089:96:0;;;82966:3227;;;;;;;;82837:3356;;;;:::o;28884:121::-;28943:4;25286;28967:19;28972:1;28975;:10;;;28967:4;:19::i;:::-;:30;;;;:::i;75177:2505::-;75333:28;75401:43;;;75467:4;75488:8;75512:12;75364:171;;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;75364:171:0;;;;;;;;;;;;;;-1:-1:-1;;;;;75364:171:0;-1:-1:-1;;;;;;75364:171:0;;;;;;;;;;75613:11;;75364:171;;-1:-1:-1;;;75577:108:0;;-1:-1:-1;;;;;75613:11:0;75364:171;75613:11;75577:13;:108::i;:::-;75548:137;;75698:12;75724:13;75713:36;;;;;;;;;;;;:::i;:::-;75698:51;-1:-1:-1;75766:12:0;;75762:87;;75802:35;;-1:-1:-1;;;75802:35:0;;;;;1564:25:1;;;1537:18;;75802:35:0;1418:177:1;75762:87:0;58845:12;75937:18;;:38;75933:100;;75999:22;;-1:-1:-1;;;75999:22:0;;;;;;;;;;;75933:100;76142:12;76125:14;:12;:14::i;:::-;:29;76121:93;;;76178:24;;-1:-1:-1;;;76178:24:0;;;;;;;;;;;76121:93;76461:23;76487:37;76515:8;76487:27;:37::i;:::-;76461:63;-1:-1:-1;76535:22:0;76560:33;76581:12;76461:63;76560:33;:::i;:::-;76535:58;;76604:20;76642:12;76627;;:27;;;;:::i;:::-;-1:-1:-1;;;;;76985:24:0;;;;;;:14;:24;;;;;:54;;;77091:11;;77050:38;;;;:52;77113:12;:30;;;76604:50;-1:-1:-1;77515:37:0;77000:8;77539:12;77515:13;:37::i;:::-;77608:66;;;-1:-1:-1;;;;;22957:32:1;;22939:51;;23021:2;23006:18;;22999:34;;;23049:18;;;23042:34;;;23107:2;23092:18;;23085:34;;;77608:66:0;;22926:3:1;22911:19;77608:66:0;;;;;;;75252:2430;;;;;;75177:2505;;:::o;95048:1453::-;95109:4;;;;58845:12;95333:18;;:38;95329:122;;95395:44;;-1:-1:-1;;;95395:44:0;;;;;1564:25:1;;;1537:18;;95395:44:0;1418:177:1;95329:122:0;96040:35;96053:10;96065:9;96040:12;:35::i;:::-;96022:53;;96123:15;96107:13;;:31;;;;:::i;:::-;96088:50;;96231:16;96215:13;:32;;;;96336:60;96350:10;96362:15;96379:16;96336:60;;;;;;;;:::i;:::-;;;;;;;;8406:1;;96477:15;;-1:-1:-1;95048:1453:0;-1:-1:-1;;;95048:1453:0:o;30502:90::-;30555:4;30579:5;30583:1;30579;:5;:::i;36235:98::-;36293:7;36320:5;36324:1;36320;:5;:::i;46449:389::-;46584:12;46605:20;46628:32;46644:15;46628;:32::i;:::-;46605:55;;46670:12;46684:19;46714:15;-1:-1:-1;;;;;46714:20:0;46742:12;:28;;46769:1;46742:28;;;46757:9;46742:28;46772:7;46714:66;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;46669:111;;;;46796:36;46816:7;46825:6;46796:19;:36::i;:::-;46789:43;46449:389;-1:-1:-1;;;;;;;46449:389:0:o;47181:335::-;47301:12;47325:20;47348:32;47364:15;47348;:32::i;:::-;47325:55;;47388:12;47402:19;47425:15;-1:-1:-1;;;;;47425:26:0;47452:7;47425:35;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;47387:73;;;;47474:36;47494:7;47503:6;47474:19;:36::i;:::-;47467:43;47181:335;-1:-1:-1;;;;;;47181:335:0:o;47522:1738::-;47656:22;;47599:12;;47620:33;47719:29;:27;:29::i;:::-;47685:63;-1:-1:-1;47755:29:0;47787:51;47685:63;47787:25;:51;:::i;:::-;47755:83;-1:-1:-1;47877:8:0;47851:41;;47847:96;;;47910:25;;-1:-1:-1;;;47910:25:0;;;;;;;;;;;47847:96;47951:20;48015:15;48009:22;47998:33;;48189:21;48180:7;48173:38;48319:15;48297:20;48293:42;48370:25;48364:4;48360:36;48442:7;48420:20;48416:34;48266:431;48470:7;48464:4;48460:18;48266:431;;;48676:11;;48665:23;;48508:16;48498:27;;;;48541:25;48266:431;;;48270:189;;;48939:23;48894;48878:14;48874:44;48825:25;48803:20;48799:52;48790:7;48786:66;48763:232;49116:55;;;;49103:69;;49185:20;49087:129;49061:15;49044:181;49107:7;47522:1738;-1:-1:-1;;;47522:1738:0:o;49860:859::-;49962:12;49991:7;49986:706;;50015:6;:13;50032:1;50015:18;50011:674;;50053:34;;-1:-1:-1;;;50053:34:0;;;;;;;;;;;50011:674;50218:20;50206:33;;50200:40;-1:-1:-1;;;50276:49:0;50348:328;;;;50532:52;;-1:-1:-1;;;50532:52:0;;50482:17;50470:30;;;50532:52;;50470:30;;50532:52;;;:::i;50348:328::-;50657:6;50622:42;;-1:-1:-1;;;50622:42:0;;;;;;;;:::i;49266:588::-;49327:7;49343:30;49376:36;:34;:36::i;:::-;49343:69;;49419:25;49447:61;49485:22;49447:37;:61::i;:::-;49419:89;;;-1:-1:-1;49515:48:0;31917:1;49515:48;;:::i;:::-;;;49575:24;49570:241;49624:17;49605:16;:36;49570:241;;;49672:27;49702:47;49726:22;49702:23;:47::i;:::-;49672:77;-1:-1:-1;49758:45:0;49672:77;49758:45;;:::i;:::-;;;49663:148;49643:18;;;;;:::i;:::-;;;;49570:241;;;-1:-1:-1;49826:22:0;;49266:588;-1:-1:-1;;49266:588:0:o;14:250:1:-;99:1;109:113;123:6;120:1;117:13;109:113;;;199:11;;;193:18;180:11;;;173:39;145:2;138:10;109:113;;;-1:-1:-1;;256:1:1;238:16;;231:27;14:250::o;269:271::-;311:3;349:5;343:12;376:6;371:3;364:19;392:76;461:6;454:4;449:3;445:14;438:4;431:5;427:16;392:76;:::i;:::-;522:2;501:15;-1:-1:-1;;497:29:1;488:39;;;;529:4;484:50;;269:271;-1:-1:-1;;269:271:1:o;545:220::-;694:2;683:9;676:21;657:4;714:45;755:2;744:9;740:18;732:6;714:45;:::i;770:131::-;-1:-1:-1;;;;;845:31:1;;835:42;;825:70;;891:1;888;881:12;906:315;974:6;982;1035:2;1023:9;1014:7;1010:23;1006:32;1003:52;;;1051:1;1048;1041:12;1003:52;1090:9;1077:23;1109:31;1134:5;1109:31;:::i;:::-;1159:5;1211:2;1196:18;;;;1183:32;;-1:-1:-1;;;906:315:1:o;1600:247::-;1659:6;1712:2;1700:9;1691:7;1687:23;1683:32;1680:52;;;1728:1;1725;1718:12;1680:52;1767:9;1754:23;1786:31;1811:5;1786:31;:::i;1852:456::-;1929:6;1937;1945;1998:2;1986:9;1977:7;1973:23;1969:32;1966:52;;;2014:1;2011;2004:12;1966:52;2053:9;2040:23;2072:31;2097:5;2072:31;:::i;:::-;2122:5;-1:-1:-1;2179:2:1;2164:18;;2151:32;2192:33;2151:32;2192:33;:::i;:::-;1852:456;;2244:7;;-1:-1:-1;;;2298:2:1;2283:18;;;;2270:32;;1852:456::o;3242:180::-;3301:6;3354:2;3342:9;3333:7;3329:23;3325:32;3322:52;;;3370:1;3367;3360:12;3322:52;-1:-1:-1;3393:23:1;;3242:180;-1:-1:-1;3242:180:1:o;3427:127::-;3488:10;3483:3;3479:20;3476:1;3469:31;3519:4;3516:1;3509:15;3543:4;3540:1;3533:15;3559:719;3602:5;3655:3;3648:4;3640:6;3636:17;3632:27;3622:55;;3673:1;3670;3663:12;3622:55;3709:6;3696:20;3735:18;3772:2;3768;3765:10;3762:36;;;3778:18;;:::i;:::-;3853:2;3847:9;3821:2;3907:13;;-1:-1:-1;;3903:22:1;;;3927:2;3899:31;3895:40;3883:53;;;3951:18;;;3971:22;;;3948:46;3945:72;;;3997:18;;:::i;:::-;4037:10;4033:2;4026:22;4072:2;4064:6;4057:18;4118:3;4111:4;4106:2;4098:6;4094:15;4090:26;4087:35;4084:55;;;4135:1;4132;4125:12;4084:55;4199:2;4192:4;4184:6;4180:17;4173:4;4165:6;4161:17;4148:54;4246:1;4239:4;4234:2;4226:6;4222:15;4218:26;4211:37;4266:6;4257:15;;;;;;3559:719;;;;:::o;4283:1108::-;4458:6;4466;4474;4482;4490;4498;4551:3;4539:9;4530:7;4526:23;4522:33;4519:53;;;4568:1;4565;4558:12;4519:53;4607:9;4594:23;4626:31;4651:5;4626:31;:::i;:::-;4676:5;-1:-1:-1;4733:2:1;4718:18;;4705:32;4746:33;4705:32;4746:33;:::i;:::-;4798:7;-1:-1:-1;4852:2:1;4837:18;;4824:32;;-1:-1:-1;4907:2:1;4892:18;;4879:32;4930:18;4960:14;;;4957:34;;;4987:1;4984;4977:12;4957:34;5010:50;5052:7;5043:6;5032:9;5028:22;5010:50;:::i;:::-;5000:60;;5113:3;5102:9;5098:19;5085:33;5069:49;;5143:2;5133:8;5130:16;5127:36;;;5159:1;5156;5149:12;5127:36;;5182:52;5226:7;5215:8;5204:9;5200:24;5182:52;:::i;:::-;5172:62;;;5286:3;5275:9;5271:19;5258:33;5335:4;5326:7;5322:18;5313:7;5310:31;5300:59;;5355:1;5352;5345:12;5300:59;5378:7;5368:17;;;4283:1108;;;;;;;;:::o;5396:403::-;5479:6;5487;5540:2;5528:9;5519:7;5515:23;5511:32;5508:52;;;5556:1;5553;5546:12;5508:52;5595:9;5582:23;5614:31;5639:5;5614:31;:::i;:::-;5664:5;-1:-1:-1;5721:2:1;5706:18;;5693:32;5734:33;5693:32;5734:33;:::i;:::-;5786:7;5776:17;;;5396:403;;;;;:::o;7363:334::-;7565:2;7547:21;;;7604:2;7584:18;;;7577:30;-1:-1:-1;;;7638:2:1;7623:18;;7616:40;7688:2;7673:18;;7363:334::o;7702:380::-;7781:1;7777:12;;;;7824;;;7845:61;;7899:4;7891:6;7887:17;7877:27;;7845:61;7952:2;7944:6;7941:14;7921:18;7918:38;7915:161;;7998:10;7993:3;7989:20;7986:1;7979:31;8033:4;8030:1;8023:15;8061:4;8058:1;8051:15;8087:277;8154:6;8207:2;8195:9;8186:7;8182:23;8178:32;8175:52;;;8223:1;8220;8213:12;8175:52;8255:9;8249:16;8308:5;8301:13;8294:21;8287:5;8284:32;8274:60;;8330:1;8327;8320:12;9091:127;9152:10;9147:3;9143:20;9140:1;9133:31;9183:4;9180:1;9173:15;9207:4;9204:1;9197:15;9223:125;9288:9;;;9309:10;;;9306:36;;;9322:18;;:::i;9353:128::-;9420:9;;;9441:11;;;9438:37;;;9455:18;;:::i;9486:135::-;9525:3;9546:17;;;9543:43;;9566:18;;:::i;:::-;-1:-1:-1;9613:1:1;9602:13;;9486:135::o;11736:545::-;11838:2;11833:3;11830:11;11827:448;;;11874:1;11899:5;11895:2;11888:17;11944:4;11940:2;11930:19;12014:2;12002:10;11998:19;11995:1;11991:27;11985:4;11981:38;12050:4;12038:10;12035:20;12032:47;;;-1:-1:-1;12073:4:1;12032:47;12128:2;12123:3;12119:12;12116:1;12112:20;12106:4;12102:31;12092:41;;12183:82;12201:2;12194:5;12191:13;12183:82;;;12246:17;;;12227:1;12216:13;12183:82;;;12187:3;;;11736:545;;;:::o;12457:1352::-;12583:3;12577:10;12610:18;12602:6;12599:30;12596:56;;;12632:18;;:::i;:::-;12661:97;12751:6;12711:38;12743:4;12737:11;12711:38;:::i;:::-;12705:4;12661:97;:::i;:::-;12813:4;;12877:2;12866:14;;12894:1;12889:663;;;;13596:1;13613:6;13610:89;;;-1:-1:-1;13665:19:1;;;13659:26;13610:89;-1:-1:-1;;12414:1:1;12410:11;;;12406:24;12402:29;12392:40;12438:1;12434:11;;;12389:57;13712:81;;12859:944;;12889:663;11683:1;11676:14;;;11720:4;11707:18;;-1:-1:-1;;12925:20:1;;;13043:236;13057:7;13054:1;13051:14;13043:236;;;13146:19;;;13140:26;13125:42;;13238:27;;;;13206:1;13194:14;;;;13073:19;;13043:236;;;13047:3;13307:6;13298:7;13295:19;13292:201;;;13368:19;;;13362:26;-1:-1:-1;;13451:1:1;13447:14;;;13463:3;13443:24;13439:37;13435:42;13420:58;13405:74;;13292:201;-1:-1:-1;;;;;13539:1:1;13523:14;;;13519:22;13506:36;;-1:-1:-1;12457:1352:1:o;14138:184::-;14208:6;14261:2;14249:9;14240:7;14236:23;14232:32;14229:52;;;14277:1;14274;14267:12;14229:52;-1:-1:-1;14300:16:1;;14138:184;-1:-1:-1;14138:184:1:o;15001:375::-;-1:-1:-1;;;;;15259:15:1;;;15241:34;;15311:15;;;;15306:2;15291:18;;15284:43;15358:2;15343:18;;15336:34;;;;15191:2;15176:18;;15001:375::o;15381:345::-;-1:-1:-1;;;;;15601:32:1;;;;15583:51;;15665:2;15650:18;;15643:34;;;;15708:2;15693:18;;15686:34;15571:2;15556:18;;15381:345::o;15731:168::-;15804:9;;;15835;;15852:15;;;15846:22;;15832:37;15822:71;;15873:18;;:::i;15904:217::-;15944:1;15970;15960:132;;16014:10;16009:3;16005:20;16002:1;15995:31;16049:4;16046:1;16039:15;16077:4;16074:1;16067:15;15960:132;-1:-1:-1;16106:9:1;;15904:217::o;20587:245::-;20666:6;20674;20727:2;20715:9;20706:7;20702:23;20698:32;20695:52;;;20743:1;20740;20733:12;20695:52;-1:-1:-1;;20766:16:1;;20822:2;20807:18;;;20801:25;20766:16;;20801:25;;-1:-1:-1;20587:245:1:o;23130:287::-;23259:3;23297:6;23291:13;23313:66;23372:6;23367:3;23360:4;23352:6;23348:17;23313:66;:::i;:::-;23395:16;;;;;23130:287;-1:-1:-1;;23130:287:1:o
Swarm Source
ipfs://61ce236ad864ae6dc6f33942e810f5f9735ae223ac2e8c38d33d45a26ba23d6b
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
SCROLL | 100.00% | $1,833.35 | 0.1046 | $191.74 |
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.