More Info
Private Name Tags
ContractCreator
TokenTracker
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
0xe28cce3c5c145b32b1dc70a0d4df0d54857ecf987318c7007c8b9d6b8940b45b | - | (pending) | 4 days ago | IN | 0.0013 ETH | (Pending) | |||
Redeem Underlyin... | 10155170 | 2 hrs ago | IN | 0 ETH | 0.00004848 | ||||
Mint | 10155130 | 2 hrs ago | IN | 0.009 ETH | 0.00001883 | ||||
Redeem Underlyin... | 10155085 | 2 hrs ago | IN | 0 ETH | 0.00004861 | ||||
Mint | 10155060 | 2 hrs ago | IN | 0.00909414 ETH | 0.0000197 | ||||
Redeem Underlyin... | 10155045 | 2 hrs ago | IN | 0 ETH | 0.00005109 | ||||
Mint | 10154992 | 2 hrs ago | IN | 0.00916831 ETH | 0.00002308 | ||||
Redeem Underlyin... | 10154393 | 2 hrs ago | IN | 0 ETH | 0.00003083 | ||||
Redeem Underlyin... | 10146636 | 8 hrs ago | IN | 0 ETH | 0.00003556 | ||||
Mint | 10146613 | 8 hrs ago | IN | 0.01031242 ETH | 0.00000758 | ||||
Redeem Underlyin... | 10146599 | 8 hrs ago | IN | 0 ETH | 0.00003452 | ||||
Mint | 10146581 | 8 hrs ago | IN | 0.01035528 ETH | 0.00000833 | ||||
Redeem Underlyin... | 10143375 | 11 hrs ago | IN | 0 ETH | 0.00001631 | ||||
Mint | 10143367 | 11 hrs ago | IN | 0.01000785 ETH | 0.00000827 | ||||
Redeem Underlyin... | 10136322 | 17 hrs ago | IN | 0 ETH | 0.00002462 | ||||
Redeem Underlyin... | 10131003 | 21 hrs ago | IN | 0 ETH | 0.00002837 | ||||
Mint | 10130989 | 21 hrs ago | IN | 0.00914254 ETH | 0.00000833 | ||||
Mint | 10130718 | 21 hrs ago | IN | 0.000525 ETH | 0.00001227 | ||||
Borrow | 10127094 | 24 hrs ago | IN | 0 ETH | 0.00002452 | ||||
Mint | 10127062 | 24 hrs ago | IN | 0.017 ETH | 0.00001062 | ||||
Redeem Underlyin... | 10125969 | 25 hrs ago | IN | 0 ETH | 0.00002418 | ||||
Mint | 10125953 | 25 hrs ago | IN | 0.00901943 ETH | 0.0000106 | ||||
Redeem Underlyin... | 10121740 | 29 hrs ago | IN | 0 ETH | 0.00003439 | ||||
Mint | 10121718 | 29 hrs ago | IN | 0.00919149 ETH | 0.00000718 | ||||
Redeem Underlyin... | 10121660 | 29 hrs ago | IN | 0 ETH | 0.00002145 |
Latest 25 internal transactions (View All)
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
10155170 | 2 hrs ago | 0.009 ETH | ||||
10155085 | 2 hrs ago | 0.00909414 ETH | ||||
10155045 | 2 hrs ago | 0.00916831 ETH | ||||
10154393 | 2 hrs ago | 0.01700007 ETH | ||||
10154363 | 2 hrs ago | 0.01300116 ETH | ||||
10146636 | 8 hrs ago | 0.01031242 ETH | ||||
10146599 | 8 hrs ago | 0.01035528 ETH | ||||
10143375 | 11 hrs ago | 0.01000785 ETH | ||||
10136322 | 17 hrs ago | 0.000525 ETH | ||||
10131003 | 21 hrs ago | 0.00914254 ETH | ||||
10127094 | 24 hrs ago | 0.013 ETH | ||||
10125969 | 25 hrs ago | 0.00901943 ETH | ||||
10121740 | 29 hrs ago | 0.00919149 ETH | ||||
10121660 | 29 hrs ago | 0.00922885 ETH | ||||
10120888 | 29 hrs ago | 0.00997444 ETH | ||||
10115977 | 33 hrs ago | 0.19000317 ETH | ||||
10099626 | 47 hrs ago | 0.03103 ETH | ||||
10097559 | 2 days ago | 0.00924847 ETH | ||||
10089198 | 2 days ago | 0.0094821 ETH | ||||
10089139 | 2 days ago | 0.00952753 ETH | ||||
10089037 | 2 days ago | 0.00958579 ETH | ||||
10088187 | 2 days ago | 0.00911032 ETH | ||||
10085729 | 2 days ago | 0.00887743 ETH | ||||
10061850 | 3 days ago | 0.3170106 ETH | ||||
10061428 | 3 days ago | 0.01500918 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-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
[{"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
60806040523480156200001157600080fd5b50604051620043d1380380620043d18339810160408190526200003491620006bd565b60038054610100600160a81b03199081163361010002918216171790556200006187878787878762000094565b600380546001600160a01b0390921661010002610100600160a81b0319909216919091179055506200090e945050505050565b60035461010090046001600160a01b03163314620001055760405162461bcd60e51b8152602060048201526024808201527f6f6e6c792061646d696e206d617920696e697469616c697a6520746865206d616044820152631c9ad95d60e21b60648201526084015b60405180910390fd5b600954158015620001165750600a54155b620001705760405162461bcd60e51b815260206004820152602360248201527f6d61726b6574206d6179206f6e6c7920626520696e697469616c697a6564206f6044820152626e636560e81b6064820152608401620000fc565b600784905583620001dd5760405162461bcd60e51b815260206004820152603060248201527f696e697469616c2065786368616e67652072617465206d75737420626520677260448201526f32b0ba32b9103a3430b7103d32b9379760811b6064820152608401620000fc565b6000620001ea87620002f8565b905080156200023c5760405162461bcd60e51b815260206004820152601a60248201527f73657474696e6720636f6d7074726f6c6c6572206661696c65640000000000006044820152606401620000fc565b43600955670de0b6b3a7640000600a55620002578662000450565b90508015620002b45760405162461bcd60e51b815260206004820152602260248201527f73657474696e6720696e7465726573742072617465206d6f64656c206661696c604482015261195960f21b6064820152608401620000fc565b6001620002c2858262000817565b506002620002d1848262000817565b50506003805460ff90921660ff199283161790556000805490911660011790555050505050565b60035460009061010090046001600160a01b031633146200032c5760405163d219dc1f60e01b815260040160405180910390fd5b60055460408051623f1ee960e11b815290516001600160a01b0392831692851691627e3dd29160048083019260209291908290030181865afa15801562000377573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200039d9190620008e3565b620003eb5760405162461bcd60e51b815260206004820152601c60248201527f6d61726b6572206d6574686f642072657475726e65642066616c7365000000006044820152606401620000fc565b600580546001600160a01b0319166001600160a01b0385811691821790925560408051928416835260208301919091527f7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d91015b60405180910390a150600092915050565b600354600090819061010090046001600160a01b03163314620004865760405163407fded560e01b815260040160405180910390fd5b4360095414620004a957604051630be2a5cb60e11b815260040160405180910390fd5b600660009054906101000a90046001600160a01b03169050826001600160a01b0316632191f92a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000500573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005269190620008e3565b620005745760405162461bcd60e51b815260206004820152601c60248201527f6d61726b6572206d6574686f642072657475726e65642066616c7365000000006044820152606401620000fc565b600680546001600160a01b0319166001600160a01b0385811691821790925560408051928416835260208301919091527fedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f92691016200043f565b6001600160a01b0381168114620005e357600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200060e57600080fd5b81516001600160401b03808211156200062b576200062b620005e6565b604051601f8301601f19908116603f01168101908282118183101715620006565762000656620005e6565b816040528381526020925086838588010111156200067357600080fd5b600091505b8382101562000697578582018301518183018401529082019062000678565b600093810190920192909252949350505050565b8051620006b881620005cd565b919050565b600080600080600080600060e0888a031215620006d957600080fd5b8751620006e681620005cd565b6020890151909750620006f981620005cd565b604089015160608a015191975095506001600160401b03808211156200071e57600080fd5b6200072c8b838c01620005fc565b955060808a01519150808211156200074357600080fd5b50620007528a828b01620005fc565b93505060a088015160ff811681146200076a57600080fd5b91506200077a60c08901620006ab565b905092959891949750929550565b600181811c908216806200079d57607f821691505b602082108103620007be57634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200081257600081815260208120601f850160051c81016020861015620007ed5750805b601f850160051c820191505b818110156200080e57828155600101620007f9565b5050505b505050565b81516001600160401b03811115620008335762000833620005e6565b6200084b8162000844845462000788565b84620007c4565b602080601f8311600181146200088357600084156200086a5750858301515b600019600386901b1c1916600185901b1785556200080e565b600085815260208120601f198616915b82811015620008b45788860151825594840194600190910190840162000893565b5085821015620008d35787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b600060208284031215620008f657600080fd5b815180151581146200090757600080fd5b9392505050565b613ab3806200091e6000396000f3fe6080604052600436106102cd5760003560e01c80638f840ddd11610175578063c37f68e2116100dc578063f2b3abbd11610095578063f8f9da281161006f578063f8f9da281461084a578063fca7820b1461085f578063fcb641471461087f578063fe9c44ae1461088757600080fd5b8063f2b3abbd146107e5578063f3fdb15a14610805578063f851a4401461082557600080fd5b8063c37f68e2146106f7578063c5ebeaec14610737578063db006a7514610757578063dd62ed3e14610777578063e5974619146107bd578063e9c714f2146107d057600080fd5b8063aa5af0fd1161012e578063aa5af0fd14610664578063aae40a2a1461067a578063ae9d70b01461068d578063b2a02ff1146106a2578063b71d1a0c146106c2578063bd6d894d146106e257600080fd5b80638f840ddd146105c457806395d89b41146105da57806395dd9193146105ef57806399d8c1b41461060f578063a6afed951461062f578063a9059cbb1461064457600080fd5b80634576b5db116102345780636752e702116101ed57806370a08231116101c757806370a082311461054657806373acee981461057c5780637cb05b2914610591578063852a12e3146105a457600080fd5b80636752e7021461050057806369ab32501461051b5780636c540baf1461053057600080fd5b80634576b5db1461046d57806347bd37181461048d5780634e4d9fea146104a357806355a547d5146104ab5780635fe3b567146104c0578063601a0bf1146104e057600080fd5b8063182df0f511610286578063182df0f51461039f57806323b872dd146103b457806326782247146103d4578063313ce5671461040c5780633af9e669146104385780633b1d21a21461045857600080fd5b806306fdde03146102e2578063095ea7b31461030d5780631249c58b1461033d578063173b99041461034557806317bfdfbc1461036957806318160ddd1461038957600080fd5b366102dd576102db3461089c565b005b600080fd5b3480156102ee57600080fd5b506102f76108f4565b6040516103049190613556565b60405180910390f35b34801561031957600080fd5b5061032d61032836600461357e565b610982565b6040519015158152602001610304565b6102db6109f2565b34801561035157600080fd5b5061035b60085481565b604051908152602001610304565b34801561037557600080fd5b5061035b6103843660046135aa565b6109fd565b34801561039557600080fd5b5061035b600d5481565b3480156103ab57600080fd5b5061035b610a50565b3480156103c057600080fd5b5061032d6103cf3660046135c7565b610a5f565b3480156103e057600080fd5b506004546103f4906001600160a01b031681565b6040516001600160a01b039091168152602001610304565b34801561041857600080fd5b506003546104269060ff1681565b60405160ff9091168152602001610304565b34801561044457600080fd5b5061035b6104533660046135aa565b610aaf565b34801561046457600080fd5b5061035b610af5565b34801561047957600080fd5b5061035b6104883660046135aa565b610aff565b34801561049957600080fd5b5061035b600b5481565b6102db610c51565b3480156104b757600080fd5b5061035b610c5a565b3480156104cc57600080fd5b506005546103f4906001600160a01b031681565b3480156104ec57600080fd5b5061035b6104fb366004613608565b610d72565b34801561050c57600080fd5b5061035b666379da05b6000081565b34801561052757600080fd5b5061035b600081565b34801561053c57600080fd5b5061035b60095481565b34801561055257600080fd5b5061035b6105613660046135aa565b6001600160a01b03166000908152600e602052604090205490565b34801561058857600080fd5b5061035b610db1565b6102db61059f36600461357e565b610dfb565b3480156105b057600080fd5b5061035b6105bf366004613608565b610e09565b3480156105d057600080fd5b5061035b600c5481565b3480156105e657600080fd5b506102f7610e1c565b3480156105fb57600080fd5b5061035b61060a3660046135aa565b610e29565b34801561061b57600080fd5b506102db61062a3660046136c4565b610e34565b34801561063b57600080fd5b5061035b611081565b34801561065057600080fd5b5061032d61065f36600461357e565b61126e565b34801561067057600080fd5b5061035b600a5481565b6102db610688366004613770565b6112bd565b34801561069957600080fd5b5061035b6112c8565b3480156106ae57600080fd5b5061035b6106bd3660046135c7565b611360565b3480156106ce57600080fd5b5061035b6106dd3660046135aa565b6113af565b3480156106ee57600080fd5b5061035b61143c565b34801561070357600080fd5b506107176107123660046135aa565b61148c565b604080519485526020850193909352918301526060820152608001610304565b34801561074357600080fd5b5061035b610752366004613608565b6114cd565b34801561076357600080fd5b5061035b610772366004613608565b6114d8565b34801561078357600080fd5b5061035b610792366004613770565b6001600160a01b039182166000908152600f6020908152604080832093909416825291909152205490565b6102db6107cb3660046135aa565b6114e3565b3480156107dc57600080fd5b5061035b6114f0565b3480156107f157600080fd5b5061035b6108003660046135aa565b6115f7565b34801561081157600080fd5b506006546103f4906001600160a01b031681565b34801561083157600080fd5b506003546103f49061010090046001600160a01b031681565b34801561085657600080fd5b5061035b61160b565b34801561086b57600080fd5b5061035b61087a366004613608565b61165e565b61035b61169d565b34801561089357600080fd5b5061032d600181565b60005460ff166108c75760405162461bcd60e51b81526004016108be906137a9565b60405180910390fd5b6000805460ff191690556108d9611081565b506108e433826116a8565b506000805460ff19166001179055565b60018054610901906137cd565b80601f016020809104026020016040519081016040528092919081815260200182805461092d906137cd565b801561097a5780601f1061094f5761010080835404028352916020019161097a565b820191906000526020600020905b81548152906001019060200180831161095d57829003601f168201915b505050505081565b336000818152600f602090815260408083206001600160a01b03871680855292528083208590555191929182907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906109de9087815260200190565b60405180910390a360019150505b92915050565b6109fb3461089c565b565b6000805460ff16610a205760405162461bcd60e51b81526004016108be906137a9565b6000805460ff19169055610a32611081565b50610a3c82610e29565b90506000805460ff19166001179055919050565b6000610a5a61185e565b905090565b6000805460ff16610a825760405162461bcd60e51b81526004016108be906137a9565b6000805460ff19168155610a98338686866118c6565b1490506000805460ff191660011790559392505050565b6000806040518060200160405280610ac561143c565b90526001600160a01b0384166000908152600e6020526040902054909150610aee908290611af2565b9392505050565b6000610a5a611b12565b60035460009061010090046001600160a01b03163314610b325760405163d219dc1f60e01b815260040160405180910390fd5b60055460408051623f1ee960e11b815290516001600160a01b0392831692851691627e3dd29160048083019260209291908290030181865afa158015610b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ba09190613801565b610bec5760405162461bcd60e51b815260206004820152601c60248201527f6d61726b6572206d6574686f642072657475726e65642066616c73650000000060448201526064016108be565b600580546001600160a01b0319166001600160a01b0385811691821790925560408051928416835260208301919091527f7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d91015b60405180910390a150600092915050565b6109fb34611b1e565b600080610c65611b6f565b90506000610c7282611c16565b61ffff16905080600003610c9957604051632154bfcf60e21b815260040160405180910390fd5b610ca4600283613839565b915060005b81811015610d6c576000610cbc84611c50565b9050600080610ccc606887613839565b90506000610cda823661384c565b9050803592508265ffffffffffff16600003610d0957604051630336dc9d60e41b815260040160405180910390fd5b87600003610d21578265ffffffffffff169750610d49565b878365ffffffffffff1614610d495760405163d9d1f46560e01b815260040160405180910390fd5b610d538488613839565b9650505050508080610d649061385f565b915050610ca9565b50505090565b6000805460ff16610d955760405162461bcd60e51b81526004016108be906137a9565b6000805460ff19169055610da7611081565b50610a3c82611c84565b6000805460ff16610dd45760405162461bcd60e51b81526004016108be906137a9565b6000805460ff19169055610de6611081565b5050600b546000805460ff1916600117905590565b610e058282611d9f565b5050565b6000610e1482611df1565b506000919050565b60028054610901906137cd565b60006109ec82611e32565b60035461010090046001600160a01b03163314610e9f5760405162461bcd60e51b8152602060048201526024808201527f6f6e6c792061646d696e206d617920696e697469616c697a6520746865206d616044820152631c9ad95d60e21b60648201526084016108be565b600954158015610eaf5750600a54155b610f075760405162461bcd60e51b815260206004820152602360248201527f6d61726b6574206d6179206f6e6c7920626520696e697469616c697a6564206f6044820152626e636560e81b60648201526084016108be565b600784905583610f725760405162461bcd60e51b815260206004820152603060248201527f696e697469616c2065786368616e67652072617465206d75737420626520677260448201526f32b0ba32b9103a3430b7103d32b9379760811b60648201526084016108be565b6000610f7d87610aff565b90508015610fcd5760405162461bcd60e51b815260206004820152601a60248201527f73657474696e6720636f6d7074726f6c6c6572206661696c656400000000000060448201526064016108be565b43600955670de0b6b3a7640000600a55610fe686611e7e565b905080156110415760405162461bcd60e51b815260206004820152602260248201527f73657474696e6720696e7465726573742072617465206d6f64656c206661696c604482015261195960f21b60648201526084016108be565b600161104d85826138c6565b50600261105a84826138c6565b50506003805460ff90921660ff199283161790556000805490911660011790555050505050565b60095460009043908181036110995760009250505090565b60006110a3611b12565b600b54600c54600a546006546040516315f2405360e01b81526004810186905260248101859052604481018490529495509293919290916000916001600160a01b0316906315f2405390606401602060405180830381865afa15801561110d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111319190613986565b905065048c273950008111156111895760405162461bcd60e51b815260206004820152601c60248201527f626f72726f772072617465206973206162737572646c7920686967680000000060448201526064016108be565b6000611195878961384c565b905060006111b160405180602001604052808581525083611ff3565b905060006111bf8288611af2565b905060006111cd8883613839565b905060006111ec6040518060200160405280600854815250848a612024565b905060006111fb85898a612024565b60098e9055600a819055600b849055600c839055604080518d815260208101879052908101829052606081018590529091507f4dec04e750ca11537cabcd8a9eab06494de08da3735bc8871cd41250e190bc049060800160405180910390a160009d505050505050505050505050505090565b6000805460ff166112915760405162461bcd60e51b81526004016108be906137a9565b6000805460ff191681556112a7338086866118c6565b1490506000805460ff1916600117905592915050565b610e05823483612045565b6006546000906001600160a01b031663b81688166112e4611b12565b600b54600c546008546040516001600160e01b031960e087901b16815260048101949094526024840192909252604483015260648201526084015b602060405180830381865afa15801561133c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a5a9190613986565b6000805460ff166113835760405162461bcd60e51b81526004016108be906137a9565b6000805460ff1916905561139933858585612123565b50600080805460ff191660011790559392505050565b60035460009061010090046001600160a01b031633146113e257604051635cb56c2b60e01b815260040160405180910390fd5b600480546001600160a01b038481166001600160a01b031983168117909355604080519190921680825260208201939093527fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a99101610c40565b6000805460ff1661145f5760405162461bcd60e51b81526004016108be906137a9565b6000805460ff19169055611471611081565b5061147a610a50565b90506000805460ff1916600117905590565b6001600160a01b0381166000908152600e602052604081205481908190819081906114b687611e32565b6114be61185e565b93509350935093509193509193565b6000610e148261239b565b6000610e14826123da565b6114ed8134611d9f565b50565b6004546000906001600160a01b03163314158061150b575033155b1561152957604051631ba24f2960e21b815260040160405180910390fd5b60038054600480546001600160a01b03808216610100818102610100600160a81b0319871617968790556001600160a01b031990931690935560408051948390048216808652929095041660208401529290917ff9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc910160405180910390a1600454604080516001600160a01b03808516825290921660208301527fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9910160405180910390a160009250505090565b6000611601611081565b506109ec82611e7e565b6006546000906001600160a01b03166315f24053611627611b12565b600b54600c546040516001600160e01b031960e086901b16815260048101939093526024830191909152604482015260640161131f565b6000805460ff166116815760405162461bcd60e51b81526004016108be906137a9565b6000805460ff19169055611693611081565b50610a3c8261241b565b6000610a5a346124d7565b600554604051634ef4c3e160e01b81526000916001600160a01b031690634ef4c3e1906116dd9030908790879060040161399f565b6020604051808303816000875af11580156116fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117209190613986565b90508015611744576040516349abd4fd60e01b8152600481018290526024016108be565b4360095414611766576040516338d8859760e01b815260040160405180910390fd5b6000604051806020016040528061177b61185e565b90529050600061178b858561252e565b9050600061179982846125c0565b905080600d546117a99190613839565b600d556001600160a01b0386166000908152600e60205260409020546117d0908290613839565b6001600160a01b0387166000908152600e60205260409081902091909155517f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f90611820908890859085906139c3565b60405180910390a16040518181526001600160a01b038716903090600080516020613a5e8339815191529060200160405180910390a3505050505050565b600d5460009080820361187357505060075490565b600061187d611b12565b90506000600c54600b54836118929190613839565b61189c919061384c565b90506000836118b3670de0b6b3a7640000846139e4565b6118bd91906139fb565b95945050505050565b6005546040516317b9b84b60e31b81523060048201526001600160a01b038581166024830152848116604483015260648201849052600092839291169063bdcdc258906084016020604051808303816000875af115801561192b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061194f9190613986565b905080156119735760405163089d427760e11b8152600481018290526024016108be565b836001600160a01b0316856001600160a01b0316036119a557604051638cd22d1960e01b815260040160405180910390fd5b6000856001600160a01b0316876001600160a01b0316036119c957506000196119f1565b506001600160a01b038086166000908152600f60209081526040808320938a16835292905220545b60006119fd858361384c565b6001600160a01b0388166000908152600e602052604081205491925090611a2590879061384c565b6001600160a01b0388166000908152600e602052604081205491925090611a4d908890613839565b6001600160a01b03808b166000908152600e6020526040808220869055918b1681522081905590506000198414611aa7576001600160a01b03808a166000908152600f60209081526040808320938e168352929052208390555b876001600160a01b0316896001600160a01b0316600080516020613a5e83398151915289604051611ada91815260200190565b60405180910390a35060009998505050505050505050565b600080611aff8484611ff3565b9050611b0a816125de565b949350505050565b6000610a5a344761384c565b60005460ff16611b405760405162461bcd60e51b81526004016108be906137a9565b6000805460ff19169055611b52611081565b50611b5e3333836125f6565b50506000805460ff19166001179055565b60006602ed57011e0000601f1936013581161480611ba0576040516373bb264f60e11b815260040160405180910390fd5b60003660291115611bc457604051632bcb7bc560e11b815260040160405180910390fd5b5060281936013560006009611bdf600362ffffff8516613839565b611be99190613839565b905036611bf7600283613839565b1115610aee5760405163c30a7bd760e01b815260040160405180910390fd5b600080611c24602084613839565b905036811115611c4757604051632bcb7bc560e11b815260040160405180910390fd5b36033592915050565b6000806000611c5e8461279f565b9092509050604e611c70826020613839565b611c7a90846139e4565b611b0a9190613839565b600354600090819061010090046001600160a01b03163314611cb957604051630f7e5e6d60e41b815260040160405180910390fd5b4360095414611cdb57604051630dff50cb60e41b815260040160405180910390fd5b82611ce4611b12565b1015611d0357604051633345e99960e01b815260040160405180910390fd5b600c54831115611d26576040516378d2980560e11b815260040160405180910390fd5b82600c54611d34919061384c565b600c819055600354909150611d579061010090046001600160a01b0316846127f6565b7f3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e600360019054906101000a90046001600160a01b03168483604051610c40939291906139c3565b60005460ff16611dc15760405162461bcd60e51b81526004016108be906137a9565b6000805460ff19169055611dd3611081565b50611ddf3383836125f6565b50506000805460ff1916600117905550565b60005460ff16611e135760405162461bcd60e51b81526004016108be906137a9565b6000805460ff19169055611e25611081565b506108e433600083612831565b6001600160a01b038116600090815260106020526040812080548203611e5b5750600092915050565b600a548154600091611e6c916139e4565b9050816001015481611b0a91906139fb565b600354600090819061010090046001600160a01b03163314611eb35760405163407fded560e01b815260040160405180910390fd5b4360095414611ed557604051630be2a5cb60e11b815260040160405180910390fd5b600660009054906101000a90046001600160a01b03169050826001600160a01b0316632191f92a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f4f9190613801565b611f9b5760405162461bcd60e51b815260206004820152601c60248201527f6d61726b6572206d6574686f642072657475726e65642066616c73650000000060448201526064016108be565b600680546001600160a01b0319166001600160a01b0385811691821790925560408051928416835260208301919091527fedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f9269101610c40565b604080516020810190915260008152604051806020016040528061201b856000015185612b1f565b90529392505050565b6000806120318585611ff3565b90506118bd61203f826125de565b84612b2b565b60005460ff166120675760405162461bcd60e51b81526004016108be906137a9565b6000805460ff19169055612079611081565b506000816001600160a01b031663a6afed956040518163ffffffff1660e01b81526004016020604051808303816000875af11580156120bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120e09190613986565b9050801561210457604051633eea49b760e11b8152600481018290526024016108be565b61211033858585612b37565b50506000805460ff191660011790555050565b60055460405163d02f735160e01b81523060048201526001600160a01b0386811660248301528581166044830152848116606483015260848201849052600092169063d02f73519060a4016020604051808303816000875af115801561218d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121b19190613986565b905080156121d5576040516363e00e3360e11b8152600481018290526024016108be565b836001600160a01b0316836001600160a01b03160361220757604051633a94626760e11b815260040160405180910390fd5b6000612228836040518060200160405280666379da05b60000815250612fff565b90506000612236828561384c565b90506000604051806020016040528061224d61185e565b90529050600061225d8285611af2565b9050600081600c5461226f9190613839565b600c819055600d5490915061228590869061384c565b600d556001600160a01b0388166000908152600e60205260409020546122ac90889061384c565b6001600160a01b03808a166000908152600e602052604080822093909355908b16815220546122dc908590613839565b6001600160a01b03808b166000818152600e602052604090819020939093559151908a1690600080516020613a5e8339815191529061231e9088815260200190565b60405180910390a360405185815230906001600160a01b038a1690600080516020613a5e8339815191529060200160405180910390a37fa91e67c5ea634cd43a12c5a482724b03de01e85ca68702a53d0c2f45cb7c1dc5308383604051612387939291906139c3565b60405180910390a150505050505050505050565b60005460ff166123bd5760405162461bcd60e51b81526004016108be906137a9565b6000805460ff191690556123cf611081565b506108e43382613022565b60005460ff166123fc5760405162461bcd60e51b81526004016108be906137a9565b6000805460ff1916905561240e611081565b506108e433826000612831565b60035460009061010090046001600160a01b0316331461244e57604051631205b57b60e11b815260040160405180910390fd5b436009541461247057604051637dfca6b760e11b815260040160405180910390fd5b670de0b6b3a76400008211156124995760405163717220f360e11b815260040160405180910390fd5b600880549083905560408051828152602081018590527faaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f8214609101610c40565b6000805460ff166124fa5760405162461bcd60e51b81526004016108be906137a9565b6000805460ff1916905561250c611081565b50612516826131d2565b5050600090506000805460ff19166001179055919050565b6000336001600160a01b0384161461257a5760405162461bcd60e51b815260206004820152600f60248201526e0e6cadcc8cae440dad2e6dac2e8c6d608b1b60448201526064016108be565b8134146125ba5760405162461bcd60e51b815260206004820152600e60248201526d0ecc2d8eaca40dad2e6dac2e8c6d60931b60448201526064016108be565b50919050565b6000610aee6125d784670de0b6b3a7640000612b1f565b8351613266565b80516000906109ec90670de0b6b3a7640000906139fb565b600554604051631200453160e11b81523060048201526001600160a01b03858116602483015284811660448301526064820184905260009283929116906324008a62906084016020604051808303816000875af115801561265b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061267f9190613986565b905080156126a357604051638c81362d60e01b8152600481018290526024016108be565b43600954146126c55760405163c9021e2f60e01b815260040160405180910390fd5b60006126d085611e32565b9050600060001985146126e357846126e5565b815b905060006126f3888361252e565b90506000612701828561384c565b9050600082600b54612713919061384c565b6001600160a01b038a8116600081815260106020908152604091829020878155600a54600190910155600b8590558151938f168452830191909152810185905260608101849052608081018290529091507f1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a19060a00160405180910390a1509098975050505050505050565b6000808080806127b0604187613839565b905060006127c96127c2602084613839565b3690613272565b8035945090506127da816003613272565b62ffffff9490941697933563ffffffff16965092945050505050565b6040516001600160a01b0383169082156108fc029083906000818181858888f1935050505015801561282c573d6000803e3d6000fd5b505050565b81158061283c575080155b6128a55760405162461bcd60e51b815260206004820152603460248201527f6f6e65206f662072656465656d546f6b656e73496e206f722072656465656d416044820152736d6f756e74496e206d757374206265207a65726f60601b60648201526084016108be565b600060405180602001604052806128ba61185e565b9052905060008084156128db578491506128d48386611af2565b90506128eb565b6128e584846125c0565b91508390505b600063eabe7d9160e01b30888560405160240161290a9392919061399f565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915260055490915060009061295a906001600160a01b031683600161327e565b90506000818060200190518101906129729190613986565b905080156129965760405163480f424760e01b8152600481018290526024016108be565b43600954146129b8576040516397b5cfcd60e01b815260040160405180910390fd5b836129c1611b12565b10156129e0576040516391240a1b60e01b815260040160405180910390fd5b84600d546129ee919061384c565b600d556001600160a01b0389166000908152600e6020526040902054612a1590869061384c565b6001600160a01b038a166000908152600e6020526040902055612a3889856127f6565b60405185815230906001600160a01b038b1690600080516020613a5e8339815191529060200160405180910390a37fe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a929898587604051612a99939291906139c3565b60405180910390a16005546040516351dff98960e01b81523060048201526001600160a01b038b811660248301526044820187905260648201889052909116906351dff98990608401600060405180830381600087803b158015612afc57600080fd5b505af1158015612b10573d6000803e3d6000fd5b50505050505050505050505050565b6000610aee82846139e4565b6000610aee8284613839565b604080513060248201526001600160a01b0383811660448301528681166064830152858116608483015260a48083018690528351808403909101815260c49092019092526020810180516001600160e01b0316632fe3f38f60e11b1790526005549091600091612baa911683600161327e565b9050600081806020019051810190612bc29190613986565b90508015612be657604051630a14d17960e11b8152600481018290526024016108be565b4360095414612c08576040516380965b1b60e01b815260040160405180910390fd5b43846001600160a01b0316636c540baf6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c6b9190613986565b14612c8957604051631046f38d60e31b815260040160405180910390fd5b866001600160a01b0316866001600160a01b031603612cbb57604051631bd1a62160e21b815260040160405180910390fd5b84600003612cdc5760405163d29da7ef60e01b815260040160405180910390fd5b6000198503612cfe57604051635982c5bb60e11b815260040160405180910390fd5b6000612d0b8888886125f6565b9050600063c488847b60e01b308784604051602401612d2c9392919061399f565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152600554909150600090612d7a906001600160a01b031683613312565b905060008082806020019051810190612d939190613a1d565b9150915060008214612e035760405162461bcd60e51b815260206004820152603360248201527f4c49515549444154455f434f4d5054524f4c4c45525f43414c43554c4154455f604482015272105353d5539517d4d152569157d19052531151606a1b60648201526084016108be565b6040516370a0823160e01b81526001600160a01b038c811660048301528291908b16906370a0823190602401602060405180830381865afa158015612e4c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e709190613986565b1015612ebe5760405162461bcd60e51b815260206004820152601860248201527f4c49515549444154455f5345495a455f544f4f5f4d554348000000000000000060448201526064016108be565b306001600160a01b038a1603612edf57612eda308d8d84612123565b612f98565b6000896001600160a01b031663b2a02ff18e8e856040518463ffffffff1660e01b8152600401612f119392919061399f565b6020604051808303816000875af1158015612f30573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f549190613986565b14612f985760405162461bcd60e51b81526020600482015260146024820152731d1bdad95b881cd95a5e9d5c994819985a5b195960621b60448201526064016108be565b604080516001600160a01b038e811682528d811660208301528183018890528b1660608201526080810183905290517f298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb529181900360a00190a1505050505050505050505050565b6000670de0b6b3a7640000613018848460000151612b1f565b610aee91906139fb565b600063da3d454c60e01b3084846040516024016130419392919061399f565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152600554909150600090613091906001600160a01b031683600161327e565b90506000818060200190518101906130a99190613986565b905080156130cd5760405163918db40f60e01b8152600481018290526024016108be565b43600954146130ef57604051630e8d8c6160e21b815260040160405180910390fd5b836130f8611b12565b1015613117576040516348c2588160e01b815260040160405180910390fd5b600061312286611e32565b905060006131308683613839565b9050600086600b546131429190613839565b6001600160a01b0389166000908152601060205260409020838155600a54600190910155600b819055905061317788886127f6565b604080516001600160a01b038a16815260208101899052908101839052606081018290527f13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab809060800160405180910390a15050505050505050565b600080808043600954146131fc576040516338acf79960e01b8152600481018290526024016108be565b613206338661252e565b905080600c546132169190613839565b915081600c819055507fa91e67c5ea634cd43a12c5a482724b03de01e85ca68702a53d0c2f45cb7c1dc5338284604051613252939291906139c3565b60405180910390a160009590945092505050565b6000610aee82846139fb565b6000610aee828461384c565b6060600061328b84613395565b9050600080866001600160a01b0316856132a65760006132a8565b345b846040516132b69190613a41565b60006040518083038185875af1925050503d80600081146132f3576040519150601f19603f3d011682016040523d82523d6000602084013e6132f8565b606091505b50915091506133078282613424565b979650505050505050565b6060600061331f83613395565b9050600080856001600160a01b03168360405161333c9190613a41565b600060405180830381855afa9150503d8060008114613377576040519150601f19603f3d011682016040523d82523d6000602084013e61337c565b606091505b509150915061338b8282613424565b9695505050505050565b805160609060006133a461349b565b905060006133b28284613839565b9050368211156133d557604051632bcb7bc560e11b815260040160405180910390fd5b6060604051905081815285602001848101826020015b818310156134035782518152602092830192016133eb565b50505082833603856020018301379190920181016020016040529392505050565b6060826125ba57815160000361344d57604051632b3ff13d60e11b815260040160405180910390fd5b602082015162461bcd60e51b148015613480576040516301efd04f60e31b815260448401906108be908290600401613556565b8260405163fd36fde360e01b81526004016108be9190613556565b6000806134a6611b6f565b905060006134b382611c16565b61ffff1690506134c4600283613839565b915060005b818110156134fe5760006134dc84611c50565b90506134e88185613839565b93505080806134f69061385f565b9150506134c9565b509092915050565b60005b83811015613521578181015183820152602001613509565b50506000910152565b60008151808452613542816020860160208601613506565b601f01601f19169290920160200192915050565b602081526000610aee602083018461352a565b6001600160a01b03811681146114ed57600080fd5b6000806040838503121561359157600080fd5b823561359c81613569565b946020939093013593505050565b6000602082840312156135bc57600080fd5b8135610aee81613569565b6000806000606084860312156135dc57600080fd5b83356135e781613569565b925060208401356135f781613569565b929592945050506040919091013590565b60006020828403121561361a57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261364857600080fd5b813567ffffffffffffffff8082111561366357613663613621565b604051601f8301601f19908116603f0116810190828211818310171561368b5761368b613621565b816040528381528660208588010111156136a457600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c087890312156136dd57600080fd5b86356136e881613569565b955060208701356136f881613569565b945060408701359350606087013567ffffffffffffffff8082111561371c57600080fd5b6137288a838b01613637565b9450608089013591508082111561373e57600080fd5b5061374b89828a01613637565b92505060a087013560ff8116811461376257600080fd5b809150509295509295509295565b6000806040838503121561378357600080fd5b823561378e81613569565b9150602083013561379e81613569565b809150509250929050565b6020808252600a90820152691c994b595b9d195c995960b21b604082015260600190565b600181811c908216806137e157607f821691505b6020821081036125ba57634e487b7160e01b600052602260045260246000fd5b60006020828403121561381357600080fd5b81518015158114610aee57600080fd5b634e487b7160e01b600052601160045260246000fd5b808201808211156109ec576109ec613823565b818103818111156109ec576109ec613823565b60006001820161387157613871613823565b5060010190565b601f82111561282c57600081815260208120601f850160051c8101602086101561389f5750805b601f850160051c820191505b818110156138be578281556001016138ab565b505050505050565b815167ffffffffffffffff8111156138e0576138e0613621565b6138f4816138ee84546137cd565b84613878565b602080601f83116001811461392957600084156139115750858301515b600019600386901b1c1916600185901b1785556138be565b600085815260208120601f198616915b8281101561395857888601518255948401946001909101908401613939565b50858210156139765787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60006020828403121561399857600080fd5b5051919050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b039390931683526020830191909152604082015260600190565b80820281158282048414176109ec576109ec613823565b600082613a1857634e487b7160e01b600052601260045260246000fd5b500490565b60008060408385031215613a3057600080fd5b505080516020909101519092909150565b60008251613a53818460208701613506565b919091019291505056feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa2646970667358221220720e43dea4a62214f8a971deda5becee7b0947a2a48a0046d34b8191f5eb1b9964736f6c63430008120033000000000000000000000000efb0697700e5c489073a9bdf7ef94a2b2bc884a500000000000000000000000038e6357e895335cc92a6076a3ace5fff4869545f00000000000000000000000000000000000000000000000006f05b59d3b2000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000080000000000000000000000002254957426f17d301df996e1351a82bf79dd99a90000000000000000000000000000000000000000000000000000000000000004634554480000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046345544800000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x6080604052600436106102cd5760003560e01c80638f840ddd11610175578063c37f68e2116100dc578063f2b3abbd11610095578063f8f9da281161006f578063f8f9da281461084a578063fca7820b1461085f578063fcb641471461087f578063fe9c44ae1461088757600080fd5b8063f2b3abbd146107e5578063f3fdb15a14610805578063f851a4401461082557600080fd5b8063c37f68e2146106f7578063c5ebeaec14610737578063db006a7514610757578063dd62ed3e14610777578063e5974619146107bd578063e9c714f2146107d057600080fd5b8063aa5af0fd1161012e578063aa5af0fd14610664578063aae40a2a1461067a578063ae9d70b01461068d578063b2a02ff1146106a2578063b71d1a0c146106c2578063bd6d894d146106e257600080fd5b80638f840ddd146105c457806395d89b41146105da57806395dd9193146105ef57806399d8c1b41461060f578063a6afed951461062f578063a9059cbb1461064457600080fd5b80634576b5db116102345780636752e702116101ed57806370a08231116101c757806370a082311461054657806373acee981461057c5780637cb05b2914610591578063852a12e3146105a457600080fd5b80636752e7021461050057806369ab32501461051b5780636c540baf1461053057600080fd5b80634576b5db1461046d57806347bd37181461048d5780634e4d9fea146104a357806355a547d5146104ab5780635fe3b567146104c0578063601a0bf1146104e057600080fd5b8063182df0f511610286578063182df0f51461039f57806323b872dd146103b457806326782247146103d4578063313ce5671461040c5780633af9e669146104385780633b1d21a21461045857600080fd5b806306fdde03146102e2578063095ea7b31461030d5780631249c58b1461033d578063173b99041461034557806317bfdfbc1461036957806318160ddd1461038957600080fd5b366102dd576102db3461089c565b005b600080fd5b3480156102ee57600080fd5b506102f76108f4565b6040516103049190613556565b60405180910390f35b34801561031957600080fd5b5061032d61032836600461357e565b610982565b6040519015158152602001610304565b6102db6109f2565b34801561035157600080fd5b5061035b60085481565b604051908152602001610304565b34801561037557600080fd5b5061035b6103843660046135aa565b6109fd565b34801561039557600080fd5b5061035b600d5481565b3480156103ab57600080fd5b5061035b610a50565b3480156103c057600080fd5b5061032d6103cf3660046135c7565b610a5f565b3480156103e057600080fd5b506004546103f4906001600160a01b031681565b6040516001600160a01b039091168152602001610304565b34801561041857600080fd5b506003546104269060ff1681565b60405160ff9091168152602001610304565b34801561044457600080fd5b5061035b6104533660046135aa565b610aaf565b34801561046457600080fd5b5061035b610af5565b34801561047957600080fd5b5061035b6104883660046135aa565b610aff565b34801561049957600080fd5b5061035b600b5481565b6102db610c51565b3480156104b757600080fd5b5061035b610c5a565b3480156104cc57600080fd5b506005546103f4906001600160a01b031681565b3480156104ec57600080fd5b5061035b6104fb366004613608565b610d72565b34801561050c57600080fd5b5061035b666379da05b6000081565b34801561052757600080fd5b5061035b600081565b34801561053c57600080fd5b5061035b60095481565b34801561055257600080fd5b5061035b6105613660046135aa565b6001600160a01b03166000908152600e602052604090205490565b34801561058857600080fd5b5061035b610db1565b6102db61059f36600461357e565b610dfb565b3480156105b057600080fd5b5061035b6105bf366004613608565b610e09565b3480156105d057600080fd5b5061035b600c5481565b3480156105e657600080fd5b506102f7610e1c565b3480156105fb57600080fd5b5061035b61060a3660046135aa565b610e29565b34801561061b57600080fd5b506102db61062a3660046136c4565b610e34565b34801561063b57600080fd5b5061035b611081565b34801561065057600080fd5b5061032d61065f36600461357e565b61126e565b34801561067057600080fd5b5061035b600a5481565b6102db610688366004613770565b6112bd565b34801561069957600080fd5b5061035b6112c8565b3480156106ae57600080fd5b5061035b6106bd3660046135c7565b611360565b3480156106ce57600080fd5b5061035b6106dd3660046135aa565b6113af565b3480156106ee57600080fd5b5061035b61143c565b34801561070357600080fd5b506107176107123660046135aa565b61148c565b604080519485526020850193909352918301526060820152608001610304565b34801561074357600080fd5b5061035b610752366004613608565b6114cd565b34801561076357600080fd5b5061035b610772366004613608565b6114d8565b34801561078357600080fd5b5061035b610792366004613770565b6001600160a01b039182166000908152600f6020908152604080832093909416825291909152205490565b6102db6107cb3660046135aa565b6114e3565b3480156107dc57600080fd5b5061035b6114f0565b3480156107f157600080fd5b5061035b6108003660046135aa565b6115f7565b34801561081157600080fd5b506006546103f4906001600160a01b031681565b34801561083157600080fd5b506003546103f49061010090046001600160a01b031681565b34801561085657600080fd5b5061035b61160b565b34801561086b57600080fd5b5061035b61087a366004613608565b61165e565b61035b61169d565b34801561089357600080fd5b5061032d600181565b60005460ff166108c75760405162461bcd60e51b81526004016108be906137a9565b60405180910390fd5b6000805460ff191690556108d9611081565b506108e433826116a8565b506000805460ff19166001179055565b60018054610901906137cd565b80601f016020809104026020016040519081016040528092919081815260200182805461092d906137cd565b801561097a5780601f1061094f5761010080835404028352916020019161097a565b820191906000526020600020905b81548152906001019060200180831161095d57829003601f168201915b505050505081565b336000818152600f602090815260408083206001600160a01b03871680855292528083208590555191929182907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906109de9087815260200190565b60405180910390a360019150505b92915050565b6109fb3461089c565b565b6000805460ff16610a205760405162461bcd60e51b81526004016108be906137a9565b6000805460ff19169055610a32611081565b50610a3c82610e29565b90506000805460ff19166001179055919050565b6000610a5a61185e565b905090565b6000805460ff16610a825760405162461bcd60e51b81526004016108be906137a9565b6000805460ff19168155610a98338686866118c6565b1490506000805460ff191660011790559392505050565b6000806040518060200160405280610ac561143c565b90526001600160a01b0384166000908152600e6020526040902054909150610aee908290611af2565b9392505050565b6000610a5a611b12565b60035460009061010090046001600160a01b03163314610b325760405163d219dc1f60e01b815260040160405180910390fd5b60055460408051623f1ee960e11b815290516001600160a01b0392831692851691627e3dd29160048083019260209291908290030181865afa158015610b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ba09190613801565b610bec5760405162461bcd60e51b815260206004820152601c60248201527f6d61726b6572206d6574686f642072657475726e65642066616c73650000000060448201526064016108be565b600580546001600160a01b0319166001600160a01b0385811691821790925560408051928416835260208301919091527f7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d91015b60405180910390a150600092915050565b6109fb34611b1e565b600080610c65611b6f565b90506000610c7282611c16565b61ffff16905080600003610c9957604051632154bfcf60e21b815260040160405180910390fd5b610ca4600283613839565b915060005b81811015610d6c576000610cbc84611c50565b9050600080610ccc606887613839565b90506000610cda823661384c565b9050803592508265ffffffffffff16600003610d0957604051630336dc9d60e41b815260040160405180910390fd5b87600003610d21578265ffffffffffff169750610d49565b878365ffffffffffff1614610d495760405163d9d1f46560e01b815260040160405180910390fd5b610d538488613839565b9650505050508080610d649061385f565b915050610ca9565b50505090565b6000805460ff16610d955760405162461bcd60e51b81526004016108be906137a9565b6000805460ff19169055610da7611081565b50610a3c82611c84565b6000805460ff16610dd45760405162461bcd60e51b81526004016108be906137a9565b6000805460ff19169055610de6611081565b5050600b546000805460ff1916600117905590565b610e058282611d9f565b5050565b6000610e1482611df1565b506000919050565b60028054610901906137cd565b60006109ec82611e32565b60035461010090046001600160a01b03163314610e9f5760405162461bcd60e51b8152602060048201526024808201527f6f6e6c792061646d696e206d617920696e697469616c697a6520746865206d616044820152631c9ad95d60e21b60648201526084016108be565b600954158015610eaf5750600a54155b610f075760405162461bcd60e51b815260206004820152602360248201527f6d61726b6574206d6179206f6e6c7920626520696e697469616c697a6564206f6044820152626e636560e81b60648201526084016108be565b600784905583610f725760405162461bcd60e51b815260206004820152603060248201527f696e697469616c2065786368616e67652072617465206d75737420626520677260448201526f32b0ba32b9103a3430b7103d32b9379760811b60648201526084016108be565b6000610f7d87610aff565b90508015610fcd5760405162461bcd60e51b815260206004820152601a60248201527f73657474696e6720636f6d7074726f6c6c6572206661696c656400000000000060448201526064016108be565b43600955670de0b6b3a7640000600a55610fe686611e7e565b905080156110415760405162461bcd60e51b815260206004820152602260248201527f73657474696e6720696e7465726573742072617465206d6f64656c206661696c604482015261195960f21b60648201526084016108be565b600161104d85826138c6565b50600261105a84826138c6565b50506003805460ff90921660ff199283161790556000805490911660011790555050505050565b60095460009043908181036110995760009250505090565b60006110a3611b12565b600b54600c54600a546006546040516315f2405360e01b81526004810186905260248101859052604481018490529495509293919290916000916001600160a01b0316906315f2405390606401602060405180830381865afa15801561110d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111319190613986565b905065048c273950008111156111895760405162461bcd60e51b815260206004820152601c60248201527f626f72726f772072617465206973206162737572646c7920686967680000000060448201526064016108be565b6000611195878961384c565b905060006111b160405180602001604052808581525083611ff3565b905060006111bf8288611af2565b905060006111cd8883613839565b905060006111ec6040518060200160405280600854815250848a612024565b905060006111fb85898a612024565b60098e9055600a819055600b849055600c839055604080518d815260208101879052908101829052606081018590529091507f4dec04e750ca11537cabcd8a9eab06494de08da3735bc8871cd41250e190bc049060800160405180910390a160009d505050505050505050505050505090565b6000805460ff166112915760405162461bcd60e51b81526004016108be906137a9565b6000805460ff191681556112a7338086866118c6565b1490506000805460ff1916600117905592915050565b610e05823483612045565b6006546000906001600160a01b031663b81688166112e4611b12565b600b54600c546008546040516001600160e01b031960e087901b16815260048101949094526024840192909252604483015260648201526084015b602060405180830381865afa15801561133c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a5a9190613986565b6000805460ff166113835760405162461bcd60e51b81526004016108be906137a9565b6000805460ff1916905561139933858585612123565b50600080805460ff191660011790559392505050565b60035460009061010090046001600160a01b031633146113e257604051635cb56c2b60e01b815260040160405180910390fd5b600480546001600160a01b038481166001600160a01b031983168117909355604080519190921680825260208201939093527fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a99101610c40565b6000805460ff1661145f5760405162461bcd60e51b81526004016108be906137a9565b6000805460ff19169055611471611081565b5061147a610a50565b90506000805460ff1916600117905590565b6001600160a01b0381166000908152600e602052604081205481908190819081906114b687611e32565b6114be61185e565b93509350935093509193509193565b6000610e148261239b565b6000610e14826123da565b6114ed8134611d9f565b50565b6004546000906001600160a01b03163314158061150b575033155b1561152957604051631ba24f2960e21b815260040160405180910390fd5b60038054600480546001600160a01b03808216610100818102610100600160a81b0319871617968790556001600160a01b031990931690935560408051948390048216808652929095041660208401529290917ff9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc910160405180910390a1600454604080516001600160a01b03808516825290921660208301527fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9910160405180910390a160009250505090565b6000611601611081565b506109ec82611e7e565b6006546000906001600160a01b03166315f24053611627611b12565b600b54600c546040516001600160e01b031960e086901b16815260048101939093526024830191909152604482015260640161131f565b6000805460ff166116815760405162461bcd60e51b81526004016108be906137a9565b6000805460ff19169055611693611081565b50610a3c8261241b565b6000610a5a346124d7565b600554604051634ef4c3e160e01b81526000916001600160a01b031690634ef4c3e1906116dd9030908790879060040161399f565b6020604051808303816000875af11580156116fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117209190613986565b90508015611744576040516349abd4fd60e01b8152600481018290526024016108be565b4360095414611766576040516338d8859760e01b815260040160405180910390fd5b6000604051806020016040528061177b61185e565b90529050600061178b858561252e565b9050600061179982846125c0565b905080600d546117a99190613839565b600d556001600160a01b0386166000908152600e60205260409020546117d0908290613839565b6001600160a01b0387166000908152600e60205260409081902091909155517f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f90611820908890859085906139c3565b60405180910390a16040518181526001600160a01b038716903090600080516020613a5e8339815191529060200160405180910390a3505050505050565b600d5460009080820361187357505060075490565b600061187d611b12565b90506000600c54600b54836118929190613839565b61189c919061384c565b90506000836118b3670de0b6b3a7640000846139e4565b6118bd91906139fb565b95945050505050565b6005546040516317b9b84b60e31b81523060048201526001600160a01b038581166024830152848116604483015260648201849052600092839291169063bdcdc258906084016020604051808303816000875af115801561192b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061194f9190613986565b905080156119735760405163089d427760e11b8152600481018290526024016108be565b836001600160a01b0316856001600160a01b0316036119a557604051638cd22d1960e01b815260040160405180910390fd5b6000856001600160a01b0316876001600160a01b0316036119c957506000196119f1565b506001600160a01b038086166000908152600f60209081526040808320938a16835292905220545b60006119fd858361384c565b6001600160a01b0388166000908152600e602052604081205491925090611a2590879061384c565b6001600160a01b0388166000908152600e602052604081205491925090611a4d908890613839565b6001600160a01b03808b166000908152600e6020526040808220869055918b1681522081905590506000198414611aa7576001600160a01b03808a166000908152600f60209081526040808320938e168352929052208390555b876001600160a01b0316896001600160a01b0316600080516020613a5e83398151915289604051611ada91815260200190565b60405180910390a35060009998505050505050505050565b600080611aff8484611ff3565b9050611b0a816125de565b949350505050565b6000610a5a344761384c565b60005460ff16611b405760405162461bcd60e51b81526004016108be906137a9565b6000805460ff19169055611b52611081565b50611b5e3333836125f6565b50506000805460ff19166001179055565b60006602ed57011e0000601f1936013581161480611ba0576040516373bb264f60e11b815260040160405180910390fd5b60003660291115611bc457604051632bcb7bc560e11b815260040160405180910390fd5b5060281936013560006009611bdf600362ffffff8516613839565b611be99190613839565b905036611bf7600283613839565b1115610aee5760405163c30a7bd760e01b815260040160405180910390fd5b600080611c24602084613839565b905036811115611c4757604051632bcb7bc560e11b815260040160405180910390fd5b36033592915050565b6000806000611c5e8461279f565b9092509050604e611c70826020613839565b611c7a90846139e4565b611b0a9190613839565b600354600090819061010090046001600160a01b03163314611cb957604051630f7e5e6d60e41b815260040160405180910390fd5b4360095414611cdb57604051630dff50cb60e41b815260040160405180910390fd5b82611ce4611b12565b1015611d0357604051633345e99960e01b815260040160405180910390fd5b600c54831115611d26576040516378d2980560e11b815260040160405180910390fd5b82600c54611d34919061384c565b600c819055600354909150611d579061010090046001600160a01b0316846127f6565b7f3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e600360019054906101000a90046001600160a01b03168483604051610c40939291906139c3565b60005460ff16611dc15760405162461bcd60e51b81526004016108be906137a9565b6000805460ff19169055611dd3611081565b50611ddf3383836125f6565b50506000805460ff1916600117905550565b60005460ff16611e135760405162461bcd60e51b81526004016108be906137a9565b6000805460ff19169055611e25611081565b506108e433600083612831565b6001600160a01b038116600090815260106020526040812080548203611e5b5750600092915050565b600a548154600091611e6c916139e4565b9050816001015481611b0a91906139fb565b600354600090819061010090046001600160a01b03163314611eb35760405163407fded560e01b815260040160405180910390fd5b4360095414611ed557604051630be2a5cb60e11b815260040160405180910390fd5b600660009054906101000a90046001600160a01b03169050826001600160a01b0316632191f92a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f4f9190613801565b611f9b5760405162461bcd60e51b815260206004820152601c60248201527f6d61726b6572206d6574686f642072657475726e65642066616c73650000000060448201526064016108be565b600680546001600160a01b0319166001600160a01b0385811691821790925560408051928416835260208301919091527fedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f9269101610c40565b604080516020810190915260008152604051806020016040528061201b856000015185612b1f565b90529392505050565b6000806120318585611ff3565b90506118bd61203f826125de565b84612b2b565b60005460ff166120675760405162461bcd60e51b81526004016108be906137a9565b6000805460ff19169055612079611081565b506000816001600160a01b031663a6afed956040518163ffffffff1660e01b81526004016020604051808303816000875af11580156120bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120e09190613986565b9050801561210457604051633eea49b760e11b8152600481018290526024016108be565b61211033858585612b37565b50506000805460ff191660011790555050565b60055460405163d02f735160e01b81523060048201526001600160a01b0386811660248301528581166044830152848116606483015260848201849052600092169063d02f73519060a4016020604051808303816000875af115801561218d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121b19190613986565b905080156121d5576040516363e00e3360e11b8152600481018290526024016108be565b836001600160a01b0316836001600160a01b03160361220757604051633a94626760e11b815260040160405180910390fd5b6000612228836040518060200160405280666379da05b60000815250612fff565b90506000612236828561384c565b90506000604051806020016040528061224d61185e565b90529050600061225d8285611af2565b9050600081600c5461226f9190613839565b600c819055600d5490915061228590869061384c565b600d556001600160a01b0388166000908152600e60205260409020546122ac90889061384c565b6001600160a01b03808a166000908152600e602052604080822093909355908b16815220546122dc908590613839565b6001600160a01b03808b166000818152600e602052604090819020939093559151908a1690600080516020613a5e8339815191529061231e9088815260200190565b60405180910390a360405185815230906001600160a01b038a1690600080516020613a5e8339815191529060200160405180910390a37fa91e67c5ea634cd43a12c5a482724b03de01e85ca68702a53d0c2f45cb7c1dc5308383604051612387939291906139c3565b60405180910390a150505050505050505050565b60005460ff166123bd5760405162461bcd60e51b81526004016108be906137a9565b6000805460ff191690556123cf611081565b506108e43382613022565b60005460ff166123fc5760405162461bcd60e51b81526004016108be906137a9565b6000805460ff1916905561240e611081565b506108e433826000612831565b60035460009061010090046001600160a01b0316331461244e57604051631205b57b60e11b815260040160405180910390fd5b436009541461247057604051637dfca6b760e11b815260040160405180910390fd5b670de0b6b3a76400008211156124995760405163717220f360e11b815260040160405180910390fd5b600880549083905560408051828152602081018590527faaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f8214609101610c40565b6000805460ff166124fa5760405162461bcd60e51b81526004016108be906137a9565b6000805460ff1916905561250c611081565b50612516826131d2565b5050600090506000805460ff19166001179055919050565b6000336001600160a01b0384161461257a5760405162461bcd60e51b815260206004820152600f60248201526e0e6cadcc8cae440dad2e6dac2e8c6d608b1b60448201526064016108be565b8134146125ba5760405162461bcd60e51b815260206004820152600e60248201526d0ecc2d8eaca40dad2e6dac2e8c6d60931b60448201526064016108be565b50919050565b6000610aee6125d784670de0b6b3a7640000612b1f565b8351613266565b80516000906109ec90670de0b6b3a7640000906139fb565b600554604051631200453160e11b81523060048201526001600160a01b03858116602483015284811660448301526064820184905260009283929116906324008a62906084016020604051808303816000875af115801561265b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061267f9190613986565b905080156126a357604051638c81362d60e01b8152600481018290526024016108be565b43600954146126c55760405163c9021e2f60e01b815260040160405180910390fd5b60006126d085611e32565b9050600060001985146126e357846126e5565b815b905060006126f3888361252e565b90506000612701828561384c565b9050600082600b54612713919061384c565b6001600160a01b038a8116600081815260106020908152604091829020878155600a54600190910155600b8590558151938f168452830191909152810185905260608101849052608081018290529091507f1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a19060a00160405180910390a1509098975050505050505050565b6000808080806127b0604187613839565b905060006127c96127c2602084613839565b3690613272565b8035945090506127da816003613272565b62ffffff9490941697933563ffffffff16965092945050505050565b6040516001600160a01b0383169082156108fc029083906000818181858888f1935050505015801561282c573d6000803e3d6000fd5b505050565b81158061283c575080155b6128a55760405162461bcd60e51b815260206004820152603460248201527f6f6e65206f662072656465656d546f6b656e73496e206f722072656465656d416044820152736d6f756e74496e206d757374206265207a65726f60601b60648201526084016108be565b600060405180602001604052806128ba61185e565b9052905060008084156128db578491506128d48386611af2565b90506128eb565b6128e584846125c0565b91508390505b600063eabe7d9160e01b30888560405160240161290a9392919061399f565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915260055490915060009061295a906001600160a01b031683600161327e565b90506000818060200190518101906129729190613986565b905080156129965760405163480f424760e01b8152600481018290526024016108be565b43600954146129b8576040516397b5cfcd60e01b815260040160405180910390fd5b836129c1611b12565b10156129e0576040516391240a1b60e01b815260040160405180910390fd5b84600d546129ee919061384c565b600d556001600160a01b0389166000908152600e6020526040902054612a1590869061384c565b6001600160a01b038a166000908152600e6020526040902055612a3889856127f6565b60405185815230906001600160a01b038b1690600080516020613a5e8339815191529060200160405180910390a37fe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a929898587604051612a99939291906139c3565b60405180910390a16005546040516351dff98960e01b81523060048201526001600160a01b038b811660248301526044820187905260648201889052909116906351dff98990608401600060405180830381600087803b158015612afc57600080fd5b505af1158015612b10573d6000803e3d6000fd5b50505050505050505050505050565b6000610aee82846139e4565b6000610aee8284613839565b604080513060248201526001600160a01b0383811660448301528681166064830152858116608483015260a48083018690528351808403909101815260c49092019092526020810180516001600160e01b0316632fe3f38f60e11b1790526005549091600091612baa911683600161327e565b9050600081806020019051810190612bc29190613986565b90508015612be657604051630a14d17960e11b8152600481018290526024016108be565b4360095414612c08576040516380965b1b60e01b815260040160405180910390fd5b43846001600160a01b0316636c540baf6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c6b9190613986565b14612c8957604051631046f38d60e31b815260040160405180910390fd5b866001600160a01b0316866001600160a01b031603612cbb57604051631bd1a62160e21b815260040160405180910390fd5b84600003612cdc5760405163d29da7ef60e01b815260040160405180910390fd5b6000198503612cfe57604051635982c5bb60e11b815260040160405180910390fd5b6000612d0b8888886125f6565b9050600063c488847b60e01b308784604051602401612d2c9392919061399f565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152600554909150600090612d7a906001600160a01b031683613312565b905060008082806020019051810190612d939190613a1d565b9150915060008214612e035760405162461bcd60e51b815260206004820152603360248201527f4c49515549444154455f434f4d5054524f4c4c45525f43414c43554c4154455f604482015272105353d5539517d4d152569157d19052531151606a1b60648201526084016108be565b6040516370a0823160e01b81526001600160a01b038c811660048301528291908b16906370a0823190602401602060405180830381865afa158015612e4c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e709190613986565b1015612ebe5760405162461bcd60e51b815260206004820152601860248201527f4c49515549444154455f5345495a455f544f4f5f4d554348000000000000000060448201526064016108be565b306001600160a01b038a1603612edf57612eda308d8d84612123565b612f98565b6000896001600160a01b031663b2a02ff18e8e856040518463ffffffff1660e01b8152600401612f119392919061399f565b6020604051808303816000875af1158015612f30573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f549190613986565b14612f985760405162461bcd60e51b81526020600482015260146024820152731d1bdad95b881cd95a5e9d5c994819985a5b195960621b60448201526064016108be565b604080516001600160a01b038e811682528d811660208301528183018890528b1660608201526080810183905290517f298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb529181900360a00190a1505050505050505050505050565b6000670de0b6b3a7640000613018848460000151612b1f565b610aee91906139fb565b600063da3d454c60e01b3084846040516024016130419392919061399f565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152600554909150600090613091906001600160a01b031683600161327e565b90506000818060200190518101906130a99190613986565b905080156130cd5760405163918db40f60e01b8152600481018290526024016108be565b43600954146130ef57604051630e8d8c6160e21b815260040160405180910390fd5b836130f8611b12565b1015613117576040516348c2588160e01b815260040160405180910390fd5b600061312286611e32565b905060006131308683613839565b9050600086600b546131429190613839565b6001600160a01b0389166000908152601060205260409020838155600a54600190910155600b819055905061317788886127f6565b604080516001600160a01b038a16815260208101899052908101839052606081018290527f13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab809060800160405180910390a15050505050505050565b600080808043600954146131fc576040516338acf79960e01b8152600481018290526024016108be565b613206338661252e565b905080600c546132169190613839565b915081600c819055507fa91e67c5ea634cd43a12c5a482724b03de01e85ca68702a53d0c2f45cb7c1dc5338284604051613252939291906139c3565b60405180910390a160009590945092505050565b6000610aee82846139fb565b6000610aee828461384c565b6060600061328b84613395565b9050600080866001600160a01b0316856132a65760006132a8565b345b846040516132b69190613a41565b60006040518083038185875af1925050503d80600081146132f3576040519150601f19603f3d011682016040523d82523d6000602084013e6132f8565b606091505b50915091506133078282613424565b979650505050505050565b6060600061331f83613395565b9050600080856001600160a01b03168360405161333c9190613a41565b600060405180830381855afa9150503d8060008114613377576040519150601f19603f3d011682016040523d82523d6000602084013e61337c565b606091505b509150915061338b8282613424565b9695505050505050565b805160609060006133a461349b565b905060006133b28284613839565b9050368211156133d557604051632bcb7bc560e11b815260040160405180910390fd5b6060604051905081815285602001848101826020015b818310156134035782518152602092830192016133eb565b50505082833603856020018301379190920181016020016040529392505050565b6060826125ba57815160000361344d57604051632b3ff13d60e11b815260040160405180910390fd5b602082015162461bcd60e51b148015613480576040516301efd04f60e31b815260448401906108be908290600401613556565b8260405163fd36fde360e01b81526004016108be9190613556565b6000806134a6611b6f565b905060006134b382611c16565b61ffff1690506134c4600283613839565b915060005b818110156134fe5760006134dc84611c50565b90506134e88185613839565b93505080806134f69061385f565b9150506134c9565b509092915050565b60005b83811015613521578181015183820152602001613509565b50506000910152565b60008151808452613542816020860160208601613506565b601f01601f19169290920160200192915050565b602081526000610aee602083018461352a565b6001600160a01b03811681146114ed57600080fd5b6000806040838503121561359157600080fd5b823561359c81613569565b946020939093013593505050565b6000602082840312156135bc57600080fd5b8135610aee81613569565b6000806000606084860312156135dc57600080fd5b83356135e781613569565b925060208401356135f781613569565b929592945050506040919091013590565b60006020828403121561361a57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261364857600080fd5b813567ffffffffffffffff8082111561366357613663613621565b604051601f8301601f19908116603f0116810190828211818310171561368b5761368b613621565b816040528381528660208588010111156136a457600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c087890312156136dd57600080fd5b86356136e881613569565b955060208701356136f881613569565b945060408701359350606087013567ffffffffffffffff8082111561371c57600080fd5b6137288a838b01613637565b9450608089013591508082111561373e57600080fd5b5061374b89828a01613637565b92505060a087013560ff8116811461376257600080fd5b809150509295509295509295565b6000806040838503121561378357600080fd5b823561378e81613569565b9150602083013561379e81613569565b809150509250929050565b6020808252600a90820152691c994b595b9d195c995960b21b604082015260600190565b600181811c908216806137e157607f821691505b6020821081036125ba57634e487b7160e01b600052602260045260246000fd5b60006020828403121561381357600080fd5b81518015158114610aee57600080fd5b634e487b7160e01b600052601160045260246000fd5b808201808211156109ec576109ec613823565b818103818111156109ec576109ec613823565b60006001820161387157613871613823565b5060010190565b601f82111561282c57600081815260208120601f850160051c8101602086101561389f5750805b601f850160051c820191505b818110156138be578281556001016138ab565b505050505050565b815167ffffffffffffffff8111156138e0576138e0613621565b6138f4816138ee84546137cd565b84613878565b602080601f83116001811461392957600084156139115750858301515b600019600386901b1c1916600185901b1785556138be565b600085815260208120601f198616915b8281101561395857888601518255948401946001909101908401613939565b50858210156139765787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60006020828403121561399857600080fd5b5051919050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b039390931683526020830191909152604082015260600190565b80820281158282048414176109ec576109ec613823565b600082613a1857634e487b7160e01b600052601260045260246000fd5b500490565b60008060408385031215613a3057600080fd5b505080516020909101519092909150565b60008251613a53818460208701613506565b919091019291505056feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa2646970667358221220720e43dea4a62214f8a971deda5becee7b0947a2a48a0046d34b8191f5eb1b9964736f6c63430008120033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000efb0697700e5c489073a9bdf7ef94a2b2bc884a500000000000000000000000038e6357e895335cc92a6076a3ace5fff4869545f00000000000000000000000000000000000000000000000006f05b59d3b2000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000080000000000000000000000002254957426f17d301df996e1351a82bf79dd99a90000000000000000000000000000000000000000000000000000000000000004634554480000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046345544800000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : comptroller_ (address): 0xEFB0697700E5c489073a9BDF7EF94a2B2bc884a5
Arg [1] : interestRateModel_ (address): 0x38e6357E895335cC92a6076a3aCE5FFf4869545F
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] : 000000000000000000000000efb0697700e5c489073a9bdf7ef94a2b2bc884a5
Arg [1] : 00000000000000000000000038e6357e895335cc92a6076a3ace5fff4869545f
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
113078:5527:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;117489:23;117502:9;117489:12;:23::i;:::-;113078:5527;;;;;11881:18;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;56367:246;;;;;;;;;;-1:-1:-1;56367:246:0;;;;;:::i;:::-;;:::i;:::-;;;1391:14:1;;1384:22;1366:41;;1354:2;1339:18;56367:246:0;1226:187:1;114438:75:0;;;:::i;13104:33::-;;;;;;;;;;;;;;;;;;;1564:25:1;;;1552:2;1537:18;13104:33:0;1418:177:1;60086:174:0;;;;;;;;;;-1:-1:-1;60086:174:0;;;;;:::i;:::-;;:::i;13749:23::-;;;;;;;;;;;;;;;;62233:120;;;;;;;;;;;;;:::i;55696:192::-;;;;;;;;;;-1:-1:-1;55696:192:0;;;;;:::i;:::-;;:::i;12554:35::-;;;;;;;;;;-1:-1:-1;12554:35:0;;;;-1:-1:-1;;;;;12554:35:0;;;;;;-1:-1:-1;;;;;2493:32:1;;;2475:51;;2463:2;2448:18;12554:35:0;2313:219:1;12077:21:0;;;;;;;;;;-1:-1:-1;12077:21:0;;;;;;;;;;;2709:4:1;2697:17;;;2679:36;;2667:2;2652:18;12077:21:0;2537:184:1;57662:232:0;;;;;;;;;;-1:-1:-1;57662:232:0;;;;;:::i;:::-;;:::i;63553:97::-;;;;;;;;;;;;;:::i;91686:693::-;;;;;;;;;;-1:-1:-1;91686:693:0;;;;;:::i;:::-;;:::i;13513:24::-;;;;;;;;;;;;;;;;116015:89;;;:::i;40436:1448::-;;;;;;;;;;;;;:::i;12680:39::-;;;;;;;;;;-1:-1:-1;12680:39:0;;;;-1:-1:-1;;;;;12680:39:0;;;96683:280;;;;;;;;;;-1:-1:-1;96683:280:0;;;;;:::i;:::-;;:::i;14644:56::-;;;;;;;;;;;;14694:6;14644:56;;8301:33;;;;;;;;;;;;8333:1;8301:33;;13227:30;;;;;;;;;;;;;;;;57285:121;;;;;;;;;;-1:-1:-1;57285:121:0;;;;;:::i;:::-;-1:-1:-1;;;;;57378:20:0;57351:7;57378:20;;;:13;:20;;;;;;;57285:121;59653:142;;;;;;;;;;;;;:::i;116430:160::-;;;;;;:::i;:::-;;:::i;115352:152::-;;;;;;;;;;-1:-1:-1;115352:152:0;;;;;:::i;:::-;;:::i;13643:25::-;;;;;;;;;;;;;;;;11977:20;;;;;;;;;;;;;:::i;60469:144::-;;;;;;;;;;-1:-1:-1;60469:144:0;;;;;:::i;:::-;;:::i;51379:1505::-;;;;;;;;;;-1:-1:-1;51379:1505:0;;;;;:::i;:::-;;:::i;63898:2570::-;;;;;;;;;;;;;:::i;55207:182::-;;;;;;;;;;-1:-1:-1;55207:182:0;;;;;:::i;:::-;;:::i;13378:23::-;;;;;;;;;;;;;;;;116942:166;;;;;;:::i;:::-;;:::i;59314:193::-;;;;;;;;;;;;;:::i;86681:224::-;;;;;;;;;;-1:-1:-1;86681:224:0;;;;;:::i;:::-;;:::i;89873:604::-;;;;;;;;;;-1:-1:-1;89873:604:0;;;;;:::i;:::-;;:::i;61835:148::-;;;;;;;;;;;;;:::i;58240:292::-;;;;;;;;;;-1:-1:-1;58240: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;58240:292:0;6064:391:1;115772:132:0;;;;;;;;;;-1:-1:-1;115772:132:0;;;;;:::i;:::-;;:::i;114864:::-;;;;;;;;;;-1:-1:-1;114864:132:0;;;;;:::i;:::-;;:::i;56943:152::-;;;;;;;;;;-1:-1:-1;56943:152:0;;;;;:::i;:::-;-1:-1:-1;;;;;57053:25:0;;;57026:7;57053:25;;;:18;:25;;;;;;;;:34;;;;;;;;;;;;;56943:152;116295:127;;;;;;:::i;:::-;;:::i;90755:706::-;;;;;;;;;;;;;:::i;98996:321::-;;;;;;;;;;-1:-1:-1;98996:321:0;;;;;:::i;:::-;;:::i;12821:42::-;;;;;;;;;;-1:-1:-1;12821:42:0;;;;-1:-1:-1;;;;;12821:42:0;;;12443:28;;;;;;;;;;-1:-1:-1;12443:28:0;;;;;;;-1:-1:-1;;;;;12443:28:0;;;58968:170;;;;;;;;;;;;;:::i;92682:307::-;;;;;;;;;;-1:-1:-1;92682:307:0;;;;;:::i;:::-;;:::i;117267:113::-;;;:::i;14865:36::-;;;;;;;;;;;;14897:4;14865:36;;66738:244;102139:11;;;;102131:34;;;;-1:-1:-1;;;102131:34:0;;;;;;;:::i;:::-;;;;;;;;;102190:5;102176:19;;-1:-1:-1;;102176:19:0;;;66810:16:::1;:14;:16::i;:::-;;66941:33;66951:10;66963;66941:9;:33::i;:::-;-1:-1:-1::0;102218:11:0;:18;;-1:-1:-1;;102218:18:0;102232:4;102218:18;;;66738:244::o;11881:18::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;56367:246::-;56475:10;56444:4;56496:23;;;:18;:23;;;;;;;;-1:-1:-1;;;;;56496:32:0;;;;;;;;;;:41;;;56553:30;56444:4;;56475:10;;;56553:30;;;;56531:6;1564:25:1;;1552:2;1537:18;;1418:177;56553:30:0;;;;;;;;56601:4;56594:11;;;56367:246;;;;;:::o;114438:75::-;114482:23;114495:9;114482:12;:23::i;:::-;114438:75::o;60086:174::-;60173:4;102139:11;;;;102131:34;;;;-1:-1:-1;;;102131:34:0;;;;;;;:::i;:::-;102190:5;102176:19;;-1:-1:-1;;102176:19:0;;;60190:16:::1;:14;:16::i;:::-;;60224:28;60244:7;60224:19;:28::i;:::-;60217:35;;102218:11:::0;:18;;-1:-1:-1;;102218:18:0;102232:4;102218:18;;;60086:174;;-1:-1:-1;60086:174:0:o;62233:120::-;62293:4;62317:28;:26;:28::i;:::-;62310:35;;62233:120;:::o;55696:192::-;55800:4;102139:11;;;;102131:34;;;;-1:-1:-1;;;102131:34:0;;;;;;;:::i;:::-;102190:5;102176:19;;-1:-1:-1;;102176:19:0;;;55824:44:::1;55839:10;55851:3:::0;55856;55861:6;55824:14:::1;:44::i;:::-;:56;55817:63;;102218:11:::0;:18;;-1:-1:-1;;102218:18:0;102232:4;102218:18;;;55696:192;;-1:-1:-1;;;55696:192:0:o;57662:232::-;57733:4;57750:23;57776:38;;;;;;;;57791:21;:19;:21::i;:::-;57776:38;;-1:-1:-1;;;;;57865:20:0;;;;;;:13;:20;;;;;;57750:64;;-1:-1:-1;57832:54:0;;57750:64;;57832:18;:54::i;:::-;57825:61;57662:232;-1:-1:-1;;;57662:232:0:o;63553:97::-;63604:4;63628:14;:12;:14::i;91686:693::-;91842:5;;91773:4;;91842:5;;;-1:-1:-1;;;;;91842:5:0;91828:10;:19;91824:85;;91871:26;;-1:-1:-1;;;91871:26:0;;;;;;;;;;;91824:85;91959:11;;92056:30;;;-1:-1:-1;;;92056:30:0;;;;-1:-1:-1;;;;;91959:11:0;;;;92056:28;;;;;:30;;;;;;;;;;;;;;:28;:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;92048:71;;;;-1:-1:-1;;;92048:71:0;;8571:2:1;92048:71:0;;;8553:21:1;8610:2;8590:18;;;8583:30;8649;8629:18;;;8622:58;8697:18;;92048:71:0;8369:352:1;92048:71:0;92187:11;:28;;-1:-1:-1;;;;;;92187:28:0;-1:-1:-1;;;;;92187:28:0;;;;;;;;;92297:46;;;9012:15:1;;;8994:34;;9059:2;9044:18;;9037:43;;;;92297:46:0;;8929:18:1;92297:46:0;;;;;;;;-1:-1:-1;8333:1:0;;91686:693;-1:-1:-1;;91686:693:0:o;116015:89::-;116066:30;116086:9;116066:19;:30::i;40436:1448::-;40506:26;40541:30;40574:36;:34;:36::i;:::-;40541:69;;40617:25;40645:61;40683:22;40645:37;:61::i;:::-;40617:89;;;;40719:17;40740:1;40719:22;40715:98;;40759:46;;-1:-1:-1;;;40759:46:0;;;;;;;;;;;40715:98;40821:48;31844:1;40821:48;;:::i;:::-;;;40881:24;40876:1003;40930:17;40911:16;:36;40876:1003;;;40978:27;41008:47;41032:22;41008:23;:47::i;:::-;40978:77;-1:-1:-1;41126:27:0;;41239:88;32496:3;41239:22;:88;:::i;:::-;41204:124;-1:-1:-1;41337:23:0;41363:41;41204:124;41363:8;:41;:::i;:::-;41337:67;;41470:15;41457:29;41433:53;;41509:20;:25;;41533:1;41509:25;41505:94;;41554:35;;-1:-1:-1;;;41554:35:0;;;;;;;;;;;41505:94;41613:18;41635:1;41613:23;41609:207;;41670:20;41649:41;;;;41609:207;;;41734:18;41710:20;:42;;;41706:110;;41772:34;;-1:-1:-1;;;41772:34:0;;;;;;;;;;;41706:110;41826:45;41852:19;41826:45;;:::i;:::-;;;40969:910;;;;40949:18;;;;;:::i;:::-;;;;40876:1003;;;;40534:1350;;40436:1448;:::o;96683:280::-;96767:4;102139:11;;;;102131:34;;;;-1:-1:-1;;;102131:34:0;;;;;;;:::i;:::-;102190:5;102176:19;;-1:-1:-1;;102176:19:0;;;96784:16:::1;:14;:16::i;:::-;;96921:34;96942:12;96921:20;:34::i;59653:142::-:0;59724:4;102139:11;;;;102131:34;;;;-1:-1:-1;;;102131:34:0;;;;;;;:::i;:::-;102190:5;102176:19;;-1:-1:-1;;102176:19:0;;;59741:16:::1;:14;:16::i;:::-;-1:-1:-1::0;;59775:12:0::1;::::0;102218:11;:18;;-1:-1:-1;;102218:18:0;102232:4;102218:18;;;59653:142;:::o;116430:160::-;116534:48;116560:8;116570:11;116534:25;:48::i;:::-;116430:160;;:::o;115352:152::-;115415:4;115432:38;115457:12;115432:24;:38::i;:::-;-1:-1:-1;8333:1:0;;115352:152;-1:-1:-1;115352:152:0:o;11977:20::-;;;;;;;:::i;60469:144::-;60545:4;60569:36;60597:7;60569:27;:36::i;51379:1505::-;51733:5;;;;;-1:-1:-1;;;;;51733:5:0;51719:10;:19;51711:68;;;;-1:-1:-1;;;51711:68:0;;9828:2:1;51711: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;;51711:68:0;9626:400:1;51711:68:0;51798:18;;:23;:43;;;;-1:-1:-1;51825:11:0;;:16;51798:43;51790:91;;;;-1:-1:-1;;;51790:91:0;;10233:2:1;51790: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;;51790:91:0;10031:399:1;51790:91:0;51932:27;:58;;;52009:31;52001:92;;;;-1:-1:-1;;;52001:92:0;;10637:2:1;52001: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;;52001:92:0;10435:412:1;52001:92:0;52138:8;52149:29;52165:12;52149:15;:29::i;:::-;52138:40;-1:-1:-1;52197:15:0;;52189:54;;;;-1:-1:-1;;;52189:54:0;;11054:2:1;52189:54:0;;;11036:21:1;11093:2;11073:18;;;11066:30;11132:28;11112:18;;;11105:56;11178:18;;52189:54:0;10852:350:1;52189:54:0;58772:12;52362:18;:37;25213:4;52410:11;:25;52535:46;52562:18;52535:26;:46::i;:::-;52529:52;-1:-1:-1;52600:15:0;;52592:62;;;;-1:-1:-1;;;52592:62:0;;11409:2:1;52592: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;;52592:62:0;11207:398:1;52592:62:0;52667:4;:12;52674:5;52667:4;:12;:::i;:::-;-1:-1:-1;52690:6:0;:16;52699:7;52690:6;:16;:::i;:::-;-1:-1:-1;;52717:8:0;:20;;;;;;-1:-1:-1;;52717:20:0;;;;;;:8;52858:18;;;;;52717:20;52858:18;;;-1:-1:-1;;;;;51379:1505:0:o;63898:2570::-;64107:18;;63957:4;;58772:12;;64195:45;;;64191:93;;8333:1;64257:15;;;;63898:2570;:::o;64191:93::-;64351:14;64368;:12;:14::i;:::-;64413:12;;64457:13;;64505:11;;64613:17;;:71;;-1:-1:-1;;;64613:71:0;;;;;14016:25:1;;;14057:18;;;14050:34;;;14100:18;;;14093:34;;;64351:31:0;;-1:-1:-1;64413:12:0;;64457:13;;64505:11;;64393:17;;-1:-1:-1;;;;;64613:17:0;;:31;;13989:18:1;;64613:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;64587:97;;12224:9;64703:18;:43;;64695:84;;;;-1:-1:-1;;;64695:84:0;;14529:2:1;64695:84:0;;;14511:21:1;14568:2;14548:18;;;14541:30;14607;14587:18;;;14580:58;14655:18;;64695:84:0;14327:352:1;64695:84:0;64869:15;64887:44;64908:23;64887:18;:44;:::i;:::-;64869:62;;65423:31;65457:53;65462:35;;;;;;;;65477:18;65462:35;;;65499:10;65457:4;:53::i;:::-;65423:87;;65521:24;65548:54;65567:20;65589:12;65548:18;:54::i;:::-;65521:81;-1:-1:-1;65613:20:0;65636:34;65658:12;65521:81;65636:34;:::i;:::-;65613:57;;65681:21;65705:101;65731:38;;;;;;;;65746:21;;65731:38;;;65771:19;65792:13;65705:25;:101::i;:::-;65681:125;;65817:19;65839:83;65865:20;65887:16;65905;65839:25;:83::i;:::-;66126:18;:39;;;66176:11;:28;;;66215:12;:30;;;66256:13;:32;;;66353:79;;;6295:25:1;;;6351:2;6336:18;;6329:34;;;6379:18;;;6372:34;;;6437:2;6422:18;;6415:34;;;66176:28:0;;-1:-1:-1;66353:79:0;;6282:3:1;6267:19;66353:79:0;;;;;;;8333:1;66445:15;;;;;;;;;;;;;;;63898:2570;:::o;55207:182::-;55294:4;102139:11;;;;102131:34;;;;-1:-1:-1;;;102131:34:0;;;;;;;:::i;:::-;102190:5;102176:19;;-1:-1:-1;;102176:19:0;;;55318:51:::1;55333:10;::::0;55357:3;55362:6;55318:14:::1;:51::i;:::-;:63;55311:70;;102218:11:::0;:18;;-1:-1:-1;;102218:18:0;102232:4;102218:18;;;55207:182;;-1:-1:-1;;55207:182:0:o;116942:166::-;117038:62;117062:8;117072:9;117083:16;117038:23;:62::i;59314:193::-;59400:17;;59376:4;;-1:-1:-1;;;;;59400:17:0;:31;59432:14;:12;:14::i;:::-;59448:12;;59462:13;;59477:21;;59400:99;;-1:-1:-1;;;;;;59400:99:0;;;;;;;;;;6295:25:1;;;;6336:18;;;6329:34;;;;6379:18;;;6372:34;6422:18;;;6415:34;6267:19;;59400:99:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;86681:224::-;86792:4;102139:11;;;;102131:34;;;;-1:-1:-1;;;102131:34:0;;;;;;;:::i;:::-;102190:5;102176:19;;-1:-1:-1;;102176:19:0;;;86809:60:::1;86823:10;86835::::0;86847:8;86857:11;86809:13:::1;:60::i;:::-;-1:-1:-1::0;8333:1:0::1;102218:11:::0;:18;;-1:-1:-1;;102218:18:0;102232:4;102218:18;;;86681:224;;-1:-1:-1;;;86681:224:0:o;89873:604::-;90027:5;;89959:4;;90027:5;;;-1:-1:-1;;;;;90027:5:0;90013:10;:19;90009:86;;90056:27;;-1:-1:-1;;;90056:27:0;;;;;;;;;;;90009:86;90194:12;;;-1:-1:-1;;;;;90277:30:0;;;-1:-1:-1;;;;;;90277:30:0;;;;;;;90392:49;;;90194:12;;;;8994:34:1;;;9059:2;9044:18;;9037:43;;;;90392:49:0;;8929:18:1;90392:49:0;8726:360:1;61835:148:0;61904:4;102139:11;;;;102131:34;;;;-1:-1:-1;;;102131:34:0;;;;;;;:::i;:::-;102190:5;102176:19;;-1:-1:-1;;102176:19:0;;;61921:16:::1;:14;:16::i;:::-;;61955:20;:18;:20::i;:::-;61948:27;;102218:11:::0;:18;;-1:-1:-1;;102218:18:0;102232:4;102218:18;;;61835:148;:::o;58240:292::-;-1:-1:-1;;;;;58397:22:0;;58317:4;58397:22;;;:13;:22;;;;;;58317:4;;;;;;;;58434:36;58411:7;58434:27;:36::i;:::-;58485:28;:26;:28::i;:::-;58352:172;;;;;;;;58240:292;;;;;:::o;115772:132::-;115825:4;115842:28;115857:12;115842:14;:28::i;114864:132::-;114917:4;114934:28;114949:12;114934:14;:28::i;116295:127::-;116368:46;116394:8;116404:9;116368:25;:46::i;:::-;116295:127;:::o;90755:706::-;90912:12;;90806:4;;-1:-1:-1;;;;;90912:12:0;90898:10;:26;;;:54;;-1:-1:-1;90928:10:0;:24;90898:54;90894:124;;;90976:30;;-1:-1:-1;;;90976:30:0;;;;;;;;;;;90894:124;91102:5;;;91144:12;;;-1:-1:-1;;;;;91144:12:0;;;91102:5;91217:20;;;-1:-1:-1;;;;;;91217:20:0;;;;;;;-1:-1:-1;;;;;;91286:34:0;;;;;;91338:25;;;91102:5;;;;;;8994:34:1;;;91357:5:0;;;;;9059:2:1;9044:18;;9037:43;91102:5:0;91144:12;;91338:25;;8929:18:1;91338:25:0;;;;;;;91412:12;;91379:46;;;-1:-1:-1;;;;;9012:15:1;;;8994:34;;91412:12:0;;;9059:2:1;9044:18;;9037:43;91379:46:0;;8929:18:1;91379:46:0;;;;;;;8333:1;91438:15;;;;90755:706;:::o;98996:321::-;99092:4;99109:16;:14;:16::i;:::-;;99261:48;99288:20;99261:26;:48::i;58968:170::-;59054:17;;59030:4;;-1:-1:-1;;;;;59054:17:0;:31;59086:14;:12;:14::i;:::-;59102:12;;59116:13;;59054:76;;-1:-1:-1;;;;;;59054:76:0;;;;;;;;;;14016:25:1;;;;14057:18;;;14050:34;;;;14100:18;;;14093:34;13989:18;;59054:76:0;13814:319:1;92682:307:0;92780:4;102139:11;;;;102131:34;;;;-1:-1:-1;;;102131:34:0;;;;;;;:::i;:::-;102190:5;102176:19;;-1:-1:-1;;102176:19:0;;;92797:16:::1;:14;:16::i;:::-;;92933:48;92956:24;92933:22;:48::i;117267:113::-:0;117317:4;117341:31;117362:9;117341:20;:31::i;67323:2215::-;67450:11;;:58;;-1:-1:-1;;;67450:58:0;;67435:12;;-1:-1:-1;;;;;67450:11:0;;:23;;:58;;67482:4;;67489:6;;67497:10;;67450:58;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;67435:73;-1:-1:-1;67523:12:0;;67519:85;;67559:33;;-1:-1:-1;;;67559:33:0;;;;;1564:25:1;;;1537:18;;67559:33:0;1418:177:1;67519:85:0;58772:12;67692:18;;:38;67688:98;;67754:20;;-1:-1:-1;;;67754:20:0;;;;;;;;;;;67688:98;67798:23;67824:45;;;;;;;;67839:28;:26;:28::i;:::-;67824:45;;67798:71;-1:-1:-1;68478:21:0;68502:32;68515:6;68523:10;68502:12;:32::i;:::-;68478:56;;68727:15;68745:36;68750:16;68768:12;68745:4;:36::i;:::-;68727:54;;69115:10;69101:11;;:24;;;;:::i;:::-;69087:11;:38;-1:-1:-1;;;;;69160:21:0;;;;;;:13;:21;;;;;;:34;;69184:10;;69160:34;:::i;:::-;-1:-1:-1;;;;;69136:21:0;;;;;;:13;:21;;;;;;;:58;;;;69270:42;;;;;69150:6;;69283:16;;69301:10;;69270:42;:::i;:::-;;;;;;;;69328:43;;1564:25:1;;;-1:-1:-1;;;;;69328:43:0;;;69345:4;;-1:-1:-1;;;;;;;;;;;69328:43:0;1552:2:1;1537:18;69328:43:0;;;;;;;67384:2154;;;;67323:2215;;:::o;62603:780::-;62709:11;;62672:4;;62735:17;;;62731:645;;-1:-1:-1;;62908:27:0;;;62603:780::o;62731:645::-;63117:14;63134;:12;:14::i;:::-;63117:31;;63163:33;63226:13;;63211:12;;63199:9;:24;;;;:::i;:::-;:40;;;;:::i;:::-;63163:76;-1:-1:-1;63254:17:0;63316:12;63274:39;25213:4;63163:76;63274:39;:::i;:::-;:54;;;;:::i;:::-;63254:74;62603:780;-1:-1:-1;;;;;62603:780:0:o;53350:1596::-;53524:11;;:60;;-1:-1:-1;;;53524:60:0;;53560:4;53524:60;;;16395:34:1;-1:-1:-1;;;;;16465:15:1;;;16445:18;;;16438:43;16517:15;;;16497:18;;;16490:43;16549:18;;;16542:34;;;53448:4:0;;;;53524:11;;;:27;;16329:19:1;;53524:60:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;53509:75;-1:-1:-1;53599:12:0;;53595:89;;53635:37;;-1:-1:-1;;;53635:37:0;;;;;1564:25:1;;;1537:18;;53635:37:0;1418:177:1;53595:89:0;53750:3;-1:-1:-1;;;;;53743:10:0;:3;-1:-1:-1;;;;;53743:10:0;;53739:70;;53777:20;;-1:-1:-1;;;53777:20:0;;;;;;;;;;;53739:70;53886:22;53938:3;-1:-1:-1;;;;;53927:14:0;:7;-1:-1:-1;;;;;53927:14:0;;53923:166;;-1:-1:-1;;;53923:166:0;;;-1:-1:-1;;;;;;54045:23:0;;;;;;;:18;:23;;;;;;;;:32;;;;;;;;;;53923:166;54167:17;54187:26;54207:6;54187:17;:26;:::i;:::-;-1:-1:-1;;;;;54244:18:0;;54224:17;54244:18;;;:13;:18;;;;;;54167:46;;-1:-1:-1;54224:17:0;54244:27;;54265:6;;54244:27;:::i;:::-;-1:-1:-1;;;;;54302:18:0;;54282:17;54302:18;;;:13;:18;;;;;;54224:47;;-1:-1:-1;54282:17:0;54302:27;;54323:6;;54302:27;:::i;:::-;-1:-1:-1;;;;;54463:18:0;;;;;;;:13;:18;;;;;;:33;;;54507:18;;;;;;:33;;;54282:47;-1:-1:-1;;;54613:35:0;;54609:115;;-1:-1:-1;;;;;54665:23:0;;;;;;;:18;:23;;;;;;;;:32;;;;;;;;;:47;;;54609:115;54795:3;-1:-1:-1;;;;;54781:26:0;54790:3;-1:-1:-1;;;;;54781:26:0;-1:-1:-1;;;;;;;;;;;54800:6:0;54781:26;;;;1564:25:1;;1552:2;1537:18;;1418:177;54781:26:0;;;;;;;;-1:-1:-1;8333:1:0;;53350:1596;-1:-1:-1;;;;;;;;;53350:1596:0:o;25935:174::-;26013:4;26030:18;26051:15;26056:1;26059:6;26051:4;:15::i;:::-;26030:36;;26084:17;26093:7;26084:8;:17::i;:::-;26077:24;25935:174;-1:-1:-1;;;;25935:174:0:o;117788:121::-;117844:4;117868:33;117892:9;117868:21;:33;:::i;77768:261::-;102139:11;;;;102131:34;;;;-1:-1:-1;;;102131:34:0;;;;;;;:::i;:::-;102190:5;102176:19;;-1:-1:-1;;102176:19:0;;;77848:16:::1;:14;:16::i;:::-;;77968:53;77985:10;77997;78009:11;77968:16;:53::i;:::-;-1:-1:-1::0;;102218:11:0;:18;;-1:-1:-1;;102218:18:0;102232:4;102218:18;;;77768:261::o;42298:1200::-;42367:7;42679:20;-1:-1:-1;;42542:14:0;42538:37;42525:51;42654:46;;42610:99;;42722:83;;42767:30;;-1:-1:-1;;;42767:30:0;;;;;;;;;;;42722:83;42890:31;42975:8;32958:2;42932:58;42928:113;;;43008:25;;-1:-1:-1;;;43008:25:0;;;;;;;;;;;42928:113;-1:-1:-1;;;43120:14:0;43116:61;43093:93;43199:30;32200:1;43232:64;32147:1;43232:64;;;;:::i;:::-;:92;;;;:::i;:::-;43199:125;-1:-1:-1;43385:8:0;43335:47;31844:1;43199:125;43335:47;:::i;:::-;:65;43331:126;;;43418:31;;-1:-1:-1;;;43418:31:0;;;;;;;;;;;43583:540;43700:24;;43785:41;31229:2;43785:22;:41;:::i;:::-;43736:90;-1:-1:-1;43878:8:0;43837:56;;43833:111;;;43911:25;;-1:-1:-1;;;43911:25:0;;;;;;;;;;;43833:111;44016:14;44012:59;43989:91;;43583:540;-1:-1:-1;;43583:540:0:o;41890:402::-;41978:7;42003:23;42035:34;42079:63;42119:22;42079:39;:63::i;:::-;41994:148;;-1:-1:-1;41994:148:0;-1:-1:-1;32652:2:0;42191:49;41994:148;32018:2;42191:49;:::i;:::-;42165:76;;:15;:76;:::i;:::-;:121;;;;:::i;97240:1387::-;97451:5;;97307:4;;;;97451:5;;;-1:-1:-1;;;;;97451:5:0;97437:10;:19;97433:85;;97480:26;;-1:-1:-1;;;97480:26:0;;;;;;;;;;;97433:85;58772:12;97622:18;;:38;97618:104;;97684:26;;-1:-1:-1;;;97684:26:0;;;;;;;;;;;97618:104;97828:12;97811:14;:12;:14::i;:::-;:29;97807:101;;;97864:32;;-1:-1:-1;;;97864:32:0;;;;;;;;;;;97807:101;98000:13;;97985:12;:28;97981:98;;;98037:30;;-1:-1:-1;;;98037:30:0;;;;;;;;;;;97981:98;98247:12;98231:13;;:28;;;;:::i;:::-;98333:13;:32;;;98499:5;;98333:32;;-1:-1:-1;98485:34:0;;98499:5;;;-1:-1:-1;;;;;98499:5:0;98506:12;98485:13;:34::i;:::-;98537:54;98553:5;;;;;;;;;-1:-1:-1;;;;;98553:5:0;98560:12;98574:16;98537:54;;;;;;;;:::i;78268:283::-;102139:11;;;;102131:34;;;;-1:-1:-1;;;102131:34:0;;;;;;;:::i;:::-;102190:5;102176:19;;-1:-1:-1;;102176:19:0;;;78372:16:::1;:14;:16::i;:::-;;78492:51;78509:10;78521:8;78531:11;78492:16;:51::i;:::-;-1:-1:-1::0;;102218:11:0;:18;;-1:-1:-1;;102218:18:0;102232:4;102218:18;;;-1:-1:-1;78268:283:0:o;70335:252::-;102139:11;;;;102131:34;;;;-1:-1:-1;;;102131:34:0;;;;;;;:::i;:::-;102190:5;102176:19;;-1:-1:-1;;102176:19:0;;;70421:16:::1;:14;:16::i;:::-;;70530:49;70550:10;70563:1;70566:12;70530:11;:49::i;60867:813::-:0;-1:-1:-1;;;;;61050:23:0;;60944:4;61050:23;;;:14;:23;;;;;61279:24;;:29;;61275:70;;-1:-1:-1;61332:1:0;;60867:813;-1:-1:-1;;60867:813:0:o;61275:70::-;61593:11;;61566:24;;61539;;61566:38;;;:::i;:::-;61539:65;;61644:14;:28;;;61622:19;:50;;;;:::i;99647:1201::-;99947:5;;99741:4;;;;99947:5;;;-1:-1:-1;;;;;99947:5:0;99933:10;:19;99929:91;;99976:32;;-1:-1:-1;;;99976:32:0;;;;;;;;;;;99929:91;58772:12;100124:18;;:38;100120:110;;100186:32;;-1:-1:-1;;;100186:32:0;;;;;;;;;;;100120:110;100324:17;;;;;;;;;-1:-1:-1;;;;;100324:17:0;100301:40;;100444:20;-1:-1:-1;;;;;100444:40:0;;:42;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;100436:83;;;;-1:-1:-1;;;100436:83:0;;8571:2:1;100436:83:0;;;8553:21:1;8610:2;8590:18;;;8583:30;8649;8629:18;;;8622:58;8697:18;;100436:83:0;8369:352:1;100436:83:0;100596:17;:40;;-1:-1:-1;;;;;;100596:40:0;-1:-1:-1;;;;;100596:40:0;;;;;;;;;100742:70;;;9012:15:1;;;8994:34;;9059:2;9044:18;;9037:43;;;;100742:70:0;;8929:18:1;100742:70:0;8726:360:1;28670:133:0;-1:-1:-1;;;;;;;;;;;;28759:36:0;;;;;;;;28774:19;28779:1;:10;;;28791:1;28774:4;:19::i;:::-;28759:36;;28752:43;28670:133;-1:-1:-1;;;28670:133:0:o;26254:208::-;26352:4;26369:18;26390:15;26395:1;26398:6;26390:4;:15::i;:::-;26369:36;;26423:31;26428:17;26437:7;26428:8;:17::i;:::-;26447:6;26423:4;:31::i;81652:633::-;102139:11;;;;102131:34;;;;-1:-1:-1;;;102131:34:0;;;;;;;:::i;:::-;102190:5;102176:19;;-1:-1:-1;;102176:19:0;;;81788:16:::1;:14;:16::i;:::-;;81817:10;81830:16;-1:-1:-1::0;;;;;81830:31:0::1;;:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;81817:46:::0;-1:-1:-1;81878:17:0;;81874:227:::1;;82043:46;::::0;-1:-1:-1;;;82043:46:0;;::::1;::::0;::::1;1564:25:1::0;;;1537:18;;82043:46:0::1;1418:177:1::0;81874:227:0::1;82204:73;82225:10;82237:8;82247:11;82260:16;82204:20;:73::i;:::-;-1:-1:-1::0;;102218:11:0;:18;;-1:-1:-1;;102218:18:0;102232:4;102218:18;;;-1:-1:-1;;81652:633:0:o;87492:1932::-;87668:11;;:87;;-1:-1:-1;;;87668:87:0;;87701:4;87668: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;;;87653:12:0;;87668:11;;:24;;17535:19:1;;87668:87:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;87653:102;-1:-1:-1;87770:12:0;;87766:95;;87806:43;;-1:-1:-1;;;87806:43:0;;;;;1564:25:1;;;1537:18;;87806:43:0;1418:177:1;87766:95:0;87934:10;-1:-1:-1;;;;;87922:22:0;:8;-1:-1:-1;;;;;87922:22:0;;87918:98;;87968:36;;-1:-1:-1;;;87968:36:0;;;;;;;;;;;87918:98;88303:24;88330:62;88335:11;88348:43;;;;;;;;14694:6;88348:43;;;88330:4;:62::i;:::-;88303:89;-1:-1:-1;88403:26:0;88432:33;88303:89;88432:11;:33;:::i;:::-;88403:62;;88476:23;88502:45;;;;;;;;88517:28;:26;:28::i;:::-;88502:45;;88476:71;-1:-1:-1;88558:24:0;88585:53;88476:71;88618:19;88585:18;:53::i;:::-;88558:80;;88649:21;88689:19;88673:13;;:35;;;;:::i;:::-;88903:13;:32;;;88960:11;;88649:59;;-1:-1:-1;88960:33:0;;88974:19;;88960:33;:::i;:::-;88946:11;:47;-1:-1:-1;;;;;89030:23:0;;;;;;:13;:23;;;;;;:37;;89056:11;;89030:37;:::i;:::-;-1:-1:-1;;;;;89004:23:0;;;;;;;:13;:23;;;;;;:63;;;;89106:25;;;;;;;:49;;89134:21;;89106:49;:::i;:::-;-1:-1:-1;;;;;89078:25:0;;;;;;;:13;:25;;;;;;;:77;;;;89210:53;;;;;;-1:-1:-1;;;;;;;;;;;89210:53:0;;;89241:21;1564:25:1;;1552:2;1537:18;;1418:177;89210:53:0;;;;;;;;89279:54;;1564:25:1;;;89306:4:0;;-1:-1:-1;;;;;89279:54:0;;;-1:-1:-1;;;;;;;;;;;89279:54:0;1552:2:1;1537:18;89279:54:0;;;;;;;89349:67;89371:4;89378:19;89399:16;89349:67;;;;;;;;:::i;:::-;;;;;;;;87601:1823;;;;;;87492:1932;;;;:::o;74688:239::-;102139:11;;;;102131:34;;;;-1:-1:-1;;;102131:34:0;;;;;;;:::i;:::-;102190:5;102176:19;;-1:-1:-1;;102176:19:0;;;74764:16:::1;:14;:16::i;:::-;;74873:46;74893:10;74906:12;74873:11;:46::i;69801:242::-:0;102139:11;;;;102131:34;;;;-1:-1:-1;;;102131:34:0;;;;;;;:::i;:::-;102190:5;102176:19;;-1:-1:-1;;102176:19:0;;;69877:16:::1;:14;:16::i;:::-;;69986:49;70006:10;70019:12;70033:1;69986:11;:49::i;93257:838::-:0;93407:5;;93338:4;;93407:5;;;-1:-1:-1;;;;;93407:5:0;93393:10;:19;93389:87;;93436:28;;-1:-1:-1;;;93436:28:0;;;;;;;;;;;93389:87;58772:12;93561:18;;:38;93557:106;;93623:28;;-1:-1:-1;;;93623:28:0;;;;;;;;;;;93557:106;12364:4;93733:24;:51;93729:120;;;93808:29;;-1:-1:-1;;;93808:29:0;;;;;;;;;;;93729:120;93893:21;;;93925:48;;;;93991:68;;;18020:25:1;;;18076:2;18061:18;;18054:34;;;93991:68:0;;17993:18:1;93991:68:0;17846:248:1;94351:284:0;94428:4;102139:11;;;;102131:34;;;;-1:-1:-1;;;102131:34:0;;;;;;;:::i;:::-;102190:5;102176:19;;-1:-1:-1;;102176:19:0;;;94445:16:::1;:14;:16::i;:::-;;94573:28;94591:9;94573:17;:28::i;:::-;;;8333:1;94612:15;;102218:11:::0;:18;;-1:-1:-1;;102218:18:0;102232:4;102218:18;;;94351:284;;-1:-1:-1;94351:284:0:o;118150:254::-;118226:4;118277:10;-1:-1:-1;;;;;118277:18:0;;;118269:46;;;;-1:-1:-1;;;118269:46:0;;18301:2:1;118269:46:0;;;18283:21:1;18340:2;18320:18;;;18313:30;-1:-1:-1;;;18359:18:1;;;18352:45;18414:18;;118269:46:0;18099:339:1;118269:46:0;118347:6;118334:9;:19;118326:46;;;;-1:-1:-1;;;118326:46:0;;18645:2:1;118326:46:0;;;18627:21:1;18684:2;18664:18;;;18657:30;-1:-1:-1;;;18703:18:1;;;18696:44;18757:18;;118326:46:0;18443:338:1;118326:46:0;-1:-1:-1;118390:6:0;118150:254;-1:-1:-1;118150:254:0:o;29818:126::-;29877:4;29901:35;29906:17;29911:1;25213:4;29906;:17::i;:::-;29925:10;;29901:4;:35::i;25609:213::-;25791:12;;25666:4;;25791:23;;25213:4;;25791:23;:::i;78939:2319::-;79113:11;;:75;;-1:-1:-1;;;79113:75:0;;79152:4;79113:75;;;16395:34:1;-1:-1:-1;;;;;16465:15:1;;;16445:18;;;16438:43;16517:15;;;16497:18;;;16490:43;16549:18;;;16542:34;;;79034:4:0;;;;79113:11;;;:30;;16329:19:1;;79113:75:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;79098:90;-1:-1:-1;79203:12:0;;79199:92;;79239:40;;-1:-1:-1;;;79239:40:0;;;;;1564:25:1;;;1537:18;;79239:40:0;1418:177:1;79199:92:0;58772:12;79379:18;;:38;79375:105;;79441:27;;-1:-1:-1;;;79441:27:0;;;;;;;;;;;79375:105;79572:23;79598:37;79626:8;79598:27;:37::i;:::-;79572:63;;79714:21;-1:-1:-1;;79738:11:0;:29;:64;;79791:11;79738:64;;;79770:18;79738:64;79714:88;;80376:22;80401:37;80414:5;80421:16;80401:12;:37::i;:::-;80376:62;-1:-1:-1;80699:22:0;80724:38;80376:62;80724:18;:38;:::i;:::-;80699:63;;80773:20;80811:17;80796:12;;:32;;;;:::i;:::-;-1:-1:-1;;;;;80911:24:0;;;;;;;:14;:24;;;;;;;;;:54;;;81017:11;;80976:38;;;;:52;81039:12;:30;;;81130: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;;;81039:30:0;;-1:-1:-1;81130:83:0;;19032:3:1;19017:19;81130:83:0;;;;;;;-1:-1:-1;81233:17:0;;78939:2319;-1:-1:-1;;;;;;;;78939:2319:0:o;44950:1053::-;45083:23;;;;;45442:45;31739:2;45442:36;:45;:::i;:::-;45409:78;-1:-1:-1;45494:22:0;45519:62;45539:41;31229:2;45409:78;45539:41;:::i;:::-;45519:8;;:19;:62::i;:::-;45626:28;;;-1:-1:-1;45494:87:0;-1:-1:-1;45729:40:0;45494:87;31899:1;45729:18;:40::i;:::-;45900:34;;;;;;45825:28;;45941:56;;;-1:-1:-1;45900:34:0;;-1:-1:-1;;;;;44950:1053:0:o;118412:190::-;118575:19;;-1:-1:-1;;;;;118575:11:0;;;:19;;;;;118587:6;;118575:19;;;;118587:6;118575:11;:19;;;;;;;;;;;;;;;;;;;;;118412:190;;:::o;71147:3362::-;71264:19;;;:42;;-1:-1:-1;71287:19:0;;71264:42;71256:107;;;;-1:-1:-1;;;71256:107:0;;19512:2:1;71256: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;;71256:107:0;19310:416:1;71256:107:0;71436:23;71462:46;;;;;;;;71477:28;:26;:28::i;:::-;71462:46;;71436:72;-1:-1:-1;71521:17:0;;71619:18;;71615:757;;71910:14;71895:29;;71954:48;71973:12;71987:14;71954:18;:48::i;:::-;71939:63;;71615:757;;;72282:34;72287:14;72303:12;72282:4;:34::i;:::-;72267:49;;72346:14;72331:29;;71615:757;72454:28;72522:43;;;72588:4;72609:8;72633:12;72485:171;;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;72485:171:0;;;;;;;;;;;;;;-1:-1:-1;;;;;72485:171:0;-1:-1:-1;;;;;;72485:171:0;;;;;;;;;;72734:11;;72485:171;;-1:-1:-1;;;72698:108:0;;-1:-1:-1;;;;;72734:11:0;72485:171;72734:11;72698:13;:108::i;:::-;72669:137;;72819:12;72845:13;72834:36;;;;;;;;;;;;:::i;:::-;72819:51;-1:-1:-1;72885:12:0;;72881:87;;72921:35;;-1:-1:-1;;;72921:35:0;;;;;1564:25:1;;;1537:18;;72921:35:0;1418:177:1;72881:87:0;58772:12;73056:18;;:38;73052:100;;73118:22;;-1:-1:-1;;;73118:22:0;;;;;;;;;;;73052:100;73250:12;73233:14;:12;:14::i;:::-;:29;73229:99;;;73286:30;;-1:-1:-1;;;73286:30:0;;;;;;;;;;;73229:99;73686:12;73672:11;;:26;;;;:::i;:::-;73658:11;:40;-1:-1:-1;;;;;73735:23:0;;;;;;:13;:23;;;;;;:38;;73761:12;;73735:38;:::i;:::-;-1:-1:-1;;;;;73709:23:0;;;;;;:13;:23;;;;;:64;74149:37;73723:8;74173:12;74149:13;:37::i;:::-;74264:47;;1564:25:1;;;74291:4:0;;-1:-1:-1;;;;;74264:47:0;;;-1:-1:-1;;;;;;;;;;;74264:47:0;1552:2:1;1537:18;74264:47:0;;;;;;;74327:44;74334:8;74344:12;74358;74327:44;;;;;;;;:::i;:::-;;;;;;;;74424:11;;:77;;-1:-1:-1;;;74424:77:0;;74457:4;74424:77;;;20404:34:1;-1:-1:-1;;;;;20474:15:1;;;20454:18;;;20447:43;20506:18;;;20499:34;;;20549:18;;;20542:34;;;74424:11:0;;;;:24;;20338:19:1;;74424:77:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;71245:3264;;;;;;71147:3362;;;:::o;29407:90::-;29460:4;29484:5;29488:1;29484;:5;:::i;27983:90::-;28036:4;28060:5;28064:1;28060;:5;:::i;82764:3356::-;83008:244;;;83120:4;83008: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;;;83008:244:0;;;;;;;;;;17535:19:1;;;;83008:244:0;;;;;;;;-1:-1:-1;;;;;83008:244:0;-1:-1:-1;;;83008:244:0;;;83330:11;;83008:244;;-1:-1:-1;;83294:108:0;;83330:11;83008:244;83330:11;83294:13;:108::i;:::-;83265:137;;83415:12;83441:13;83430:33;;;;;;;;;;;;:::i;:::-;83415:48;-1:-1:-1;83480:12:0;;83476:90;;83516:38;;-1:-1:-1;;;83516:38:0;;;;;1564:25:1;;;1537:18;;83516:38:0;1418:177:1;83476:90:0;58772:12;83654:18;;:38;83650:103;;83716:25;;-1:-1:-1;;;83716:25:0;;;;;;;;;;;83650:103;58772:12;83858:16;-1:-1:-1;;;;;83858:35:0;;:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:57;83854:132;;83939:35;;-1:-1:-1;;;83939:35:0;;;;;;;;;;;83854:132;84059:10;-1:-1:-1;;;;;84047:22:0;:8;-1:-1:-1;;;;;84047:22:0;;84043:93;;84093:31;;-1:-1:-1;;;84093:31:0;;;;;;;;;;;84043:93;84191:11;84206:1;84191:16;84187:84;;84231:28;;-1:-1:-1;;;84231:28:0;;;;;;;;;;;84187:84;-1:-1:-1;;84327:11:0;:29;84323:100;;84380:31;;-1:-1:-1;;;84380:31:0;;;;;;;;;;;84323:100;84476:22;84501:51;84518:10;84530:8;84540:11;84501:16;:51::i;:::-;84476:76;;84794:29;84863:59;;;84945:4;84974:16;85007:17;84826:209;;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;84826:209:0;;;;;;;;;;;;;;-1:-1:-1;;;;;84826:209:0;-1:-1:-1;;;;;;84826:209:0;;;;;;;;;;85118:11;;84826:209;;-1:-1:-1;;;85078:94:0;;-1:-1:-1;;;;;85118:11:0;84826:209;85078:17;:94::i;:::-;85048:124;;85186:21;85209:16;85240:14;85229:40;;;;;;;;;;;;:::i;:::-;85185:84;;;;8333:1;85292:16;:28;85284:92;;;;-1:-1:-1;;;85284:92:0;;21039:2:1;85284: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;;85284:92:0;20837:415:1;85284:92:0;85470:36;;-1:-1:-1;;;85470:36:0;;-1:-1:-1;;;;;2493:32:1;;;85470:36:0;;;2475:51:1;85510:11:0;;85470:26;;;;;;2448:18:1;;85470:36:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:51;;85462:88;;;;-1:-1:-1;;;85462:88:0;;21667:2:1;85462:88:0;;;21649:21:1;21706:2;21686:18;;;21679:30;21745:26;21725:18;;;21718:54;21789:18;;85462:88:0;21465:348:1;85462:88:0;85720:4;-1:-1:-1;;;;;85683:42:0;;;85679:273;;85742:63;85764:4;85771:10;85783:8;85793:11;85742:13;:63::i;:::-;85679:273;;;8333:1;85846:16;-1:-1:-1;;;;;85846:22:0;;85869:10;85881:8;85891:11;85846:57;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:69;85838:102;;;;-1:-1:-1;;;85838:102:0;;22020:2:1;85838:102:0;;;22002:21:1;22059:2;22039:18;;;22032:30;-1:-1:-1;;;22078:18:1;;;22071:50;22138:18;;85838:102:0;21818:344:1;85838:102:0;86016: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;;;86016:96:0;;;;;;;22413:3:1;86016:96:0;;;82893:3227;;;;;;;;82764:3356;;;;:::o;28811:121::-;28870:4;25213;28894:19;28899:1;28902;:10;;;28894:4;:19::i;:::-;:30;;;;:::i;75104:2505::-;75260:28;75328:43;;;75394:4;75415:8;75439:12;75291:171;;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;75291:171:0;;;;;;;;;;;;;;-1:-1:-1;;;;;75291:171:0;-1:-1:-1;;;;;;75291:171:0;;;;;;;;;;75540:11;;75291:171;;-1:-1:-1;;;75504:108:0;;-1:-1:-1;;;;;75540:11:0;75291:171;75540:11;75504:13;:108::i;:::-;75475:137;;75625:12;75651:13;75640:36;;;;;;;;;;;;:::i;:::-;75625:51;-1:-1:-1;75693:12:0;;75689:87;;75729:35;;-1:-1:-1;;;75729:35:0;;;;;1564:25:1;;;1537:18;;75729:35:0;1418:177:1;75689:87:0;58772:12;75864:18;;:38;75860:100;;75926:22;;-1:-1:-1;;;75926:22:0;;;;;;;;;;;75860:100;76069:12;76052:14;:12;:14::i;:::-;:29;76048:93;;;76105:24;;-1:-1:-1;;;76105:24:0;;;;;;;;;;;76048:93;76388:23;76414:37;76442:8;76414:27;:37::i;:::-;76388:63;-1:-1:-1;76462:22:0;76487:33;76508:12;76388:63;76487:33;:::i;:::-;76462:58;;76531:20;76569:12;76554;;:27;;;;:::i;:::-;-1:-1:-1;;;;;76912:24:0;;;;;;:14;:24;;;;;:54;;;77018:11;;76977:38;;;;:52;77040:12;:30;;;76531:50;-1:-1:-1;77442:37:0;76927:8;77466:12;77442:13;:37::i;:::-;77535: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;;;77535:66:0;;22926:3:1;22911:19;77535:66:0;;;;;;;75179:2430;;;;;;75104:2505;;:::o;94975:1453::-;95036:4;;;;58772:12;95260:18;;:38;95256:122;;95322:44;;-1:-1:-1;;;95322:44:0;;;;;1564:25:1;;;1537:18;;95322:44:0;1418:177:1;95256:122:0;95967:35;95980:10;95992:9;95967:12;:35::i;:::-;95949:53;;96050:15;96034:13;;:31;;;;:::i;:::-;96015:50;;96158:16;96142:13;:32;;;;96263:60;96277:10;96289:15;96306:16;96263:60;;;;;;;;:::i;:::-;;;;;;;;8333:1;;96404:15;;-1:-1:-1;94975:1453:0;-1:-1:-1;;;94975:1453:0:o;30429:90::-;30482:4;30506:5;30510:1;30506;:5;:::i;36162:98::-;36220:7;36247:5;36251:1;36247;:5;:::i;46376:389::-;46511:12;46532:20;46555:32;46571:15;46555;:32::i;:::-;46532:55;;46597:12;46611:19;46641:15;-1:-1:-1;;;;;46641:20:0;46669:12;:28;;46696:1;46669:28;;;46684:9;46669:28;46699:7;46641:66;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;46596:111;;;;46723:36;46743:7;46752:6;46723:19;:36::i;:::-;46716:43;46376:389;-1:-1:-1;;;;;;;46376:389:0:o;47108:335::-;47228:12;47252:20;47275:32;47291:15;47275;:32::i;:::-;47252:55;;47315:12;47329:19;47352:15;-1:-1:-1;;;;;47352:26:0;47379:7;47352:35;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;47314:73;;;;47401:36;47421:7;47430:6;47401:19;:36::i;:::-;47394:43;47108:335;-1:-1:-1;;;;;;47108:335:0:o;47449:1738::-;47583:22;;47526:12;;47547:33;47646:29;:27;:29::i;:::-;47612:63;-1:-1:-1;47682:29:0;47714:51;47612:63;47714:25;:51;:::i;:::-;47682:83;-1:-1:-1;47804:8:0;47778:41;;47774:96;;;47837:25;;-1:-1:-1;;;47837:25:0;;;;;;;;;;;47774:96;47878:20;47942:15;47936:22;47925:33;;48116:21;48107:7;48100:38;48246:15;48224:20;48220:42;48297:25;48291:4;48287:36;48369:7;48347:20;48343:34;48193:431;48397:7;48391:4;48387:18;48193:431;;;48603:11;;48592:23;;48435:16;48425:27;;;;48468:25;48193:431;;;48197:189;;;48866:23;48821;48805:14;48801:44;48752:25;48730:20;48726:52;48717:7;48713:66;48690:232;49043:55;;;;49030:69;;49112:20;49014:129;48988:15;48971:181;49034:7;47449:1738;-1:-1:-1;;;47449:1738:0:o;49787:859::-;49889:12;49918:7;49913:706;;49942:6;:13;49959:1;49942:18;49938:674;;49980:34;;-1:-1:-1;;;49980:34:0;;;;;;;;;;;49938:674;50145:20;50133:33;;50127:40;-1:-1:-1;;;50203:49:0;50275:328;;;;50459:52;;-1:-1:-1;;;50459:52:0;;50409:17;50397:30;;;50459:52;;50397:30;;50459:52;;;:::i;50275:328::-;50584:6;50549:42;;-1:-1:-1;;;50549:42:0;;;;;;;;:::i;49193:588::-;49254:7;49270:30;49303:36;:34;:36::i;:::-;49270:69;;49346:25;49374:61;49412:22;49374:37;:61::i;:::-;49346:89;;;-1:-1:-1;49442:48:0;31844:1;49442:48;;:::i;:::-;;;49502:24;49497:241;49551:17;49532:16;:36;49497:241;;;49599:27;49629:47;49653:22;49629:23;:47::i;:::-;49599:77;-1:-1:-1;49685:45:0;49599:77;49685:45;;:::i;:::-;;;49590:148;49570:18;;;;;:::i;:::-;;;;49497:241;;;-1:-1:-1;49753:22:0;;49193:588;-1:-1:-1;;49193: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://720e43dea4a62214f8a971deda5becee7b0947a2a48a0046d34b8191f5eb1b99
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 27 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
SCROLL | Ether (ETH) | 100.00% | $2,626.53 | 7.9255 | $20,816.57 |
[ 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.