Source Code
Overview
GLMR Balance
GLMR Value
$0.00| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Latest 25 internal transactions (View All)
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 3052917 | 1061 days ago | 0 GLMR | ||||
| 3052917 | 1061 days ago | 0 GLMR | ||||
| 3052917 | 1061 days ago | 0 GLMR | ||||
| 3052917 | 1061 days ago | 0 GLMR | ||||
| 3052917 | 1061 days ago | 0 GLMR | ||||
| 3052917 | 1061 days ago | 0 GLMR | ||||
| 3052917 | 1061 days ago | 0 GLMR | ||||
| 3052917 | 1061 days ago | 0 GLMR | ||||
| 3052917 | 1061 days ago | 0 GLMR | ||||
| 3052917 | 1061 days ago | 0 GLMR | ||||
| 3052917 | 1061 days ago | 0 GLMR | ||||
| 3052917 | 1061 days ago | 0 GLMR | ||||
| 3052917 | 1061 days ago | 0 GLMR | ||||
| 3052917 | 1061 days ago | 0 GLMR | ||||
| 3052917 | 1061 days ago | 0 GLMR | ||||
| 3052917 | 1061 days ago | 0 GLMR | ||||
| 3052917 | 1061 days ago | 0 GLMR | ||||
| 3052917 | 1061 days ago | 0 GLMR | ||||
| 3052917 | 1061 days ago | 0 GLMR | ||||
| 3052917 | 1061 days ago | 0 GLMR | ||||
| 3052917 | 1061 days ago | 0 GLMR | ||||
| 3052917 | 1061 days ago | 0 GLMR | ||||
| 3052917 | 1061 days ago | 0 GLMR | ||||
| 3052917 | 1061 days ago | 0 GLMR | ||||
| 3052914 | 1061 days ago | 0 GLMR |
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
CErc20Delegate
Compiler Version
v0.8.10+commit.fc410830
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.0;
import "./CErc20.sol";
import "./CDelegateInterface.sol";
/**
* @title Compound's CErc20Delegate Contract
* @notice CTokens which wrap an EIP-20 underlying and are delegated to
* @author Compound
*/
contract CErc20Delegate is CDelegateInterface, CErc20 {
/**
* @notice Called by the delegator on a delegate to initialize it for duty
* @param data The encoded bytes data for any initialization
*/
function _becomeImplementation(bytes memory data) public virtual override {
require(msg.sender == address(this) || hasAdminRights(), "!self || !admin");
}
/**
* @notice Called by the delegator on a delegate to forfeit its responsibility
*/
function _resignImplementation() internal virtual {
// Shh -- we don't ever want this hook to be marked pure
if (false) {
implementation = address(0);
}
}
/**
* @dev Internal function 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 _setImplementationInternal(
address implementation_,
bool allowResign,
bytes memory becomeImplementationData
) internal {
// Check whitelist
require(
IFuseFeeDistributor(fuseAdmin).cErc20DelegateWhitelist(implementation, implementation_, allowResign),
"!impl"
);
// Call _resignImplementation internally (this delegate's code)
if (allowResign) _resignImplementation();
address oldImplementation = implementation;
implementation = implementation_;
// add the extensions of the new implementation
address[] memory latestExtensions = IFuseFeeDistributor(fuseAdmin).getCErc20DelegateExtensions(implementation);
address[] memory currentExtensions = LibDiamond.listExtensions();
// removed the current (old) extensions
for (uint256 i = 0; i < currentExtensions.length; i++) {
LibDiamond.removeExtension(DiamondExtension(currentExtensions[i]));
}
// add the new extensions
for (uint256 i = 0; i < latestExtensions.length; i++) {
LibDiamond.addExtension(DiamondExtension(latestExtensions[i]));
}
if (address(this).code.length == 0) {
// cannot delegate to self with an external call when constructing
_becomeImplementation(becomeImplementationData);
} else {
// Call _becomeImplementation externally (delegating to new delegate's code)
_functionCall(
address(this),
abi.encodeWithSignature("_becomeImplementation(bytes)", becomeImplementationData),
"!become"
);
}
emit NewImplementation(oldImplementation, implementation);
}
/**
* @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 _setImplementationSafe(
address implementation_,
bool allowResign,
bytes calldata becomeImplementationData
) external override {
// Check admin rights
require(hasAdminRights(), "!admin");
// Set implementation
if (implementation != implementation_) {
_setImplementationInternal(implementation_, allowResign, becomeImplementationData);
}
}
/**
* @notice Function called before all delegator functions
* @dev Checks comptroller.autoImplementation and upgrades the implementation if necessary
*/
function _prepare() external payable override {
if (msg.sender != address(this) && ComptrollerV3Storage(address(comptroller)).autoImplementation()) {
(address latestCErc20Delegate, bool allowResign, bytes memory becomeImplementationData) = IFuseFeeDistributor(
fuseAdmin
).latestCErc20Delegate(implementation);
if (implementation != latestCErc20Delegate) {
_setImplementationInternal(latestCErc20Delegate, allowResign, becomeImplementationData);
}
}
}
function contractType() external pure virtual override returns (string memory) {
return "CErc20Delegate";
}
}// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.0;
contract CDelegationStorage {
/**
* @notice Implementation address for this contract
*/
address public implementation;
}
abstract contract CDelegateInterface 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 _setImplementationSafe(
address implementation_,
bool allowResign,
bytes calldata becomeImplementationData
) external virtual;
/**
* @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 calldata data) public virtual;
/**
* @notice Function called before all delegator functions
* @dev Checks comptroller.autoImplementation and upgrades the implementation if necessary
*/
function _prepare() external payable virtual;
function contractType() external pure virtual returns (string memory);
}// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.0;
import "./CToken.sol";
import { CErc20Interface } from "./CTokenInterfaces.sol";
/**
* @title Compound's CErc20 Contract
* @notice CTokens which wrap an EIP-20 underlying
* @dev This contract should not to be deployed on its own; instead, deploy `CErc20Delegator` (proxy contract) and `CErc20Delegate` (logic/implementation contract).
* @author Compound
*/
contract CErc20 is CToken, CErc20Interface {
/**
* @notice Initialize the new money market
* @param underlying_ The address of the underlying asset
* @param comptroller_ The address of the Comptroller
* @param fuseAdmin_ The FuseFeeDistributor contract address.
* @param interestRateModel_ The address of the interest rate model
* @param name_ ERC-20 name of this token
* @param symbol_ ERC-20 symbol of this token
*/
function initialize(
address underlying_,
ComptrollerInterface comptroller_,
address payable fuseAdmin_,
InterestRateModel interestRateModel_,
string memory name_,
string memory symbol_,
uint256 reserveFactorMantissa_,
uint256 adminFeeMantissa_
) public {
// CToken initialize does the bulk of the work
uint256 initialExchangeRateMantissa_ = 0.2e18;
uint8 decimals_ = EIP20Interface(underlying_).decimals();
super.initialize(
comptroller_,
fuseAdmin_,
interestRateModel_,
initialExchangeRateMantissa_,
name_,
symbol_,
decimals_,
reserveFactorMantissa_,
adminFeeMantissa_
);
// 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(uint256 mintAmount) external override returns (uint256) {
(uint256 err, ) = mintInternal(mintAmount);
return err;
}
/**
* @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(uint256 redeemTokens) external override returns (uint256) {
return redeemInternal(redeemTokens);
}
/**
* @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(uint256 redeemAmount) external override returns (uint256) {
return redeemUnderlyingInternal(redeemAmount);
}
/**
* @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(uint256 borrowAmount) external override returns (uint256) {
return borrowInternal(borrowAmount);
}
/**
* @notice Sender repays their own borrow
* @param repayAmount The amount to repay
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/
function repayBorrow(uint256 repayAmount) external override returns (uint256) {
(uint256 err, ) = repayBorrowInternal(repayAmount);
return err;
}
/**
* @notice Sender repays a borrow belonging to borrower
* @param borrower the account with the debt being payed off
* @param repayAmount The amount to repay
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/
function repayBorrowBehalf(address borrower, uint256 repayAmount) external override returns (uint256) {
(uint256 err, ) = repayBorrowBehalfInternal(borrower, repayAmount);
return err;
}
/**
* @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,
uint256 repayAmount,
CTokenInterface cTokenCollateral
) external override returns (uint256) {
(uint256 err, ) = liquidateBorrowInternal(borrower, repayAmount, cTokenCollateral);
return err;
}
/*** 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() internal view virtual override returns (uint256) {
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, uint256 amount) internal virtual override returns (uint256) {
uint256 balanceBefore = EIP20Interface(underlying).balanceOf(address(this));
_callOptionalReturn(
abi.encodeWithSelector(EIP20NonStandardInterface(underlying).transferFrom.selector, from, address(this), amount),
"TOKEN_TRANSFER_IN_FAILED"
);
// Calculate the amount that was *actually* transferred
uint256 balanceAfter = EIP20Interface(underlying).balanceOf(address(this));
require(balanceAfter >= balanceBefore, "TOKEN_TRANSFER_IN_OVERFLOW");
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 to, uint256 amount) internal virtual override {
_callOptionalReturn(
abi.encodeWithSelector(EIP20NonStandardInterface(underlying).transfer.selector, to, amount),
"TOKEN_TRANSFER_OUT_FAILED"
);
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param data The call data (encoded using abi.encode or one of its variants).
* @param errorMessage The revert string to return on failure.
*/
function _callOptionalReturn(bytes memory data, string memory errorMessage) internal {
bytes memory returndata = _functionCall(underlying, data, errorMessage);
if (returndata.length > 0) require(abi.decode(returndata, (bool)), errorMessage);
}
}// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.0;
import { ComptrollerInterface } from "./ComptrollerInterface.sol";
import { CTokenInterface } from "./CTokenInterfaces.sol";
import { TokenErrorReporter } from "./ErrorReporter.sol";
import { Exponential } from "./Exponential.sol";
import { EIP20Interface } from "./EIP20Interface.sol";
import { EIP20NonStandardInterface } from "./EIP20NonStandardInterface.sol";
import { InterestRateModel } from "./InterestRateModel.sol";
import { DiamondBase, DiamondExtension, LibDiamond } from "../midas/DiamondExtension.sol";
import { Multicall } from "../utils/Multicall.sol";
import { ComptrollerV3Storage, UnitrollerAdminStorage } from "./ComptrollerStorage.sol";
import { IFuseFeeDistributor } from "./IFuseFeeDistributor.sol";
/**
* @title Compound's CToken Contract
* @notice Abstract base for CTokens
* @author Compound
*/
contract CToken is CTokenInterface, TokenErrorReporter, Exponential, DiamondBase, Multicall {
/**
* @notice Returns a boolean indicating if the sender has admin rights
*/
function hasAdminRights() internal view returns (bool) {
ComptrollerV3Storage comptrollerStorage = ComptrollerV3Storage(address(comptroller));
return
(msg.sender == comptrollerStorage.admin() && comptrollerStorage.adminHasRights()) ||
(msg.sender == address(fuseAdmin) && comptrollerStorage.fuseAdminHasRights());
}
/**
* @notice Initialize the money market
* @param comptroller_ The address of the Comptroller
* @param fuseAdmin_ The FuseFeeDistributor contract address.
* @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_,
address payable fuseAdmin_,
InterestRateModel interestRateModel_,
uint256 initialExchangeRateMantissa_,
string memory name_,
string memory symbol_,
uint8 decimals_,
uint256 reserveFactorMantissa_,
uint256 adminFeeMantissa_
) public {
require(msg.sender == fuseAdmin_, "!admin");
require(accrualBlockNumber == 0 && borrowIndex == 0, "!initialized");
fuseAdmin = fuseAdmin_;
// Set initial exchange rate
initialExchangeRateMantissa = initialExchangeRateMantissa_;
require(initialExchangeRateMantissa > 0, "!exchangeRate>0");
// Set the comptroller
comptroller = comptroller_;
// Initialize block number and borrow index (block number mocks depend on comptroller being set)
accrualBlockNumber = block.number;
borrowIndex = mantissaOne;
// Set the interest rate model (depends on block number / borrow index)
require(interestRateModel_.isInterestRateModel(), "!notIrm");
interestRateModel = interestRateModel_;
emit NewMarketInterestRateModel(InterestRateModel(address(0)), interestRateModel_);
name = name_;
symbol = symbol_;
decimals = decimals_;
// Set reserve factor
// Check newReserveFactor ≤ maxReserveFactor
require(reserveFactorMantissa_ + adminFeeMantissa + fuseFeeMantissa <= reserveFactorPlusFeesMaxMantissa, "!rf:set");
reserveFactorMantissa = reserveFactorMantissa_;
emit NewReserveFactor(0, reserveFactorMantissa_);
// Set admin fee
// Sanitize adminFeeMantissa_
if (adminFeeMantissa_ == type(uint256).max) adminFeeMantissa_ = adminFeeMantissa;
// Get latest Fuse fee
uint256 newFuseFeeMantissa = IFuseFeeDistributor(fuseAdmin).interestFeeRate();
require(
reserveFactorMantissa + adminFeeMantissa_ + newFuseFeeMantissa <= reserveFactorPlusFeesMaxMantissa,
"!adminFee:set"
);
adminFeeMantissa = adminFeeMantissa_;
emit NewAdminFee(0, adminFeeMantissa_);
fuseFeeMantissa = newFuseFeeMantissa;
emit NewFuseFee(0, newFuseFeeMantissa);
// The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)
_notEntered = true;
}
/**
* @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)
external
view
override
returns (
uint256,
uint256,
uint256,
uint256
)
{
uint256 cTokenBalance = accountTokens[account];
uint256 borrowBalance;
uint256 exchangeRateMantissa;
MathError mErr;
borrowBalance = borrowBalanceStored(account);
exchangeRateMantissa = asCTokenExtensionInterface().exchangeRateStored();
return (uint256(Error.NO_ERROR), cTokenBalance, borrowBalance, exchangeRateMantissa);
}
/**
* @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) external override nonReentrant(false) returns (uint256) {
require(asCTokenExtensionInterface().accrueInterest() == uint256(Error.NO_ERROR), "!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) public view override returns (uint256) {
/* Note: we do not assert that the market is up to date */
MathError mathErr;
uint256 principalTimesIndex;
uint256 result;
/* 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
*/
(mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);
require(mathErr == MathError.NO_ERROR, "!mulUInt overflow check failed");
(mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);
require(mathErr == MathError.NO_ERROR, "!divUInt overflow check failed");
return result;
}
/**
* @notice Get cash balance of this cToken in the underlying asset
* @return The quantity of underlying asset owned by this contract
*/
function getCash() external view override returns (uint256) {
return getCashPrior();
}
/**
* @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, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.
*/
function mintInternal(uint256 mintAmount) internal nonReentrant(false) returns (uint256, uint256) {
uint256 error = asCTokenExtensionInterface().accrueInterest();
if (error != uint256(Error.NO_ERROR)) {
// accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed
return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);
}
// mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to
return mintFresh(msg.sender, mintAmount);
}
struct MintLocalVars {
Error err;
MathError mathErr;
uint256 exchangeRateMantissa;
uint256 mintTokens;
uint256 totalSupplyNew;
uint256 accountTokensNew;
uint256 actualMintAmount;
}
/**
* @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
* @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.
*/
function mintFresh(address minter, uint256 mintAmount) internal returns (uint256, uint256) {
/* Fail if mint not allowed */
uint256 allowed = comptroller.mintAllowed(address(this), minter, mintAmount);
if (allowed != 0) {
return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);
}
/* Verify market's block number equals current block number */
if (accrualBlockNumber != block.number) {
return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);
}
MintLocalVars memory vars;
vars.exchangeRateMantissa = asCTokenExtensionInterface().exchangeRateStored();
// Check max supply
// unused function
/* allowed = comptroller.mintWithinLimits(address(this), vars.exchangeRateMantissa, accountTokens[minter], mintAmount);
if (allowed != 0) {
return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);
} */
/////////////////////////
// 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.
*/
vars.actualMintAmount = doTransferIn(minter, mintAmount);
/*
* We get the current exchange rate and calculate the number of cTokens to be minted:
* mintTokens = actualMintAmount / exchangeRate
*/
(vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(
vars.actualMintAmount,
Exp({ mantissa: vars.exchangeRateMantissa })
);
require(vars.mathErr == MathError.NO_ERROR, "MINT_EXCHANGE_CALCULATION_FAILED");
require(vars.mintTokens > 0, "MINT_ZERO_CTOKENS_REJECTED");
/*
* We calculate the new total supply of cTokens and minter token balance, checking for overflow:
* totalSupplyNew = totalSupply + mintTokens
* accountTokensNew = accountTokens[minter] + mintTokens
*/
vars.totalSupplyNew = totalSupply + vars.mintTokens;
vars.accountTokensNew = accountTokens[minter] + vars.mintTokens;
/* We write previously calculated values into storage */
totalSupply = vars.totalSupplyNew;
accountTokens[minter] = vars.accountTokensNew;
/* We emit a Mint event, and a Transfer event */
emit Mint(minter, vars.actualMintAmount, vars.mintTokens);
emit Transfer(address(this), minter, vars.mintTokens);
/* We call the defense hook */
// unused function
// comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);
return (uint256(Error.NO_ERROR), vars.actualMintAmount);
}
/**
* @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 redeemInternal(uint256 redeemTokens) internal nonReentrant(false) returns (uint256) {
uint256 error = asCTokenExtensionInterface().accrueInterest();
if (error != uint256(Error.NO_ERROR)) {
// accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed
return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);
}
// redeemFresh emits redeem-specific logs on errors, so we don't need to
return redeemFresh(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
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/
function redeemUnderlyingInternal(uint256 redeemAmount) internal nonReentrant(false) returns (uint256) {
uint256 error = asCTokenExtensionInterface().accrueInterest();
if (error != uint256(Error.NO_ERROR)) {
// accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed
return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);
}
// redeemFresh emits redeem-specific logs on errors, so we don't need to
return redeemFresh(msg.sender, 0, redeemAmount);
}
struct RedeemLocalVars {
Error err;
MathError mathErr;
uint256 exchangeRateMantissa;
uint256 redeemTokens;
uint256 redeemAmount;
uint256 totalSupplyNew;
uint256 accountTokensNew;
}
/**
* @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)
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/
function redeemFresh(
address redeemer,
uint256 redeemTokensIn,
uint256 redeemAmountIn
) internal returns (uint256) {
require(redeemTokensIn == 0 || redeemAmountIn == 0, "!redeemTokensInorOut!=0");
RedeemLocalVars memory vars;
/* exchangeRate = invoke Exchange Rate Stored() */
vars.exchangeRateMantissa = asCTokenExtensionInterface().exchangeRateStored();
if (redeemAmountIn == type(uint256).max) {
redeemAmountIn = comptroller.getMaxRedeemOrBorrow(redeemer, address(this), false);
}
/* 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
*/
vars.redeemTokens = redeemTokensIn;
(vars.mathErr, vars.redeemAmount) = mulScalarTruncate(
Exp({ mantissa: vars.exchangeRateMantissa }),
redeemTokensIn
);
if (vars.mathErr != MathError.NO_ERROR) {
return
failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED, uint256(vars.mathErr));
}
} else {
/*
* We get the current exchange rate and calculate the amount to be redeemed:
* redeemTokens = redeemAmountIn / exchangeRate
* redeemAmount = redeemAmountIn
*/
(vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(
redeemAmountIn,
Exp({ mantissa: vars.exchangeRateMantissa })
);
if (vars.mathErr != MathError.NO_ERROR) {
return
failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED, uint256(vars.mathErr));
}
vars.redeemAmount = redeemAmountIn;
}
/* Fail if redeem not allowed */
uint256 allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);
if (allowed != 0) {
return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REDEEM_COMPTROLLER_REJECTION, allowed);
}
/* Verify market's block number equals current block number */
if (accrualBlockNumber != block.number) {
return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDEEM_FRESHNESS_CHECK);
}
/*
* We calculate the new total supply and redeemer balance, checking for underflow:
* totalSupplyNew = totalSupply - redeemTokens
* accountTokensNew = accountTokens[redeemer] - redeemTokens
*/
(vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);
if (vars.mathErr != MathError.NO_ERROR) {
return
failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED, uint256(vars.mathErr));
}
(vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);
if (vars.mathErr != MathError.NO_ERROR) {
return
failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED, uint256(vars.mathErr));
}
/* Fail gracefully if protocol has insufficient cash */
if (getCashPrior() < vars.redeemAmount) {
return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDEEM_TRANSFER_OUT_NOT_POSSIBLE);
}
/////////////////////////
// EFFECTS & INTERACTIONS
// (No safe failures beyond this point)
/* We write previously calculated values into storage */
totalSupply = vars.totalSupplyNew;
accountTokens[redeemer] = vars.accountTokensNew;
/*
* 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, vars.redeemAmount);
/* We emit a Transfer event, and a Redeem event */
emit Transfer(redeemer, address(this), vars.redeemTokens);
emit Redeem(redeemer, vars.redeemAmount, vars.redeemTokens);
/* We call the defense hook */
comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);
return uint256(Error.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 borrowInternal(uint256 borrowAmount) internal nonReentrant(false) returns (uint256) {
uint256 error = asCTokenExtensionInterface().accrueInterest();
if (error != uint256(Error.NO_ERROR)) {
// accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed
return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);
}
// borrowFresh emits borrow-specific logs on errors, so we don't need to
return borrowFresh(msg.sender, borrowAmount);
}
struct BorrowLocalVars {
MathError mathErr;
uint256 accountBorrows;
uint256 accountBorrowsNew;
uint256 totalBorrowsNew;
}
/**
* @notice Users borrow 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 borrowFresh(address borrower, uint256 borrowAmount) internal returns (uint256) {
/* Fail if borrow not allowed */
uint256 allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);
if (allowed != 0) {
return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.BORROW_COMPTROLLER_REJECTION, allowed);
}
/* Verify market's block number equals current block number */
if (accrualBlockNumber != block.number) {
return fail(Error.MARKET_NOT_FRESH, FailureInfo.BORROW_FRESHNESS_CHECK);
}
/* Fail gracefully if protocol has insufficient underlying cash */
uint256 cashPrior = getCashPrior();
if (cashPrior < borrowAmount) {
return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.BORROW_CASH_NOT_AVAILABLE);
}
BorrowLocalVars memory vars;
/*
* We calculate the new borrower and total borrow balances, failing on overflow:
* accountBorrowsNew = accountBorrows + borrowAmount
* totalBorrowsNew = totalBorrows + borrowAmount
*/
vars.accountBorrows = borrowBalanceStored(borrower);
(vars.mathErr, vars.accountBorrowsNew) = addUInt(vars.accountBorrows, borrowAmount);
if (vars.mathErr != MathError.NO_ERROR) {
return
failOpaque(
Error.MATH_ERROR,
FailureInfo.BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,
uint256(vars.mathErr)
);
}
// Check min borrow for this user for this asset
allowed = comptroller.borrowWithinLimits(address(this), vars.accountBorrowsNew);
if (allowed != 0) {
return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.BORROW_COMPTROLLER_REJECTION, allowed);
}
(vars.mathErr, vars.totalBorrowsNew) = addUInt(totalBorrows, borrowAmount);
if (vars.mathErr != MathError.NO_ERROR) {
return
failOpaque(Error.MATH_ERROR, FailureInfo.BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED, uint256(vars.mathErr));
}
/////////////////////////
// EFFECTS & INTERACTIONS
// (No safe failures beyond this point)
/* We write the previously calculated values into storage */
accountBorrows[borrower].principal = vars.accountBorrowsNew;
accountBorrows[borrower].interestIndex = borrowIndex;
totalBorrows = vars.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, vars.accountBorrowsNew, vars.totalBorrowsNew);
/* We call the defense hook */
// unused function
// comptroller.borrowVerify(address(this), borrower, borrowAmount);
return uint256(Error.NO_ERROR);
}
/**
* @notice Sender repays their own borrow
* @param repayAmount The amount to repay
* @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.
*/
function repayBorrowInternal(uint256 repayAmount) internal nonReentrant(false) returns (uint256, uint256) {
uint256 error = asCTokenExtensionInterface().accrueInterest();
if (error != uint256(Error.NO_ERROR)) {
// accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed
return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);
}
// repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to
return 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
* @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.
*/
function repayBorrowBehalfInternal(address borrower, uint256 repayAmount)
internal
nonReentrant(false)
returns (uint256, uint256)
{
uint256 error = asCTokenExtensionInterface().accrueInterest();
if (error != uint256(Error.NO_ERROR)) {
// accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed
return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);
}
// repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to
return repayBorrowFresh(msg.sender, borrower, repayAmount);
}
struct RepayBorrowLocalVars {
Error err;
MathError mathErr;
uint256 repayAmount;
uint256 borrowerIndex;
uint256 accountBorrows;
uint256 accountBorrowsNew;
uint256 totalBorrowsNew;
uint256 actualRepayAmount;
}
/**
* @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 undelrying tokens being returned
* @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.
*/
function repayBorrowFresh(
address payer,
address borrower,
uint256 repayAmount
) internal returns (uint256, uint256) {
/* Fail if repayBorrow not allowed */
uint256 allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);
if (allowed != 0) {
return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed), 0);
}
/* Verify market's block number equals current block number */
if (accrualBlockNumber != block.number) {
return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);
}
RepayBorrowLocalVars memory vars;
/* We remember the original borrowerIndex for verification purposes */
vars.borrowerIndex = accountBorrows[borrower].interestIndex;
/* We fetch the amount the borrower owes, with accumulated interest */
vars.accountBorrows = borrowBalanceStored(borrower);
/* If repayAmount == -1, repayAmount = accountBorrows */
if (repayAmount == type(uint256).max) {
vars.repayAmount = vars.accountBorrows;
} else {
vars.repayAmount = 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.
*/
vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);
/*
* We calculate the new borrower and total borrow balances, failing on underflow:
* accountBorrowsNew = accountBorrows - actualRepayAmount
* totalBorrowsNew = totalBorrows - actualRepayAmount
*/
(vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);
require(vars.mathErr == MathError.NO_ERROR, "REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED");
(vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);
require(vars.mathErr == MathError.NO_ERROR, "REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED");
/* We write the previously calculated values into storage */
accountBorrows[borrower].principal = vars.accountBorrowsNew;
accountBorrows[borrower].interestIndex = borrowIndex;
totalBorrows = vars.totalBorrowsNew;
/* We emit a RepayBorrow event */
emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);
/* We call the defense hook */
// unused function
// comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);
return (uint256(Error.NO_ERROR), vars.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
* @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.
*/
function liquidateBorrowInternal(
address borrower,
uint256 repayAmount,
CTokenInterface cTokenCollateral
) internal nonReentrant(false) returns (uint256, uint256) {
uint256 error = asCTokenExtensionInterface().accrueInterest();
if (error != uint256(Error.NO_ERROR)) {
// accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed
return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED), 0);
}
error = cTokenCollateral.asCTokenExtensionInterface().accrueInterest();
if (error != uint256(Error.NO_ERROR)) {
// accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed
return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);
}
// liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to
return 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
* @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.
*/
function liquidateBorrowFresh(
address liquidator,
address borrower,
uint256 repayAmount,
CTokenInterface cTokenCollateral
) internal returns (uint256, uint256) {
/* Fail if liquidate not allowed */
uint256 allowed = comptroller.liquidateBorrowAllowed(
address(this),
address(cTokenCollateral),
liquidator,
borrower,
repayAmount
);
if (allowed != 0) {
return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);
}
/* Verify market's block number equals current block number */
if (accrualBlockNumber != block.number) {
return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);
}
/* Verify cTokenCollateral market's block number equals current block number */
if (cTokenCollateral.accrualBlockNumber() != block.number) {
return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);
}
/* Fail if borrower = liquidator */
if (borrower == liquidator) {
return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);
}
/* Fail if repayAmount = 0 */
if (repayAmount == 0) {
return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);
}
/* Fail if repayAmount = -1 */
if (repayAmount == type(uint256).max) {
return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);
}
/* Fail if repayBorrow fails */
(uint256 repayBorrowError, uint256 actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);
if (repayBorrowError != uint256(Error.NO_ERROR)) {
return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);
}
/////////////////////////
// EFFECTS & INTERACTIONS
// (No safe failures beyond this point)
/* We calculate the number of collateral tokens that will be seized */
(uint256 amountSeizeError, uint256 seizeTokens) = comptroller.liquidateCalculateSeizeTokens(
address(this),
address(cTokenCollateral),
actualRepayAmount
);
require(amountSeizeError == uint256(Error.NO_ERROR), "LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED");
/* Revert if borrower collateral token balance < seizeTokens */
require(
cTokenCollateral.asCTokenExtensionInterface().balanceOf(borrower) >= seizeTokens,
"LIQUIDATE_SEIZE_TOO_MUCH"
);
// If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call
uint256 seizeError;
if (address(cTokenCollateral) == address(this)) {
seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);
} else {
seizeError = cTokenCollateral.seize(liquidator, borrower, seizeTokens);
}
/* Revert if seize tokens fails (since we cannot be sure of side effects) */
require(seizeError == uint256(Error.NO_ERROR), "!seize");
/* We emit a LiquidateBorrow event */
emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(cTokenCollateral), seizeTokens);
/* We call the defense hook */
// unused function
// comptroller.liquidateBorrowVerify(address(this), address(cTokenCollateral), liquidator, borrower, actualRepayAmount, seizeTokens);
return (uint256(Error.NO_ERROR), actualRepayAmount);
}
/**
* @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,
uint256 seizeTokens
) external override nonReentrant(true) returns (uint256) {
return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);
}
struct SeizeInternalLocalVars {
MathError mathErr;
uint256 borrowerTokensNew;
uint256 liquidatorTokensNew;
uint256 liquidatorSeizeTokens;
uint256 protocolSeizeTokens;
uint256 protocolSeizeAmount;
uint256 exchangeRateMantissa;
uint256 totalReservesNew;
uint256 totalFuseFeeNew;
uint256 totalSupplyNew;
uint256 feeSeizeTokens;
uint256 feeSeizeAmount;
}
/**
* @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
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/
function seizeInternal(
address seizerToken,
address liquidator,
address borrower,
uint256 seizeTokens
) internal returns (uint256) {
/* Fail if seize not allowed */
uint256 allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);
if (allowed != 0) {
return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);
}
/* Fail if borrower = liquidator */
if (borrower == liquidator) {
return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);
}
SeizeInternalLocalVars memory vars;
/*
* We calculate the new borrower and liquidator token balances, failing on underflow/overflow:
* borrowerTokensNew = accountTokens[borrower] - seizeTokens
* liquidatorTokensNew = accountTokens[liquidator] + seizeTokens
*/
(vars.mathErr, vars.borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);
if (vars.mathErr != MathError.NO_ERROR) {
return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint256(vars.mathErr));
}
vars.protocolSeizeTokens = mul_(seizeTokens, Exp({ mantissa: protocolSeizeShareMantissa }));
vars.feeSeizeTokens = mul_(seizeTokens, Exp({ mantissa: feeSeizeShareMantissa }));
vars.liquidatorSeizeTokens = seizeTokens - vars.protocolSeizeTokens - vars.feeSeizeTokens;
vars.exchangeRateMantissa = asCTokenExtensionInterface().exchangeRateStored();
vars.protocolSeizeAmount = mul_ScalarTruncate(
Exp({ mantissa: vars.exchangeRateMantissa }),
vars.protocolSeizeTokens
);
vars.feeSeizeAmount = mul_ScalarTruncate(Exp({ mantissa: vars.exchangeRateMantissa }), vars.feeSeizeTokens);
vars.totalReservesNew = totalReserves + vars.protocolSeizeAmount;
vars.totalSupplyNew = totalSupply - vars.protocolSeizeTokens - vars.feeSeizeTokens;
vars.totalFuseFeeNew = totalFuseFees + vars.feeSeizeAmount;
(vars.mathErr, vars.liquidatorTokensNew) = addUInt(accountTokens[liquidator], vars.liquidatorSeizeTokens);
if (vars.mathErr != MathError.NO_ERROR) {
return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint256(vars.mathErr));
}
/////////////////////////
// EFFECTS & INTERACTIONS
// (No safe failures beyond this point)
/* We write the previously calculated values into storage */
totalReserves = vars.totalReservesNew;
totalSupply = vars.totalSupplyNew;
totalFuseFees = vars.totalFuseFeeNew;
accountTokens[borrower] = vars.borrowerTokensNew;
accountTokens[liquidator] = vars.liquidatorTokensNew;
/* Emit a Transfer event */
emit Transfer(borrower, liquidator, vars.liquidatorSeizeTokens);
emit Transfer(borrower, address(this), vars.protocolSeizeTokens);
emit ReservesAdded(address(this), vars.protocolSeizeAmount, vars.totalReservesNew);
/* We call the defense hook */
// unused function
// comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);
return uint256(Error.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() internal view virtual returns (uint256) {
return 0;
}
/**
* @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, uint256 amount) internal virtual returns (uint256) {
return 1;
}
/**
* @dev Performs a transfer out, ideally returning an explanatory error code upon failure tather 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 to, uint256 amount) internal virtual {}
/**
* @notice Accrues interest and reduces Fuse fees by transferring to Fuse
* @param withdrawAmount Amount of fees to withdraw
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/
function _withdrawFuseFees(uint256 withdrawAmount) external override nonReentrant(false) returns (uint256) {
uint256 error = asCTokenExtensionInterface().accrueInterest();
if (error != uint256(Error.NO_ERROR)) {
// accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted Fuse fee withdrawal failed.
return fail(Error(error), FailureInfo.WITHDRAW_FUSE_FEES_ACCRUE_INTEREST_FAILED);
}
if (accrualBlockNumber != block.number) {
return fail(Error.MARKET_NOT_FRESH, FailureInfo.WITHDRAW_FUSE_FEES_FRESH_CHECK);
}
if (getCashPrior() < withdrawAmount) {
return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.WITHDRAW_FUSE_FEES_CASH_NOT_AVAILABLE);
}
if (withdrawAmount > totalFuseFees) {
return fail(Error.BAD_INPUT, FailureInfo.WITHDRAW_FUSE_FEES_VALIDATION);
}
/////////////////////////
// EFFECTS & INTERACTIONS
// (No safe failures beyond this point)
uint256 totalFuseFeesNew = totalFuseFees - withdrawAmount;
totalFuseFees = totalFuseFeesNew;
// doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.
doTransferOut(address(fuseAdmin), withdrawAmount);
return uint256(Error.NO_ERROR);
}
/**
* @notice Accrues interest and reduces admin fees by transferring to admin
* @param withdrawAmount Amount of fees to withdraw
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/
function _withdrawAdminFees(uint256 withdrawAmount) external override nonReentrant(false) returns (uint256) {
uint256 error = asCTokenExtensionInterface().accrueInterest();
if (error != uint256(Error.NO_ERROR)) {
return fail(Error(error), FailureInfo.WITHDRAW_ADMIN_FEES_ACCRUE_INTEREST_FAILED);
}
if (accrualBlockNumber != block.number) {
return fail(Error.MARKET_NOT_FRESH, FailureInfo.WITHDRAW_ADMIN_FEES_FRESH_CHECK);
}
// Fail gracefully if protocol has insufficient underlying cash
if (getCashPrior() < withdrawAmount) {
return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.WITHDRAW_ADMIN_FEES_CASH_NOT_AVAILABLE);
}
if (withdrawAmount > totalAdminFees) {
return fail(Error.BAD_INPUT, FailureInfo.WITHDRAW_ADMIN_FEES_VALIDATION);
}
/////////////////////////
// EFFECTS & INTERACTIONS
// (No safe failures beyond this point)
totalAdminFees = totalAdminFees - withdrawAmount;
// doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.
doTransferOut(UnitrollerAdminStorage(address(comptroller)).admin(), withdrawAmount);
return uint256(Error.NO_ERROR);
}
/**
* @dev register a logic extension
* @param extensionToAdd the extension whose functions are to be added
* @param extensionToReplace the extension whose functions are to be removed/replaced
*/
function _registerExtension(DiamondExtension extensionToAdd, DiamondExtension extensionToReplace) external override {
ComptrollerV3Storage comptrollerStorage = ComptrollerV3Storage(address(comptroller));
require(
msg.sender == address(fuseAdmin) && comptrollerStorage.fuseAdminHasRights(),
"!unauthorized - no admin rights"
);
LibDiamond.registerExtension(extensionToAdd, extensionToReplace);
}
/*** Reentrancy Guard ***/
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
*/
modifier nonReentrant(bool localOnly) {
_beforeNonReentrant(localOnly);
_;
_afterNonReentrant(localOnly);
}
/**
* @dev Split off from `nonReentrant` to keep contract below the 24 KB size limit.
* Saves space because function modifier code is "inlined" into every function with the modifier).
* In this specific case, the optimization saves around 1500 bytes of that valuable 24 KB limit.
*/
function _beforeNonReentrant(bool localOnly) private {
require(_notEntered, "re-entered");
if (!localOnly) comptroller._beforeNonReentrant();
_notEntered = false;
}
/**
* @dev Split off from `nonReentrant` to keep contract below the 24 KB size limit.
* Saves space because function modifier code is "inlined" into every function with the modifier).
* In this specific case, the optimization saves around 150 bytes of that valuable 24 KB limit.
*/
function _afterNonReentrant(bool localOnly) private {
_notEntered = true; // get a gas-refund post-Istanbul
if (!localOnly) comptroller._afterNonReentrant();
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
* @param data The call data (encoded using abi.encode or one of its variants).
* @param errorMessage The revert string to return on failure.
*/
function _functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.call(data);
if (!success) {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
// solhint-disable-next-line no-inline-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
return returndata;
}
}// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.0;
import { ComptrollerInterface } from "./ComptrollerInterface.sol";
import { InterestRateModel } from "./InterestRateModel.sol";
contract CTokenAdminStorage {
/*
* Administrator for Fuse
*/
address payable public fuseAdmin;
/**
* @dev LEGACY USE ONLY: Administrator for this contract
*/
address payable internal __admin;
/**
* @dev LEGACY USE ONLY: Whether or not the Fuse admin has admin rights
*/
bool internal __fuseAdminHasRights;
/**
* @dev LEGACY USE ONLY: Whether or not the admin has admin rights
*/
bool internal __adminHasRights;
}
contract CTokenStorage is CTokenAdminStorage {
/**
* @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)
*/
uint256 internal constant borrowRateMaxMantissa = 0.0005e16;
/*
* Maximum fraction of interest that can be set aside for reserves + fees
*/
uint256 internal constant reserveFactorPlusFeesMaxMantissa = 1e18;
/*
* LEGACY USE ONLY: Pending administrator for this contract
*/
address payable private __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)
*/
uint256 internal initialExchangeRateMantissa;
/**
* @notice Fraction of interest currently set aside for admin fees
*/
uint256 public adminFeeMantissa;
/**
* @notice Fraction of interest currently set aside for Fuse fees
*/
uint256 public fuseFeeMantissa;
/**
* @notice Fraction of interest currently set aside for reserves
*/
uint256 public reserveFactorMantissa;
/**
* @notice Block number that interest was last accrued at
*/
uint256 public accrualBlockNumber;
/**
* @notice Accumulator of the total earned interest rate since the opening of the market
*/
uint256 public borrowIndex;
/**
* @notice Total amount of outstanding borrows of the underlying in this market
*/
uint256 public totalBorrows;
/**
* @notice Total amount of reserves of the underlying held in this market
*/
uint256 public totalReserves;
/**
* @notice Total amount of admin fees of the underlying held in this market
*/
uint256 public totalAdminFees;
/**
* @notice Total amount of Fuse fees of the underlying held in this market
*/
uint256 public totalFuseFees;
/**
* @notice Total number of tokens in circulation
*/
uint256 public totalSupply;
/*
* Official record of token balances for each account
*/
mapping(address => uint256) internal accountTokens;
/*
* Approved token transfer amounts on behalf of others
*/
mapping(address => mapping(address => uint256)) 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 {
uint256 principal;
uint256 interestIndex;
}
/*
* Mapping of account addresses to outstanding borrow balances
*/
mapping(address => BorrowSnapshot) internal accountBorrows;
/*
* Share of seized collateral that is added to reserves
*/
uint256 public constant protocolSeizeShareMantissa = 2.8e16; //2.8%
/*
* Share of seized collateral taken as fees
*/
uint256 public constant feeSeizeShareMantissa = 1e17; //10%
}
abstract contract CTokenBaseInterface is CTokenStorage {
/* ERC20 */
/**
* @notice EIP20 Transfer event
*/
event Transfer(address indexed from, address indexed to, uint256 amount);
/*** Admin Events ***/
/**
* @notice Event emitted when interestRateModel is changed
*/
event NewMarketInterestRateModel(InterestRateModel oldInterestRateModel, InterestRateModel newInterestRateModel);
/**
* @notice Event emitted when the reserve factor is changed
*/
event NewReserveFactor(uint256 oldReserveFactorMantissa, uint256 newReserveFactorMantissa);
/**
* @notice Event emitted when the admin fee is changed
*/
event NewAdminFee(uint256 oldAdminFeeMantissa, uint256 newAdminFeeMantissa);
/**
* @notice Event emitted when the Fuse fee is changed
*/
event NewFuseFee(uint256 oldFuseFeeMantissa, uint256 newFuseFeeMantissa);
}
abstract contract CTokenExtensionInterface is CTokenBaseInterface {
/**
* @notice EIP20 Approval event
*/
event Approval(address indexed owner, address indexed spender, uint256 amount);
/**
* @notice Event emitted when interest is accrued
*/
event AccrueInterest(uint256 cashPrior, uint256 interestAccumulated, uint256 borrowIndex, uint256 totalBorrows);
/*** User Interface ***/
function transfer(address dst, uint256 amount) external virtual returns (bool);
function transferFrom(
address src,
address dst,
uint256 amount
) external virtual returns (bool);
function approve(address spender, uint256 amount) external virtual returns (bool);
function allowance(address owner, address spender) external view virtual returns (uint256);
function balanceOf(address owner) external view virtual returns (uint256);
/*** Admin Functions ***/
function _setReserveFactor(uint256 newReserveFactorMantissa) external virtual returns (uint256);
function _setAdminFee(uint256 newAdminFeeMantissa) external virtual returns (uint256);
function _setInterestRateModel(InterestRateModel newInterestRateModel) external virtual returns (uint256);
function borrowRatePerBlock() external view virtual returns (uint256);
function supplyRatePerBlock() external view virtual returns (uint256);
function exchangeRateCurrent() public virtual returns (uint256);
function exchangeRateStored() public view virtual returns (uint256);
function accrueInterest() public virtual returns (uint256);
function totalBorrowsCurrent() external virtual returns (uint256);
function balanceOfUnderlying(address owner) external virtual returns (uint256);
function asCTokenInterface() public view returns (CTokenInterface) {
return CTokenInterface(address(this));
}
}
abstract contract CTokenInterface is CTokenBaseInterface {
function asCTokenExtensionInterface() public view returns (CTokenExtensionInterface) {
return CTokenExtensionInterface(address(this));
}
/**
* @notice Indicator that this is a CToken contract (for inspection)
*/
function isCToken() external virtual returns (bool) {
return true;
}
/**
* @notice Indicator that this is or is not a CEther contract (for inspection)
*/
function isCEther() external virtual returns (bool) {
return false;
}
/*** Market Events ***/
/**
* @notice Event emitted when tokens are minted
*/
event Mint(address minter, uint256 mintAmount, uint256 mintTokens);
/**
* @notice Event emitted when tokens are redeemed
*/
event Redeem(address redeemer, uint256 redeemAmount, uint256 redeemTokens);
/**
* @notice Event emitted when underlying is borrowed
*/
event Borrow(address borrower, uint256 borrowAmount, uint256 accountBorrows, uint256 totalBorrows);
/**
* @notice Event emitted when a borrow is repaid
*/
event RepayBorrow(address payer, address borrower, uint256 repayAmount, uint256 accountBorrows, uint256 totalBorrows);
/**
* @notice Event emitted when a borrow is liquidated
*/
event LiquidateBorrow(
address liquidator,
address borrower,
uint256 repayAmount,
address cTokenCollateral,
uint256 seizeTokens
);
/**
* @notice Event emitted when the reserves are added
*/
event ReservesAdded(address benefactor, uint256 addAmount, uint256 newTotalReserves);
/**
* @notice Event emitted when the reserves are reduced
*/
event ReservesReduced(address admin, uint256 reduceAmount, uint256 newTotalReserves);
function getAccountSnapshot(address account)
external
view
virtual
returns (
uint256,
uint256,
uint256,
uint256
);
function borrowBalanceCurrent(address account) external virtual returns (uint256);
function borrowBalanceStored(address account) public view virtual returns (uint256);
function getCash() external view virtual returns (uint256);
function seize(
address liquidator,
address borrower,
uint256 seizeTokens
) external virtual returns (uint256);
/*** Admin Functions ***/
function _withdrawAdminFees(uint256 withdrawAmount) external virtual returns (uint256);
function _withdrawFuseFees(uint256 withdrawAmount) external virtual returns (uint256);
}
contract CErc20Storage is CTokenStorage {
/**
* @notice Underlying asset for this CToken
*/
address public underlying;
}
abstract contract CErc20Interface is CTokenInterface, CErc20Storage {
/*** User Interface ***/
function mint(uint256 mintAmount) external virtual returns (uint256);
function redeem(uint256 redeemTokens) external virtual returns (uint256);
function redeemUnderlying(uint256 redeemAmount) external virtual returns (uint256);
function borrow(uint256 borrowAmount) external virtual returns (uint256);
function repayBorrow(uint256 repayAmount) external virtual returns (uint256);
function repayBorrowBehalf(address borrower, uint256 repayAmount) external virtual returns (uint256);
function liquidateBorrow(
address borrower,
uint256 repayAmount,
CTokenInterface cTokenCollateral
) external virtual returns (uint256);
}// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.0;
/**
* @title Careful Math
* @author Compound
* @notice Derived from OpenZeppelin's SafeMath library
* https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol
*/
contract CarefulMath {
/**
* @dev Possible error codes that we can return
*/
enum MathError {
NO_ERROR,
DIVISION_BY_ZERO,
INTEGER_OVERFLOW,
INTEGER_UNDERFLOW
}
/**
* @dev Multiplies two numbers, returns an error on overflow.
*/
function mulUInt(uint256 a, uint256 b) internal pure returns (MathError, uint256) {
if (a == 0) {
return (MathError.NO_ERROR, 0);
}
uint256 c;
unchecked {
c = a * b;
}
if (c / a != b) {
return (MathError.INTEGER_OVERFLOW, 0);
} else {
return (MathError.NO_ERROR, c);
}
}
/**
* @dev Integer division of two numbers, truncating the quotient.
*/
function divUInt(uint256 a, uint256 b) internal pure returns (MathError, uint256) {
if (b == 0) {
return (MathError.DIVISION_BY_ZERO, 0);
}
return (MathError.NO_ERROR, a / b);
}
/**
* @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).
*/
function subUInt(uint256 a, uint256 b) internal pure returns (MathError, uint256) {
if (b <= a) {
return (MathError.NO_ERROR, a - b);
} else {
return (MathError.INTEGER_UNDERFLOW, 0);
}
}
/**
* @dev Adds two numbers, returns an error on overflow.
*/
function addUInt(uint256 a, uint256 b) internal pure returns (MathError, uint256) {
uint256 c;
unchecked {
c = a + b;
}
if (c >= a) {
return (MathError.NO_ERROR, c);
} else {
return (MathError.INTEGER_OVERFLOW, 0);
}
}
/**
* @dev add a and b and then subtract c
*/
function addThenSubUInt(
uint256 a,
uint256 b,
uint256 c
) internal pure returns (MathError, uint256) {
(MathError err0, uint256 sum) = addUInt(a, b);
if (err0 != MathError.NO_ERROR) {
return (err0, 0);
}
return subUInt(sum, c);
}
}// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.0;
abstract contract ComptrollerInterface {
/// @notice Indicator that this is a Comptroller contract (for inspection)
bool public constant isComptroller = true;
function getRewardsDistributors() external view virtual returns (address[] memory);
function getMaxRedeemOrBorrow(
address account,
address cToken,
bool isBorrow
) external virtual returns (uint256);
/*** Assets You Are In ***/
function enterMarkets(address[] calldata cTokens) external virtual returns (uint256[] memory);
function exitMarket(address cToken) external virtual returns (uint256);
/*** Policy Hooks ***/
function mintAllowed(
address cToken,
address minter,
uint256 mintAmount
) external virtual returns (uint256);
function redeemAllowed(
address cToken,
address redeemer,
uint256 redeemTokens
) external virtual returns (uint256);
function redeemVerify(
address cToken,
address redeemer,
uint256 redeemAmount,
uint256 redeemTokens
) external virtual;
function borrowAllowed(
address cToken,
address borrower,
uint256 borrowAmount
) external virtual returns (uint256);
function borrowWithinLimits(address cToken, uint256 accountBorrowsNew) external view virtual returns (uint256);
function repayBorrowAllowed(
address cToken,
address payer,
address borrower,
uint256 repayAmount
) external virtual returns (uint256);
function liquidateBorrowAllowed(
address cTokenBorrowed,
address cTokenCollateral,
address liquidator,
address borrower,
uint256 repayAmount
) external virtual returns (uint256);
function seizeAllowed(
address cTokenCollateral,
address cTokenBorrowed,
address liquidator,
address borrower,
uint256 seizeTokens
) external virtual returns (uint256);
function transferAllowed(
address cToken,
address src,
address dst,
uint256 transferTokens
) external virtual returns (uint256);
/*** Liquidity/Liquidation Calculations ***/
function getAccountLiquidity(address account)
external
view
virtual
returns (
uint256,
uint256,
uint256
);
function liquidateCalculateSeizeTokens(
address cTokenBorrowed,
address cTokenCollateral,
uint256 repayAmount
) external view virtual returns (uint256, uint256);
/*** Pool-Wide/Cross-Asset Reentrancy Prevention ***/
function _beforeNonReentrant() external virtual;
function _afterNonReentrant() external virtual;
}// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.0;
import "./IFuseFeeDistributor.sol";
import "./PriceOracle.sol";
contract UnitrollerAdminStorage {
/*
* Administrator for Fuse
*/
address payable public fuseAdmin;
/**
* @notice Administrator for this contract
*/
address public admin;
/**
* @notice Pending administrator for this contract
*/
address public pendingAdmin;
/**
* @notice Whether or not the Fuse admin has admin rights
*/
bool public fuseAdminHasRights = true;
/**
* @notice Whether or not the admin has admin rights
*/
bool public adminHasRights = true;
/**
* @notice Returns a boolean indicating if the sender has admin rights
*/
function hasAdminRights() internal view returns (bool) {
return (msg.sender == admin && adminHasRights) || (msg.sender == address(fuseAdmin) && fuseAdminHasRights);
}
/**
* @notice Active brains of Unitroller
*/
address public comptrollerImplementation;
/**
* @notice Pending brains of Unitroller
*/
address public pendingComptrollerImplementation;
}
contract ComptrollerV1Storage is UnitrollerAdminStorage {
/**
* @notice Oracle which gives the price of any given asset
*/
PriceOracle public oracle;
/**
* @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow
*/
uint256 public closeFactorMantissa;
/**
* @notice Multiplier representing the discount on collateral that a liquidator receives
*/
uint256 public liquidationIncentiveMantissa;
/*
* UNUSED AFTER UPGRADE: Max number of assets a single account can participate in (borrow or use as collateral)
*/
uint256 internal maxAssets;
/**
* @notice Per-account mapping of "assets you are in", capped by maxAssets
*/
mapping(address => CTokenInterface[]) public accountAssets;
}
contract ComptrollerV2Storage is ComptrollerV1Storage {
struct Market {
// Whether or not this market is listed
bool isListed;
// Multiplier representing the most one can borrow against their collateral in this market.
// For instance, 0.9 to allow borrowing 90% of collateral value.
// Must be between 0 and 1, and stored as a mantissa.
uint256 collateralFactorMantissa;
// Per-market mapping of "accounts in this asset"
mapping(address => bool) accountMembership;
}
/**
* @notice Official mapping of cTokens -> Market metadata
* @dev Used e.g. to determine if a market is supported
*/
mapping(address => Market) public markets;
/// @notice A list of all markets
CTokenInterface[] public allMarkets;
/**
* @dev Maps borrowers to booleans indicating if they have entered any markets
*/
mapping(address => bool) internal borrowers;
/// @notice A list of all borrowers who have entered markets
address[] public allBorrowers;
// Indexes of borrower account addresses in the `allBorrowers` array
mapping(address => uint256) internal borrowerIndexes;
/**
* @dev Maps suppliers to booleans indicating if they have ever supplied to any markets
*/
mapping(address => bool) public suppliers;
/// @notice All cTokens addresses mapped by their underlying token addresses
mapping(address => CTokenInterface) public cTokensByUnderlying;
/// @notice Whether or not the supplier whitelist is enforced
bool public enforceWhitelist;
/// @notice Maps addresses to booleans indicating if they are allowed to supply assets (i.e., mint cTokens)
mapping(address => bool) public whitelist;
/// @notice An array of all whitelisted accounts
address[] public whitelistArray;
// Indexes of account addresses in the `whitelistArray` array
mapping(address => uint256) internal whitelistIndexes;
/**
* @notice The Pause Guardian can pause certain actions as a safety mechanism.
* Actions which allow users to remove their own assets cannot be paused.
* Liquidation / seizing / transfer can only be paused globally, not by market.
*/
address public pauseGuardian;
bool public _mintGuardianPaused;
bool public _borrowGuardianPaused;
bool public transferGuardianPaused;
bool public seizeGuardianPaused;
mapping(address => bool) public mintGuardianPaused;
mapping(address => bool) public borrowGuardianPaused;
}
contract ComptrollerV3Storage is ComptrollerV2Storage {
/**
* @dev Whether or not the implementation should be auto-upgraded.
*/
bool public autoImplementation;
/// @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.
address public borrowCapGuardian;
/// @notice Borrow caps enforced by borrowAllowed for each cToken address. Defaults to zero which corresponds to unlimited borrowing.
mapping(address => uint256) public borrowCaps;
/// @notice Supply caps enforced by mintAllowed for each cToken address. Defaults to zero which corresponds to unlimited supplying.
mapping(address => uint256) public supplyCaps;
/// @notice RewardsDistributor contracts to notify of flywheel changes.
address[] public rewardsDistributors;
/// @dev Guard variable for pool-wide/cross-asset re-entrancy checks
bool internal _notEntered;
/// @dev Whether or not _notEntered has been initialized
bool internal _notEnteredInitialized;
/// @notice RewardsDistributor to list for claiming, but not to notify of flywheel changes.
address[] public nonAccruingRewardsDistributors;
}// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.0;
/**
* @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 uint256 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 uint256 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 bool 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 bool 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 bool 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 uint256 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);
}// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.0;
/**
* @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 uint256 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 bool 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 uint256 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);
}// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.0;
contract ComptrollerErrorReporter {
enum Error {
NO_ERROR,
UNAUTHORIZED,
COMPTROLLER_MISMATCH,
INSUFFICIENT_SHORTFALL,
INSUFFICIENT_LIQUIDITY,
INVALID_CLOSE_FACTOR,
INVALID_COLLATERAL_FACTOR,
INVALID_LIQUIDATION_INCENTIVE,
MARKET_NOT_LISTED,
MARKET_ALREADY_LISTED,
MATH_ERROR,
NONZERO_BORROW_BALANCE,
PRICE_ERROR,
REJECTION,
SNAPSHOT_ERROR,
TOO_MANY_ASSETS,
TOO_MUCH_REPAY,
SUPPLIER_NOT_WHITELISTED,
BORROW_BELOW_MIN,
SUPPLY_ABOVE_MAX,
NONZERO_TOTAL_SUPPLY
}
enum FailureInfo {
ACCEPT_ADMIN_PENDING_ADMIN_CHECK,
ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,
ADD_REWARDS_DISTRIBUTOR_OWNER_CHECK,
EXIT_MARKET_BALANCE_OWED,
EXIT_MARKET_REJECTION,
TOGGLE_ADMIN_RIGHTS_OWNER_CHECK,
TOGGLE_AUTO_IMPLEMENTATIONS_ENABLED_OWNER_CHECK,
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_LIQUIDATION_INCENTIVE_OWNER_CHECK,
SET_LIQUIDATION_INCENTIVE_VALIDATION,
SET_PENDING_ADMIN_OWNER_CHECK,
SET_PENDING_IMPLEMENTATION_CONTRACT_CHECK,
SET_PENDING_IMPLEMENTATION_OWNER_CHECK,
SET_PRICE_ORACLE_OWNER_CHECK,
SET_WHITELIST_ENFORCEMENT_OWNER_CHECK,
SET_WHITELIST_STATUS_OWNER_CHECK,
SUPPORT_MARKET_EXISTS,
SUPPORT_MARKET_OWNER_CHECK,
SET_PAUSE_GUARDIAN_OWNER_CHECK,
UNSUPPORT_MARKET_OWNER_CHECK,
UNSUPPORT_MARKET_DOES_NOT_EXIST,
UNSUPPORT_MARKET_IN_USE
}
/**
* @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(uint256 error, uint256 info, uint256 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 (uint256) {
emit Failure(uint256(err), uint256(info), 0);
return uint256(err);
}
/**
* @dev use this when reporting an opaque error from an upgradeable collaborator contract
*/
function failOpaque(
Error err,
FailureInfo info,
uint256 opaqueError
) internal returns (uint256) {
emit Failure(uint256(err), uint256(info), opaqueError);
return uint256(err);
}
}
contract TokenErrorReporter {
enum Error {
NO_ERROR,
UNAUTHORIZED,
BAD_INPUT,
COMPTROLLER_REJECTION,
COMPTROLLER_CALCULATION_ERROR,
INTEREST_RATE_MODEL_ERROR,
INVALID_ACCOUNT_PAIR,
INVALID_CLOSE_AMOUNT_REQUESTED,
INVALID_COLLATERAL_FACTOR,
MATH_ERROR,
MARKET_NOT_FRESH,
MARKET_NOT_LISTED,
TOKEN_INSUFFICIENT_ALLOWANCE,
TOKEN_INSUFFICIENT_BALANCE,
TOKEN_INSUFFICIENT_CASH,
TOKEN_TRANSFER_IN_FAILED,
TOKEN_TRANSFER_OUT_FAILED,
UTILIZATION_ABOVE_MAX
}
/*
* Note: FailureInfo (but not Error) is kept in alphabetical order
* This is because FailureInfo grows significantly faster, and
* the order of Error has some meaning, while the order of FailureInfo
* is entirely arbitrary.
*/
enum FailureInfo {
ACCEPT_ADMIN_PENDING_ADMIN_CHECK,
ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,
ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,
ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,
ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,
ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,
ACCRUE_INTEREST_NEW_TOTAL_FUSE_FEES_CALCULATION_FAILED,
ACCRUE_INTEREST_NEW_TOTAL_ADMIN_FEES_CALCULATION_FAILED,
ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,
BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,
BORROW_ACCRUE_INTEREST_FAILED,
BORROW_CASH_NOT_AVAILABLE,
BORROW_FRESHNESS_CHECK,
BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,
BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,
BORROW_MARKET_NOT_LISTED,
BORROW_COMPTROLLER_REJECTION,
LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,
LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,
LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,
LIQUIDATE_COMPTROLLER_REJECTION,
LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,
LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,
LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,
LIQUIDATE_FRESHNESS_CHECK,
LIQUIDATE_LIQUIDATOR_IS_BORROWER,
LIQUIDATE_REPAY_BORROW_FRESH_FAILED,
LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,
LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,
LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,
LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,
LIQUIDATE_SEIZE_TOO_MUCH,
MINT_ACCRUE_INTEREST_FAILED,
MINT_COMPTROLLER_REJECTION,
MINT_EXCHANGE_CALCULATION_FAILED,
MINT_EXCHANGE_RATE_READ_FAILED,
MINT_FRESHNESS_CHECK,
MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,
MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,
MINT_TRANSFER_IN_FAILED,
MINT_TRANSFER_IN_NOT_POSSIBLE,
NEW_UTILIZATION_RATE_ABOVE_MAX,
REDEEM_ACCRUE_INTEREST_FAILED,
REDEEM_COMPTROLLER_REJECTION,
REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,
REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,
REDEEM_EXCHANGE_RATE_READ_FAILED,
REDEEM_FRESHNESS_CHECK,
REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,
REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,
REDEEM_TRANSFER_OUT_NOT_POSSIBLE,
WITHDRAW_FUSE_FEES_ACCRUE_INTEREST_FAILED,
WITHDRAW_FUSE_FEES_CASH_NOT_AVAILABLE,
WITHDRAW_FUSE_FEES_FRESH_CHECK,
WITHDRAW_FUSE_FEES_VALIDATION,
WITHDRAW_ADMIN_FEES_ACCRUE_INTEREST_FAILED,
WITHDRAW_ADMIN_FEES_CASH_NOT_AVAILABLE,
WITHDRAW_ADMIN_FEES_FRESH_CHECK,
WITHDRAW_ADMIN_FEES_VALIDATION,
REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,
REDUCE_RESERVES_ADMIN_CHECK,
REDUCE_RESERVES_CASH_NOT_AVAILABLE,
REDUCE_RESERVES_FRESH_CHECK,
REDUCE_RESERVES_VALIDATION,
REPAY_BEHALF_ACCRUE_INTEREST_FAILED,
REPAY_BORROW_ACCRUE_INTEREST_FAILED,
REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,
REPAY_BORROW_COMPTROLLER_REJECTION,
REPAY_BORROW_FRESHNESS_CHECK,
REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,
REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,
REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,
SET_COLLATERAL_FACTOR_OWNER_CHECK,
SET_COLLATERAL_FACTOR_VALIDATION,
SET_COMPTROLLER_OWNER_CHECK,
SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,
SET_INTEREST_RATE_MODEL_FRESH_CHECK,
SET_INTEREST_RATE_MODEL_OWNER_CHECK,
TOGGLE_ADMIN_RIGHTS_OWNER_CHECK,
SET_PENDING_ADMIN_OWNER_CHECK,
SET_ADMIN_FEE_ACCRUE_INTEREST_FAILED,
SET_ADMIN_FEE_ADMIN_CHECK,
SET_ADMIN_FEE_FRESH_CHECK,
SET_ADMIN_FEE_BOUNDS_CHECK,
SET_FUSE_FEE_ACCRUE_INTEREST_FAILED,
SET_FUSE_FEE_FRESH_CHECK,
SET_FUSE_FEE_BOUNDS_CHECK,
SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,
SET_RESERVE_FACTOR_ADMIN_CHECK,
SET_RESERVE_FACTOR_FRESH_CHECK,
SET_RESERVE_FACTOR_BOUNDS_CHECK,
TRANSFER_COMPTROLLER_REJECTION,
TRANSFER_NOT_ALLOWED,
TRANSFER_NOT_ENOUGH,
TRANSFER_TOO_MUCH,
ADD_RESERVES_ACCRUE_INTEREST_FAILED,
ADD_RESERVES_FRESH_CHECK,
ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE
}
/**
* @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(uint256 error, uint256 info, uint256 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 (uint256) {
emit Failure(uint256(err), uint256(info), 0);
return uint256(err);
}
/**
* @dev use this when reporting an opaque error from an upgradeable collaborator contract
*/
function failOpaque(
Error err,
FailureInfo info,
uint256 opaqueError
) internal returns (uint256) {
emit Failure(uint256(err), uint256(info), opaqueError);
return err == Error.COMPTROLLER_REJECTION ? 1000 + opaqueError : uint256(err);
}
}// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.0;
import "./CarefulMath.sol";
import "./ExponentialNoError.sol";
/**
* @title Exponential module for storing fixed-precision decimals
* @author Compound
* @dev Legacy contract for compatibility reasons with existing contracts that still use MathError
* @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 Exponential is CarefulMath, ExponentialNoError {
/**
* @dev Creates an exponential from numerator and denominator values.
* Note: Returns an error if (`num` * 10e18) > MAX_INT,
* or if `denom` is zero.
*/
function getExp(uint256 num, uint256 denom) internal pure returns (MathError, Exp memory) {
(MathError err0, uint256 scaledNumerator) = mulUInt(num, expScale);
if (err0 != MathError.NO_ERROR) {
return (err0, Exp({ mantissa: 0 }));
}
(MathError err1, uint256 rational) = divUInt(scaledNumerator, denom);
if (err1 != MathError.NO_ERROR) {
return (err1, Exp({ mantissa: 0 }));
}
return (MathError.NO_ERROR, Exp({ mantissa: rational }));
}
/**
* @dev Adds two exponentials, returning a new exponential.
*/
function addExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {
(MathError error, uint256 result) = addUInt(a.mantissa, b.mantissa);
return (error, Exp({ mantissa: result }));
}
/**
* @dev Subtracts two exponentials, returning a new exponential.
*/
function subExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {
(MathError error, uint256 result) = subUInt(a.mantissa, b.mantissa);
return (error, Exp({ mantissa: result }));
}
/**
* @dev Multiply an Exp by a scalar, returning a new Exp.
*/
function mulScalar(Exp memory a, uint256 scalar) internal pure returns (MathError, Exp memory) {
(MathError err0, uint256 scaledMantissa) = mulUInt(a.mantissa, scalar);
if (err0 != MathError.NO_ERROR) {
return (err0, Exp({ mantissa: 0 }));
}
return (MathError.NO_ERROR, Exp({ mantissa: scaledMantissa }));
}
/**
* @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.
*/
function mulScalarTruncate(Exp memory a, uint256 scalar) internal pure returns (MathError, uint256) {
(MathError err, Exp memory product) = mulScalar(a, scalar);
if (err != MathError.NO_ERROR) {
return (err, 0);
}
return (MathError.NO_ERROR, truncate(product));
}
/**
* @dev Divide an Exp by a scalar, returning a new Exp.
*/
function divScalar(Exp memory a, uint256 scalar) internal pure returns (MathError, Exp memory) {
(MathError err0, uint256 descaledMantissa) = divUInt(a.mantissa, scalar);
if (err0 != MathError.NO_ERROR) {
return (err0, Exp({ mantissa: 0 }));
}
return (MathError.NO_ERROR, Exp({ mantissa: descaledMantissa }));
}
/**
* @dev Divide a scalar by an Exp, returning a new Exp.
*/
function divScalarByExp(uint256 scalar, Exp memory divisor) internal pure returns (MathError, Exp memory) {
/*
We are doing this as:
getExp(mulUInt(expScale, scalar), divisor.mantissa)
How it works:
Exp = a / b;
Scalar = s;
`s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`
*/
(MathError err0, uint256 numerator) = mulUInt(expScale, scalar);
if (err0 != MathError.NO_ERROR) {
return (err0, Exp({ mantissa: 0 }));
}
return getExp(numerator, divisor.mantissa);
}
/**
* @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.
*/
function divScalarByExpTruncate(uint256 scalar, Exp memory divisor) internal pure returns (MathError, uint256) {
(MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);
if (err != MathError.NO_ERROR) {
return (err, 0);
}
return (MathError.NO_ERROR, truncate(fraction));
}
/**
* @dev Multiplies two exponentials, returning a new exponential.
*/
function mulExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {
(MathError err0, uint256 doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);
if (err0 != MathError.NO_ERROR) {
return (err0, Exp({ mantissa: 0 }));
}
// We add half the scale before dividing so that we get rounding instead of truncation.
// See "Listing 6" and text above it at https://accu.org/index.php/journals/1717
// Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.
(MathError err1, uint256 doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);
if (err1 != MathError.NO_ERROR) {
return (err1, Exp({ mantissa: 0 }));
}
(MathError err2, uint256 product) = divUInt(doubleScaledProductWithHalfScale, expScale);
// The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.
assert(err2 == MathError.NO_ERROR);
return (MathError.NO_ERROR, Exp({ mantissa: product }));
}
/**
* @dev Multiplies two exponentials given their mantissas, returning a new exponential.
*/
function mulExp(uint256 a, uint256 b) internal pure returns (MathError, Exp memory) {
return mulExp(Exp({ mantissa: a }), Exp({ mantissa: b }));
}
/**
* @dev Multiplies three exponentials, returning a new exponential.
*/
function mulExp3(
Exp memory a,
Exp memory b,
Exp memory c
) internal pure returns (MathError, Exp memory) {
(MathError err, Exp memory ab) = mulExp(a, b);
if (err != MathError.NO_ERROR) {
return (err, ab);
}
return mulExp(ab, c);
}
/**
* @dev Divides two exponentials, returning a new exponential.
* (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,
* which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)
*/
function divExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {
return getExp(a.mantissa, b.mantissa);
}
}// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.0;
/**
* @title Exponential module for storing fixed-precision decimals
* @author Compound
* @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.
* Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:
* `Exp({mantissa: 5100000000000000000})`.
*/
contract ExponentialNoError {
uint256 constant expScale = 1e18;
uint256 constant doubleScale = 1e36;
uint256 constant halfExpScale = expScale / 2;
uint256 constant mantissaOne = expScale;
struct Exp {
uint256 mantissa;
}
struct Double {
uint256 mantissa;
}
/**
* @dev Truncates the given exp to a whole number value.
* For example, truncate(Exp{mantissa: 15 * expScale}) = 15
*/
function truncate(Exp memory exp) internal pure returns (uint256) {
// 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, uint256 scalar) internal pure returns (uint256) {
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,
uint256 scalar,
uint256 addend
) internal pure returns (uint256) {
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) internal pure returns (bool) {
return left.mantissa < right.mantissa;
}
/**
* @dev Checks if left Exp <= right Exp.
*/
function lessThanOrEqualExp(Exp memory left, Exp memory right) internal pure returns (bool) {
return left.mantissa <= right.mantissa;
}
/**
* @dev Checks if left Exp > right Exp.
*/
function greaterThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {
return left.mantissa > right.mantissa;
}
/**
* @dev returns true if Exp is exactly zero
*/
function isZeroExp(Exp memory value) internal pure returns (bool) {
return value.mantissa == 0;
}
function safe224(uint256 n, string memory errorMessage) internal pure returns (uint224) {
require(n < 2**224, errorMessage);
return uint224(n);
}
function safe32(uint256 n, string memory errorMessage) internal pure returns (uint32) {
require(n < 2**32, errorMessage);
return uint32(n);
}
function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {
return Exp({ mantissa: add_(a.mantissa, b.mantissa) });
}
function add_(Double memory a, Double memory b) internal pure returns (Double memory) {
return Double({ mantissa: add_(a.mantissa, b.mantissa) });
}
function add_(uint256 a, uint256 b) internal pure returns (uint256) {
return add_(a, b, "addition overflow");
}
function add_(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, errorMessage);
return c;
}
function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {
return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });
}
function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {
return Double({ mantissa: sub_(a.mantissa, b.mantissa) });
}
function sub_(uint256 a, uint256 b) internal pure returns (uint256) {
return sub_(a, b, "subtraction underflow");
}
function sub_(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
require(b <= a, errorMessage);
return a - b;
}
function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {
return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / expScale });
}
function mul_(Exp memory a, uint256 b) internal pure returns (Exp memory) {
return Exp({ mantissa: mul_(a.mantissa, b) });
}
function mul_(uint256 a, Exp memory b) internal pure returns (uint256) {
return mul_(a, b.mantissa) / expScale;
}
function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {
return Double({ mantissa: mul_(a.mantissa, b.mantissa) / doubleScale });
}
function mul_(Double memory a, uint256 b) internal pure returns (Double memory) {
return Double({ mantissa: mul_(a.mantissa, b) });
}
function mul_(uint256 a, Double memory b) internal pure returns (uint256) {
return mul_(a, b.mantissa) / doubleScale;
}
function mul_(uint256 a, uint256 b) internal pure returns (uint256) {
return mul_(a, b, "multiplication overflow");
}
function mul_(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
if (a == 0 || b == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, errorMessage);
return c;
}
function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {
return Exp({ mantissa: div_(mul_(a.mantissa, expScale), b.mantissa) });
}
function div_(Exp memory a, uint256 b) internal pure returns (Exp memory) {
return Exp({ mantissa: div_(a.mantissa, b) });
}
function div_(uint256 a, Exp memory b) internal pure returns (uint256) {
return div_(mul_(a, expScale), b.mantissa);
}
function div_(Double memory a, Double memory b) internal pure returns (Double memory) {
return Double({ mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa) });
}
function div_(Double memory a, uint256 b) internal pure returns (Double memory) {
return Double({ mantissa: div_(a.mantissa, b) });
}
function div_(uint256 a, Double memory b) internal pure returns (uint256) {
return div_(mul_(a, doubleScale), b.mantissa);
}
function div_(uint256 a, uint256 b) internal pure returns (uint256) {
return div_(a, b, "divide by zero");
}
function div_(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a / b;
}
function fraction(uint256 a, uint256 b) internal pure returns (Double memory) {
return Double({ mantissa: div_(mul_(a, doubleScale), b) });
}
}// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.0;
interface IFuseFeeDistributor {
function minBorrowEth() external view returns (uint256);
function maxSupplyEth() external view returns (uint256);
function maxUtilizationRate() external view returns (uint256);
function interestFeeRate() external view returns (uint256);
function comptrollerImplementationWhitelist(address oldImplementation, address newImplementation)
external
view
returns (bool);
function pluginImplementationWhitelist(address oldImplementation, address newImplementation)
external
view
returns (bool);
function cErc20DelegateWhitelist(
address oldImplementation,
address newImplementation,
bool allowResign
) external view returns (bool);
function latestComptrollerImplementation(address oldImplementation) external view returns (address);
function latestCErc20Delegate(address oldImplementation)
external
view
returns (
address cErc20Delegate,
bool allowResign,
bytes memory becomeImplementationData
);
function latestPluginImplementation(address oldImplementation) external view returns (address);
function getComptrollerExtensions(address comptroller) external view returns (address[] memory);
function getCErc20DelegateExtensions(address cErc20Delegate) external view returns (address[] memory);
function deployCErc20(bytes calldata constructorData) external returns (address);
fallback() external payable;
receive() external payable;
}// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.0;
/**
* @title Compound's InterestRateModel Interface
* @author Compound
*/
abstract contract InterestRateModel {
/// @notice Indicator that this is an InterestRateModel contract (for inspection)
bool public constant isInterestRateModel = true;
/**
* @notice Calculates the current borrow interest rate per block
* @param cash The total amount of cash the market has
* @param borrows The total amount of borrows the market has outstanding
* @param reserves The total amount of reserves the market has
* @return The borrow rate per block (as a percentage, and scaled by 1e18)
*/
function getBorrowRate(
uint256 cash,
uint256 borrows,
uint256 reserves
) public view virtual returns (uint256);
/**
* @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(
uint256 cash,
uint256 borrows,
uint256 reserves,
uint256 reserveFactorMantissa
) public view virtual returns (uint256);
}// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.0;
import "./CTokenInterfaces.sol";
abstract contract PriceOracle {
/// @notice Indicator that this is a PriceOracle contract (for inspection)
bool public constant isPriceOracle = true;
/**
* @notice Get the underlying price of a cToken asset
* @param cToken The cToken to get the underlying price of
* @return The underlying asset price mantissa (scaled by 1e18).
* Zero means the price is unavailable.
*/
function getUnderlyingPrice(CTokenInterface cToken) external view virtual returns (uint256);
}// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.0;
/**
* @notice a base contract for logic extensions that use the diamond pattern storage
* to map the functions when looking up the extension contract to delegate to.
*/
abstract contract DiamondExtension {
/**
* @return a list of all the function selectors that this logic extension exposes
*/
function _getExtensionFunctions() external view virtual returns (bytes4[] memory);
}
// When no function exists for function called
error FunctionNotFound(bytes4 _functionSelector);
// When no extension exists for function called
error ExtensionNotFound(bytes4 _functionSelector);
// When the function is already added
error FunctionAlreadyAdded(bytes4 _functionSelector, address _currentImpl);
abstract contract DiamondBase {
/**
* @dev register a logic extension
* @param extensionToAdd the extension whose functions are to be added
* @param extensionToReplace the extension whose functions are to be removed/replaced
*/
function _registerExtension(DiamondExtension extensionToAdd, DiamondExtension extensionToReplace) external virtual;
function _listExtensions() public view returns (address[] memory) {
return LibDiamond.listExtensions();
}
fallback() external {
address extension = LibDiamond.getExtensionForFunction(msg.sig);
if (extension == address(0)) revert FunctionNotFound(msg.sig);
// Execute external function from extension using delegatecall and return any value.
assembly {
// copy function selector and any arguments
calldatacopy(0, 0, calldatasize())
// execute function call using the extension
let result := delegatecall(gas(), extension, 0, calldatasize(), 0, 0)
// get any return value
returndatacopy(0, 0, returndatasize())
// return any return value or error back to the caller
switch result
case 0 {
revert(0, returndatasize())
}
default {
return(0, returndatasize())
}
}
}
}
/**
* @notice a library to use in a contract, whose logic is extended with diamond extension
*/
library LibDiamond {
bytes32 constant DIAMOND_STORAGE_POSITION = keccak256("diamond.standard.diamond.storage");
struct Function {
address implementation;
uint16 index; // used to remove functions without looping
}
struct LogicStorage {
mapping(bytes4 => Function) functions;
bytes4[] selectorAtIndex;
address[] extensions;
}
function getExtensionForFunction(bytes4 msgSig) internal view returns (address) {
LibDiamond.LogicStorage storage ds = diamondStorage();
address extension = ds.functions[msgSig].implementation;
if (extension == address(0)) revert ExtensionNotFound(msgSig);
return extension;
}
function diamondStorage() internal pure returns (LogicStorage storage ds) {
bytes32 position = DIAMOND_STORAGE_POSITION;
assembly {
ds.slot := position
}
}
function listExtensions() internal view returns (address[] memory) {
return diamondStorage().extensions;
}
function registerExtension(DiamondExtension extensionToAdd, DiamondExtension extensionToReplace) internal {
if (address(extensionToReplace) != address(0)) {
removeExtension(extensionToReplace);
}
addExtension(extensionToAdd);
}
function removeExtension(DiamondExtension extension) internal {
LogicStorage storage ds = diamondStorage();
// remove all functions of the extension to replace
removeExtensionFunctions(extension);
for (uint8 i = 0; i < ds.extensions.length; i++) {
if (ds.extensions[i] == address(extension)) {
ds.extensions[i] = ds.extensions[ds.extensions.length - 1];
ds.extensions.pop();
}
}
}
function addExtension(DiamondExtension extension) internal {
LogicStorage storage ds = diamondStorage();
for (uint8 i = 0; i < ds.extensions.length; i++) {
require(ds.extensions[i] != address(extension), "extension already added");
}
addExtensionFunctions(extension);
ds.extensions.push(address(extension));
}
function removeExtensionFunctions(DiamondExtension extension) internal {
bytes4[] memory fnsToRemove = extension._getExtensionFunctions();
LogicStorage storage ds = diamondStorage();
for (uint16 i = 0; i < fnsToRemove.length; i++) {
bytes4 selectorToRemove = fnsToRemove[i];
// must never fail
assert(address(extension) == ds.functions[selectorToRemove].implementation);
// swap with the last element in the selectorAtIndex array and remove the last element
uint16 indexToKeep = ds.functions[selectorToRemove].index;
ds.selectorAtIndex[indexToKeep] = ds.selectorAtIndex[ds.selectorAtIndex.length - 1];
ds.functions[ds.selectorAtIndex[indexToKeep]].index = indexToKeep;
ds.selectorAtIndex.pop();
delete ds.functions[selectorToRemove];
}
}
function addExtensionFunctions(DiamondExtension extension) internal {
bytes4[] memory fnsToAdd = extension._getExtensionFunctions();
LogicStorage storage ds = diamondStorage();
uint16 selectorCount = uint16(ds.selectorAtIndex.length);
for (uint256 selectorIndex = 0; selectorIndex < fnsToAdd.length; selectorIndex++) {
bytes4 selector = fnsToAdd[selectorIndex];
address oldImplementation = ds.functions[selector].implementation;
if (oldImplementation != address(0)) revert FunctionAlreadyAdded(selector, oldImplementation);
ds.functions[selector] = Function(address(extension), selectorCount);
ds.selectorAtIndex.push(selector);
selectorCount++;
}
}
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.8.0;
/// @title Multicall interface
/// @notice Enables calling multiple methods in a single call to the contract
interface IMulticall {
/// @notice Call multiple functions in the current contract and return the data from all of them if they all succeed
/// @dev The `msg.value` should not be trusted for any method callable from multicall.
/// @param data The encoded function data for each of the calls to make to this contract
/// @return results The results from each of the calls passed in via data
function multicall(bytes[] calldata data) external payable returns (bytes[] memory results);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.8.0;
import "./IMulticall.sol";
/// @title Multicall
/// @notice Enables calling multiple methods in a single call to the contract
abstract contract Multicall is IMulticall {
/// @inheritdoc IMulticall
function multicall(bytes[] calldata data) public payable override returns (bytes[] memory results) {
results = new bytes[](data.length);
for (uint256 i = 0; i < data.length; i++) {
(bool success, bytes memory result) = address(this).delegatecall(data[i]);
if (!success) {
// Next 5 lines from https://ethereum.stackexchange.com/a/83577
if (result.length < 68) revert();
assembly {
result := add(result, 0x04)
}
revert(abi.decode(result, (string)));
}
results[i] = result;
}
}
}{
"remappings": [],
"optimizer": {
"enabled": true,
"runs": 2
},
"metadata": {
"useLiteralContent": true,
"bytecodeHash": "none"
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"abi"
]
}
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"bytes4","name":"_functionSelector","type":"bytes4"}],"name":"ExtensionNotFound","type":"error"},{"inputs":[{"internalType":"bytes4","name":"_functionSelector","type":"bytes4"},{"internalType":"address","name":"_currentImpl","type":"address"}],"name":"FunctionAlreadyAdded","type":"error"},{"inputs":[{"internalType":"bytes4","name":"_functionSelector","type":"bytes4"}],"name":"FunctionNotFound","type":"error"},{"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":"uint256","name":"error","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"info","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"detail","type":"uint256"}],"name":"Failure","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"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":"uint256","name":"oldAdminFeeMantissa","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newAdminFeeMantissa","type":"uint256"}],"name":"NewAdminFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldFuseFeeMantissa","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newFuseFeeMantissa","type":"uint256"}],"name":"NewFuseFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldImplementation","type":"address"},{"indexed":false,"internalType":"address","name":"newImplementation","type":"address"}],"name":"NewImplementation","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":"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"},{"stateMutability":"nonpayable","type":"fallback"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"}],"name":"_becomeImplementation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"_listExtensions","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_prepare","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"contract DiamondExtension","name":"extensionToAdd","type":"address"},{"internalType":"contract DiamondExtension","name":"extensionToReplace","type":"address"}],"name":"_registerExtension","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"implementation_","type":"address"},{"internalType":"bool","name":"allowResign","type":"bool"},{"internalType":"bytes","name":"becomeImplementationData","type":"bytes"}],"name":"_setImplementationSafe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"withdrawAmount","type":"uint256"}],"name":"_withdrawAdminFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"withdrawAmount","type":"uint256"}],"name":"_withdrawFuseFees","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":"adminFeeMantissa","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"asCTokenExtensionInterface","outputs":[{"internalType":"contract CTokenExtensionInterface","name":"","type":"address"}],"stateMutability":"view","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":"comptroller","outputs":[{"internalType":"contract ComptrollerInterface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contractType","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeSeizeShareMantissa","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fuseAdmin","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fuseFeeMantissa","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getAccountSnapshot","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCash","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"implementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"underlying_","type":"address"},{"internalType":"contract ComptrollerInterface","name":"comptroller_","type":"address"},{"internalType":"address payable","name":"fuseAdmin_","type":"address"},{"internalType":"contract InterestRateModel","name":"interestRateModel_","type":"address"},{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"},{"internalType":"uint256","name":"reserveFactorMantissa_","type":"uint256"},{"internalType":"uint256","name":"adminFeeMantissa_","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ComptrollerInterface","name":"comptroller_","type":"address"},{"internalType":"address payable","name":"fuseAdmin_","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":"uint256","name":"reserveFactorMantissa_","type":"uint256"},{"internalType":"uint256","name":"adminFeeMantissa_","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"interestRateModel","outputs":[{"internalType":"contract InterestRateModel","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isCEther","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isCToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"borrower","type":"address"},{"internalType":"uint256","name":"repayAmount","type":"uint256"},{"internalType":"contract CTokenInterface","name":"cTokenCollateral","type":"address"}],"name":"liquidateBorrow","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"mintAmount","type":"uint256"}],"name":"mint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"protocolSeizeShareMantissa","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"redeemTokens","type":"uint256"}],"name":"redeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"redeemAmount","type":"uint256"}],"name":"redeemUnderlying","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"repayAmount","type":"uint256"}],"name":"repayBorrow","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"borrower","type":"address"},{"internalType":"uint256","name":"repayAmount","type":"uint256"}],"name":"repayBorrowBehalf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"reserveFactorMantissa","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"liquidator","type":"address"},{"internalType":"address","name":"borrower","type":"address"},{"internalType":"uint256","name":"seizeTokens","type":"uint256"}],"name":"seize","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalAdminFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalBorrows","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalFuseFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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":[],"name":"underlying","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]Contract Creation Code
608060405234801561001057600080fd5b5061598b80620000216000396000f3fe60806040526004361061020d5760003560e01c806306db3ecd1461029557806306fdde03146102b75780630e752702146102e257806315761d5114610310578063173b99041461033d57806317bfdfbc1461035357806318160ddd146103735780631db7894414610389578063219ef65c146103915780632608f818146103b1578063313ce567146103d15780633b1d21a2146103fd57806347bd37181461041257806350d85b731461042857806356e67728146104485780635c60da1b146104685780635fe3b5671461048857806361feacff146104a85780636333d001146104be5780636752e702146104e05780636c540baf146104fb5780636f307dc314610511578063852a12e31461053157806389cd9855146105515780638d02d9a1146105715780638f840ddd1461058757806395d89b411461059d57806395dd9193146105b25780639f5ef272146105d2578063a03dce8d146105e5578063a0712d6814610605578063a7b820df14610625578063aa5af0fd14610645578063ac784ddc1461065b578063ac9650d81461067b578063b2a02ff11461069b578063be99f119146106bb578063c37f68e2146106d7578063c5ebeaec14610717578063cb2ef6f714610737578063db006a751461076e578063dbfe7c191461078e578063dc028ab1146107a4578063f3fdb15a146107ba578063f5e3c462146107da578063fe9c44ae146107fa575b34801561021957600080fd5b5060006102316000356001600160e01b03191661080e565b90506001600160a01b038116610271576000356001600160e01b031916604051630a82dd7360e31b81526004016102689190614d2e565b60405180910390fd5b3660008037600080366000845af43d6000803e808015610290573d6000f35b3d6000fd5b3480156102a157600080fd5b506102b56102b0366004614e33565b610866565b005b3480156102c357600080fd5b506102cc610974565b6040516102d99190614f4c565b60405180910390f35b3480156102ee57600080fd5b506103026102fd366004614f5f565b610a02565b6040519081526020016102d9565b34801561031c57600080fd5b50600154610330906001600160a01b031681565b6040516102d99190614f78565b34801561034957600080fd5b50610302600b5481565b34801561035f57600080fd5b5061030261036e366004614f8c565b610a16565b34801561037f57600080fd5b5061030260125481565b6102b5610ae2565b34801561039d57600080fd5b506102b56103ac366004614fc3565b610c18565b3480156103bd57600080fd5b506103026103cc36600461508a565b611058565b3480156103dd57600080fd5b506005546103eb9060ff1681565b60405160ff90911681526020016102d9565b34801561040957600080fd5b50610302611070565b34801561041e57600080fd5b50610302600e5481565b34801561043457600080fd5b506102b56104433660046150c4565b61107f565b34801561045457600080fd5b506102b5610463366004615155565b6110ff565b34801561047457600080fd5b50600054610330906001600160a01b031681565b34801561049457600080fd5b50600654610330906001600160a01b031681565b3480156104b457600080fd5b5061030260105481565b3480156104ca57600080fd5b506104d3611151565b6040516102d9919061519d565b3480156104ec57600080fd5b50610302666379da05b6000081565b34801561050757600080fd5b50610302600c5481565b34801561051d57600080fd5b50601654610330906001600160a01b031681565b34801561053d57600080fd5b5061030261054c366004614f5f565b61115b565b34801561055d57600080fd5b506102b561056c3660046151ea565b611166565b34801561057d57600080fd5b5061030260095481565b34801561059357600080fd5b50610302600f5481565b3480156105a957600080fd5b506102cc61123a565b3480156105be57600080fd5b506103026105cd366004614f8c565b611247565b3480156105de57600080fd5b5030610330565b3480156105f157600080fd5b50610302610600366004614f5f565b61136b565b34801561061157600080fd5b50610302610620366004614f5f565b61148c565b34801561063157600080fd5b50610302610640366004614f5f565b611498565b34801561065157600080fd5b50610302600d5481565b34801561066757600080fd5b5060005b60405190151581526020016102d9565b61068e610689366004615223565b611609565b6040516102d99190615297565b3480156106a757600080fd5b506103026106b63660046152f9565b611760565b3480156106c757600080fd5b5061030267016345785d8a000081565b3480156106e357600080fd5b506106f76106f2366004614f8c565b611784565b6040805194855260208501939093529183015260608201526080016102d9565b34801561072357600080fd5b50610302610732366004614f5f565b611827565b34801561074357600080fd5b5060408051808201909152600e81526d43457263323044656c656761746560901b60208201526102cc565b34801561077a57600080fd5b50610302610789366004614f5f565b611832565b34801561079a57600080fd5b50610302600a5481565b3480156107b057600080fd5b5061030260115481565b3480156107c657600080fd5b50600754610330906001600160a01b031681565b3480156107e657600080fd5b506103026107f536600461533a565b61183d565b34801561080657600080fd5b50600161066b565b600080610819611855565b6001600160e01b031984166000908152602082905260409020549091506001600160a01b03168061085f5783604051631f3f429960e31b81526004016102689190614d2e565b9392505050565b60006702c68af0bb14000090506000896001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108d7919061537c565b90506108ea898989858a8a878b8b610c18565b601680546001600160a01b0319166001600160a01b038c16908117909155604080516318160ddd60e01b815290516318160ddd916004808201926020929091908290030181865afa158015610943573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109679190615399565b5050505050505050505050565b60038054610981906153b2565b80601f01602080910402602001604051908101604052809291908181526020018280546109ad906153b2565b80156109fa5780601f106109cf576101008083540402835291602001916109fa565b820191906000526020600020905b8154815290600101906020018083116109dd57829003601f168201915b505050505081565b600080610a0e83611879565b509392505050565b600080610a228161193d565b6000306001600160a01b031663a6afed956040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610a64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a889190615399565b14610ac75760405162461bcd60e51b815260206004820152600f60248201526e085858d8dc9d59525b9d195c995cdd608a1b6044820152606401610268565b610ad083611247565b91505b610adc81611a01565b50919050565b333014801590610b645750600660009054906101000a90046001600160a01b03166001600160a01b031663dd5cd22c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b40573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b6491906153fd565b15610c1657600154600080546040516345cc970560e01b81529192839283926001600160a01b03928316926345cc970592610ba59290911690600401614f78565b600060405180830381865afa158015610bc2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610bea919081019061544a565b60005492955090935091506001600160a01b03808516911614610c1257610c12838383611a84565b5050505b565b336001600160a01b03891614610c405760405162461bcd60e51b8152600401610268906154c1565b600c54158015610c505750600d54155b610c8b5760405162461bcd60e51b815260206004820152600c60248201526b085a5b9a5d1a585b1a5e995960a21b6044820152606401610268565b600180546001600160a01b0319166001600160a01b038a16179055600886905585610cea5760405162461bcd60e51b815260206004820152600f60248201526e02165786368616e6765526174653e3608c1b6044820152606401610268565b600680546001600160a01b0319166001600160a01b038b81169190911790915543600c55670de0b6b3a7640000600d55604080516310c8fc9560e11b8152905191891691632191f92a916004808201926020929091908290030181865afa158015610d59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d7d91906153fd565b610db35760405162461bcd60e51b8152602060048201526007602482015266216e6f7449726d60c81b6044820152606401610268565b600780546001600160a01b0319166001600160a01b0389161790556040517fedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f92690610e01906000908a906154e1565b60405180910390a18451610e1c906003906020880190614c44565b508351610e30906004906020870190614c44565b506005805460ff191660ff8516179055600a54600954670de0b6b3a76400009190610e5b9085615511565b610e659190615511565b1115610e9d5760405162461bcd60e51b8152602060048201526007602482015266085c998e9cd95d60ca1b6044820152606401610268565b600b8290556040805160008152602081018490527faaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460910160405180910390a1600019811415610eeb57506009545b6001546040805163dd86fea160e01b815290516000926001600160a01b03169163dd86fea19160048083019260209291908290030181865afa158015610f35573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f599190615399565b9050670de0b6b3a76400008183600b54610f739190615511565b610f7d9190615511565b1115610fbb5760405162461bcd60e51b815260206004820152600d60248201526c0858591b5a5b9199594e9cd95d609a1b6044820152606401610268565b60098290556040805160008152602081018490527fcdd0b588250e1398549f79cfdb8217c186688822905d6715b0834ea1c865594a910160405180910390a1600a8190556040805160008152602081018390527f92eef861b6533b7d3417f39c2ad7b460eed4e88a32fa3604f30e718b7602e7dc910160405180910390a150506002805460ff60b01b1916600160b01b1790555050505050505050565b6000806110658484611d11565b509150505b92915050565b600061107a611dd7565b905090565b611087611e51565b6110a35760405162461bcd60e51b8152600401610268906154c1565b6000546001600160a01b038581169116146110f9576110f9848484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611a8492505050565b50505050565b333014806111105750611110611e51565b61114e5760405162461bcd60e51b815260206004820152600f60248201526e10b9b2b633103e3e1010b0b236b4b760891b6044820152606401610268565b50565b606061107a611fbc565b600061106a82612027565b6006546001546001600160a01b039182169116331480156111e45750806001600160a01b0316632f1069ba6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e491906153fd565b6112305760405162461bcd60e51b815260206004820152601f60248201527f21756e617574686f72697a6564202d206e6f2061646d696e20726967687473006044820152606401610268565b610c1283836120c9565b60048054610981906153b2565b6001600160a01b03811660009081526015602052604081208054829182918291906112785750600095945050505050565b6112888160000154600d546120ee565b909450925060008460038111156112a1576112a16153e7565b146112ee5760405162461bcd60e51b815260206004820152601e60248201527f216d756c55496e74206f766572666c6f7720636865636b206661696c656400006044820152606401610268565b6112fc838260010154612130565b90945091506000846003811115611315576113156153e7565b146113625760405162461bcd60e51b815260206004820152601e60248201527f2164697655496e74206f766572666c6f7720636865636b206661696c656400006044820152606401610268565b50949350505050565b6000806113778161193d565b6000306001600160a01b031663a6afed956040518163ffffffff1660e01b81526004016020604051808303816000875af11580156113b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113dd9190615399565b90508015611409576114018160118111156113fa576113fa6153e7565b603361215b565b925050610ad3565b43600c541461141e57611401600a603561215b565b83611427611dd7565b101561143957611401600e603461215b565b60115484111561144f576114016002603661215b565b60008460115461145f9190615529565b601181905560015490915061147d906001600160a01b0316866121bb565b600093505050610adc81611a01565b600080610a0e83612243565b6000806114a48161193d565b6000306001600160a01b031663a6afed956040518163ffffffff1660e01b81526004016020604051808303816000875af11580156114e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061150a9190615399565b9050801561152e57611401816011811115611527576115276153e7565b603761215b565b43600c541461154357611401600a603961215b565b8361154c611dd7565b101561155e57611401600e603861215b565b601054841115611574576114016002603a61215b565b836010546115829190615529565b601055600654604080516303e1469160e61b815290516115fa926001600160a01b03169163f851a4409160048083019260209291908290030181865afa1580156115d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115f49190615540565b856121bb565b60005b925050610adc81611a01565b6060816001600160401b0381111561162357611623614d68565b60405190808252806020026020018201604052801561165657816020015b60608152602001906001900390816116415790505b50905060005b82811015611759576000803086868581811061167a5761167a61555d565b905060200281019061168c9190615573565b60405161169a9291906155b9565b600060405180830381855af49150503d80600081146116d5576040519150601f19603f3d011682016040523d82523d6000602084013e6116da565b606091505b509150915081611726576044815110156116f357600080fd5b6004810190508080602001905181019061170d91906155c9565b60405162461bcd60e51b81526004016102689190614f4c565b808484815181106117395761173961555d565b60200260200101819052505050808061175190615611565b91505061165c565b5092915050565b6000600161176d8161193d565b611779338686866122e5565b9150610a0e81611a01565b6001600160a01b0381166000908152601360205260408120548190819081908180806117af89611247565b9250306001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa1580156117ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118139190615399565b915060009993985091965094509092505050565b600061106a826127b1565b600061106a82612851565b60008061184b8585856128ec565b5095945050505050565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c90565b60008060006118878161193d565b6000306001600160a01b031663a6afed956040518163ffffffff1660e01b81526004016020604051808303816000875af11580156118c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ed9190615399565b9050801561191d5761191181601181111561190a5761190a6153e7565b604161215b565b6000935093505061192e565b611928333387612a9d565b93509350505b61193781611a01565b50915091565b600254600160b01b900460ff166119835760405162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b6044820152606401610268565b806119f157600660009054906101000a90046001600160a01b03166001600160a01b031663c90c20b16040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156119d857600080fd5b505af11580156119ec573d6000803e3d6000fd5b505050505b506002805460ff60b01b19169055565b6002805460ff60b01b1916600160b01b1790558061114e57600660009054906101000a90046001600160a01b03166001600160a01b031663632e51426040518163ffffffff1660e01b8152600401600060405180830381600087803b158015611a6957600080fd5b505af1158015611a7d573d6000803e3d6000fd5b5050505050565b6001546000546040516338e6a07360e11b81526001600160a01b03928316926371cd40e692611abc929116908790879060040161562c565b602060405180830381865afa158015611ad9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611afd91906153fd565b611b315760405162461bcd60e51b8152602060048201526005602482015264085a5b5c1b60da1b6044820152606401610268565b600080546001600160a01b038581166001600160a01b03198316811784556001546040516311a0e21760e01b815293831694939216916311a0e21791611b7991600401614f78565b600060405180830381865afa158015611b96573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611bbe9190810190615673565b90506000611bca611fbc565b905060005b8151811015611c0c57611bfa828281518110611bed57611bed61555d565b6020026020010151612e3f565b80611c0481615611565b915050611bcf565b5060005b8251811015611c4d57611c3b838281518110611c2e57611c2e61555d565b6020026020010151612f6c565b80611c4581615611565b915050611c10565b50303b611c6257611c5d846110ff565b611cc4565b611cc23085604051602401611c779190614f4c565b60408051601f19818403018152918152602080830180516001600160e01b0316630adccee560e31b17905281518083019092526007825266216265636f6d6560c81b9082015261305b565b505b6000546040517fd604de94d45953f9138079ec1b82d533cb2160c906d1076d1f7ed54befbca97a91611d019186916001600160a01b0316906154e1565b60405180910390a1505050505050565b6000806000611d1f8161193d565b6000306001600160a01b031663a6afed956040518163ffffffff1660e01b81526004016020604051808303816000875af1158015611d61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d859190615399565b90508015611db557611da9816011811115611da257611da26153e7565b604061215b565b60009350935050611dc6565b611dc0338787612a9d565b93509350505b611dcf81611a01565b509250929050565b6016546040516370a0823160e01b81526000916001600160a01b03169081906370a0823190611e0a903090600401614f78565b602060405180830381865afa158015611e27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e4b9190615399565b91505090565b600654604080516303e1469160e61b815290516000926001600160a01b031691829163f851a440916004808201926020929091908290030181865afa158015611e9e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec29190615540565b6001600160a01b0316336001600160a01b0316148015611f3f5750806001600160a01b0316630a755ec26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f3f91906153fd565b80611e4b57506001546001600160a01b031633148015611e4b5750806001600160a01b0316632f1069ba6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f98573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e4b91906153fd565b6060611fc6611855565b60020180548060200260200160405190810160405280929190818152602001828054801561201d57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611fff575b5050505050905090565b6000806120338161193d565b6000306001600160a01b031663a6afed956040518163ffffffff1660e01b81526004016020604051808303816000875af1158015612075573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120999190615399565b905080156120bd576114018160118111156120b6576120b66153e7565b602a61215b565b6115fd336000866130f7565b6001600160a01b038116156120e1576120e181612e3f565b6120ea82612f6c565b5050565b6000808361210157506000905080612129565b8383028361210f868361570c565b1461212257600260009250925050612129565b6000925090505b9250929050565b600080826121445750600190506000612129565b6000612150848661570c565b915091509250929050565b600060008051602061593f83398151915283601181111561217e5761217e6153e7565b836061811115612190576121906153e7565b60006040516121a19392919061572e565b60405180910390a182601181111561085f5761085f6153e7565b6120ea63a9059cbb60e01b83836040516024016121d9929190615744565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b038381831617835250505050604051806040016040528060198152602001781513d2d15397d514905394d1915497d3d55517d19052531151603a1b815250613698565b60008060006122518161193d565b6000306001600160a01b031663a6afed956040518163ffffffff1660e01b81526004016020604051808303816000875af1158015612293573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122b79190615399565b905080156122db576119118160118111156122d4576122d46153e7565b602061215b565b61192833866136ef565b60065460405163d02f735160e01b815260009182916001600160a01b039091169063d02f7351906123229030908a908a908a908a9060040161575d565b6020604051808303816000875af1158015612341573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123659190615399565b905080156123825761237a6003601d83613a24565b9150506127a9565b846001600160a01b0316846001600160a01b031614156123a85761237a6006601e61215b565b61240d604080516101808101909152806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6001600160a01b0385166000908152601360205260409020546124309085613aad565b602083018190528282600381111561244a5761244a6153e7565b600381111561245b5761245b6153e7565b9052506000905081516003811115612475576124756153e7565b146124a55761249c6009601c83600001516003811115612497576124976153e7565b613a24565b925050506127a9565b6124c4846040518060200160405280666379da05b60000815250613ad8565b6080820152604080516020810190915267016345785d8a000081526124ea908590613ad8565b610140820181905260808201516125019086615529565b61250b9190615529565b6060820152306001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa15801561254e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125729190615399565b60c0820190815260408051602081019091529051815260808201516125979190613afb565b60a0820152604080516020810190915260c082015181526101408201516125be9190613afb565b61016082015260a0810151600f546125d69190615511565b60e082015261014081015160808201516012546125f39190615529565b6125fd9190615529565b6101208201526101608101516011546126169190615511565b6101008201526001600160a01b03861660009081526013602052604090205460608201516126449190613b13565b604083018190528282600381111561265e5761265e6153e7565b600381111561266f5761266f6153e7565b9052506000905081516003811115612689576126896153e7565b146126ab5761249c6009601b83600001516003811115612497576124976153e7565b60e0810151600f556101208101516012556101008101516011556020808201516001600160a01b0387811660008181526013855260408082209490945583860151928b168082529084902092909255606085015192519283529092909160008051602061595f833981519152910160405180910390a3306001600160a01b0316856001600160a01b031660008051602061595f833981519152836080015160405161275891815260200190565b60405180910390a360a081015160e08201516040517fa91e67c5ea634cd43a12c5a482724b03de01e85ca68702a53d0c2f45cb7c1dc59261279a923092615790565b60405180910390a16000925050505b949350505050565b6000806127bd8161193d565b6000306001600160a01b031663a6afed956040518163ffffffff1660e01b81526004016020604051808303816000875af11580156127ff573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128239190615399565b9050801561284757611401816011811115612840576128406153e7565b600a61215b565b6115fd3385613b39565b60008061285d8161193d565b6000306001600160a01b031663a6afed956040518163ffffffff1660e01b81526004016020604051808303816000875af115801561289f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128c39190615399565b905080156128e0576114018160118111156120b6576120b66153e7565b6115fd338560006130f7565b60008060006128fa8161193d565b6000306001600160a01b031663a6afed956040518163ffffffff1660e01b81526004016020604051808303816000875af115801561293c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129609190615399565b905080156129905761298481601181111561297d5761297d6153e7565b601161215b565b60009350935050612a8b565b846001600160a01b0316639f5ef2726040518163ffffffff1660e01b8152600401602060405180830381865afa1580156129ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129f29190615540565b6001600160a01b031663a6afed956040518163ffffffff1660e01b81526004016020604051808303816000875af1158015612a31573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a559190615399565b90508015612a7957612984816011811115612a7257612a726153e7565b601261215b565b612a8533888888613e66565b93509350505b612a9481611a01565b50935093915050565b600654604051631200453160e11b81523060048201526001600160a01b03858116602483015284811660448301526064820184905260009283928392909116906324008a62906084016020604051808303816000875af1158015612b05573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b299190615399565b90508015612b4a57612b3e6003604383613a24565b60009250925050612e37565b43600c5414612b5f57612b3e600a604461215b565b612ba86040805161010081019091528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6001600160a01b0386166000908152601560205260409020600101546060820152612bd286611247565b6080820152600019851415612bf05760808101516040820152612bf8565b604081018590525b612c06878260400151614362565b60e082018190526080820151612c1b91613aad565b60a0830181905260208301826003811115612c3857612c386153e7565b6003811115612c4957612c496153e7565b9052506000905081602001516003811115612c6657612c666153e7565b14612cd65760405162461bcd60e51b815260206004820152603a60248201527f52455041595f424f52524f575f4e45575f4143434f554e545f424f52524f575f604482015279109053105390d157d0d05310d55310551253d397d1905253115160321b6064820152608401610268565b612ce6600e548260e00151613aad565b60c0830181905260208301826003811115612d0357612d036153e7565b6003811115612d1457612d146153e7565b9052506000905081602001516003811115612d3157612d316153e7565b14612d985760405162461bcd60e51b815260206004820152603160248201527f52455041595f424f52524f575f4e45575f544f54414c5f42414c414e43455f43604482015270105310d55310551253d397d19052531151607a1b6064820152608401610268565b60a081810180516001600160a01b03898116600081815260156020908152604091829020948555600d5460019095019490945560c0870151600e81905560e088015195518251948f16855294840192909252820193909352606081019190915260808101919091527f1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a1910160405180910390a160e00151600093509150505b935093915050565b6000612e49611855565b9050612e548261452e565b60005b600282015460ff82161015610c1257826001600160a01b0316826002018260ff1681548110612e8857612e8861555d565b6000918252602090912001546001600160a01b03161415612f5a57600282018054612eb590600190615529565b81548110612ec557612ec561555d565b6000918252602090912001546002830180546001600160a01b039092169160ff8416908110612ef657612ef661555d565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555081600201805480612f3757612f376157b1565b600082815260209020810160001990810180546001600160a01b03191690550190555b80612f64816157c7565b915050612e57565b6000612f76611855565b905060005b600282015460ff8216101561301b57826001600160a01b0316826002018260ff1681548110612fac57612fac61555d565b6000918252602090912001546001600160a01b031614156130095760405162461bcd60e51b8152602060048201526017602482015276195e1d195b9cda5bdb88185b1c9958591e481859191959604a1b6044820152606401610268565b80613013816157c7565b915050612f7b565b50613025826147b8565b6002018054600181018255600091825260209091200180546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080856001600160a01b03168560405161307891906157e7565b6000604051808303816000865af19150503d80600081146130b5576040519150601f19603f3d011682016040523d82523d6000602084013e6130ba565b606091505b5091509150816130ee578051156130d45780518082602001fd5b8360405162461bcd60e51b81526004016102689190614f4c565b95945050505050565b6000821580613104575081155b61314a5760405162461bcd60e51b815260206004820152601760248201527602172656465656d546f6b656e73496e6f724f7574213d3604c1b6044820152606401610268565b613152614cc8565b306001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015613190573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131b49190615399565b604082015260001983141561323e57600654604051630cbb414760e11b81526001600160a01b0390911690631976828e906131f8908890309060009060040161562c565b6020604051808303816000875af1158015613217573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061323b9190615399565b92505b83156132df5760608101849052604080516020810182529082015181526132659085614981565b6080830181905260208301826003811115613282576132826153e7565b6003811115613293576132936153e7565b90525060009050816020015160038111156132b0576132b06153e7565b146132da576132d26009602c83602001516003811115612497576124976153e7565b91505061085f565b613370565b6132fb83604051806020016040528084604001518152506149d3565b6060830181905260208301826003811115613318576133186153e7565b6003811115613329576133296153e7565b9052506000905081602001516003811115613346576133466153e7565b14613368576132d26009602d83602001516003811115612497576124976153e7565b608081018390525b600654606082015160405163eabe7d9160e01b81526000926001600160a01b03169163eabe7d91916133a99130918b9190600401615803565b6020604051808303816000875af11580156133c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133ec9190615399565b9050801561340a576134016003602b83613a24565b9250505061085f565b43600c541461341f57613401600a602f61215b565b61342f6012548360600151613aad565b60a084018190526020840182600381111561344c5761344c6153e7565b600381111561345d5761345d6153e7565b905250600090508260200151600381111561347a5761347a6153e7565b1461349c576134016009603184602001516003811115612497576124976153e7565b6001600160a01b03861660009081526013602052604090205460608301516134c49190613aad565b60c08401819052602084018260038111156134e1576134e16153e7565b60038111156134f2576134f26153e7565b905250600090508260200151600381111561350f5761350f6153e7565b14613531576134016009603084602001516003811115612497576124976153e7565b816080015161353e611dd7565b101561355057613401600e603261215b565b60a082015160125560c08201516001600160a01b03871660009081526013602052604090205560808201516135869087906121bb565b306001600160a01b0316866001600160a01b031660008051602061595f83398151915284606001516040516135bd91815260200190565b60405180910390a3608082015160608301516040517fe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a929926135ff928a92615790565b60405180910390a1600654608083015160608401516040516351dff98960e01b81523060048201526001600160a01b038a81166024830152604482019390935260648101919091529116906351dff98990608401600060405180830381600087803b15801561366d57600080fd5b505af1158015613681573d6000803e3d6000fd5b506000925061368e915050565b9695505050505050565b6016546000906136b2906001600160a01b0316848461305b565b805190915015610c1257808060200190518101906136d091906153fd565b82906110f95760405162461bcd60e51b81526004016102689190614f4c565b600654604051634ef4c3e160e01b8152600091829182916001600160a01b031690634ef4c3e19061372890309089908990600401615803565b6020604051808303816000875af1158015613747573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061376b9190615399565b9050801561378c576137806003602183613a24565b60009250925050612129565b43600c54146137a157613780600a602461215b565b6137a9614cc8565b306001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa1580156137e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061380b9190615399565b604082015261381a8686614362565b60c082018190526040805160208101825290830151815261383b91906149d3565b6060830181905260208301826003811115613858576138586153e7565b6003811115613869576138696153e7565b9052506000905081602001516003811115613886576138866153e7565b146138d35760405162461bcd60e51b815260206004820181905260248201527f4d494e545f45584348414e47455f43414c43554c4154494f4e5f4641494c45446044820152606401610268565b60008160600151116139245760405162461bcd60e51b815260206004820152601a6024820152791352539517d6915493d7d0d513d2d15394d7d491529150d5115160321b6044820152606401610268565b80606001516012546139369190615511565b608082015260608101516001600160a01b0387166000908152601360205260409020546139639190615511565b60a0820181905260808201516012556001600160a01b038716600090815260136020526040908190209190915560c0820151606083015191517f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f926139cc928a92909190615790565b60405180910390a1856001600160a01b0316306001600160a01b031660008051602061595f8339815191528360600151604051613a0b91815260200190565b60405180910390a360c001516000969095509350505050565b600060008051602061593f833981519152846011811115613a4757613a476153e7565b846061811115613a5957613a596153e7565b84604051613a699392919061572e565b60405180910390a16003846011811115613a8557613a856153e7565b14613aa157836011811115613a9c57613a9c6153e7565b6127a9565b6127a9826103e8615511565b600080838311613acc576000613ac38486615529565b91509150612129565b50600390506000612129565b6000670de0b6b3a7640000613af18484600001516149e3565b61085f919061570c565b600080613b088484614a1f565b90506127a981614a49565b600080838301848110613b2b57600092509050612129565b600260009250925050612129565b60065460405163368f515360e21b815260009182916001600160a01b039091169063da3d454c90613b7290309088908890600401615803565b6020604051808303816000875af1158015613b91573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613bb59190615399565b90508015613bd257613bca6003601083613a24565b91505061106a565b43600c5414613be757613bca600a600c61215b565b6000613bf1611dd7565b905083811015613c1057613c07600e600b61215b565b9250505061106a565b613c3c604080516080810190915280600081526020016000815260200160008152602001600081525090565b613c4586611247565b60208201819052613c569086613b13565b6040830181905282826003811115613c7057613c706153e7565b6003811115613c8157613c816153e7565b9052506000905081516003811115613c9b57613c9b6153e7565b14613cc757613cbd6009600e83600001516003811115612497576124976153e7565b935050505061106a565b6006546040808301519051631de6c8a560e21b81526001600160a01b039092169163779b229491613cfd91309190600401615744565b602060405180830381865afa158015613d1a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d3e9190615399565b92508215613d5357613cbd6003601085613a24565b613d5f600e5486613b13565b6060830181905282826003811115613d7957613d796153e7565b6003811115613d8a57613d8a6153e7565b9052506000905081516003811115613da457613da46153e7565b14613dc657613cbd6009600d83600001516003811115612497576124976153e7565b6040808201516001600160a01b0388166000908152601560205291909120908155600d546001909101556060810151600e55613e0286866121bb565b60408082015160608084015183516001600160a01b038b168152602081018a9052938401929092528201527f13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab809060800160405180910390a160009695505050505050565b600654604051632fe3f38f60e11b8152600091829182916001600160a01b031690635fc7e71e90613ea390309088908c908c908c9060040161575d565b6020604051808303816000875af1158015613ec2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ee69190615399565b90508015613f0757613efb6003601483613a24565b60009250925050614359565b43600c5414613f1c57613efb600a601861215b565b43846001600160a01b0316636c540baf6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613f5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f7f9190615399565b14613f9057613efb600a601361215b565b866001600160a01b0316866001600160a01b03161415613fb657613efb6006601961215b565b84613fc757613efb6007601761215b565b600019851415613fdd57613efb6007601661215b565b600080613feb898989612a9d565b909250905081156140205761401282601181111561400b5761400b6153e7565b601a61215b565b600094509450505050614359565b60065460405163c488847b60e01b815260009182916001600160a01b039091169063c488847b906140599030908c908890600401615803565b6040805180830381865afa158015614075573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140999190615827565b909250905081156141085760405162461bcd60e51b815260206004820152603360248201527f4c49515549444154455f434f4d5054524f4c4c45525f43414c43554c4154455f604482015272105353d5539517d4d152569157d19052531151606a1b6064820152608401610268565b80886001600160a01b0316639f5ef2726040518163ffffffff1660e01b8152600401602060405180830381865afa158015614147573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061416b9190615540565b6001600160a01b03166370a082318c6040518263ffffffff1660e01b81526004016141969190614f78565b602060405180830381865afa1580156141b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141d79190615399565b10156142205760405162461bcd60e51b815260206004820152601860248201527709892a2aa928882a88abea68a92b48abea89e9ebe9aaa86960431b6044820152606401610268565b60006001600160a01b0389163014156142465761423f308d8d856122e5565b90506142bc565b60405163b2a02ff160e01b81526001600160a01b038a169063b2a02ff190614276908f908f908790600401615803565b6020604051808303816000875af1158015614295573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142b99190615399565b90505b80156142f35760405162461bcd60e51b8152602060048201526006602482015265217365697a6560d01b6044820152606401610268565b604080516001600160a01b038e811682528d811660208301528183018790528b1660608201526080810184905290517f298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb529181900360a00190a16000975092955050505050505b94509492505050565b6016546040516370a0823160e01b815260009182916001600160a01b03909116906370a0823190614397903090600401614f78565b602060405180830381865afa1580156143b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143d89190615399565b90506144636323b872dd60e01b8530866040516024016143fa93929190615803565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b038381831617835250505050604051806040016040528060188152602001771513d2d15397d514905394d1915497d25397d1905253115160421b815250613698565b6016546040516370a0823160e01b81526000916001600160a01b0316906370a0823190614494903090600401614f78565b602060405180830381865afa1580156144b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144d59190615399565b9050818110156145245760405162461bcd60e51b815260206004820152601a602482015279544f4b454e5f5452414e534645525f494e5f4f564552464c4f5760301b6044820152606401610268565b6130ee8282615529565b6000816001600160a01b03166389f8132e6040518163ffffffff1660e01b8152600401600060405180830381865afa15801561456e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052614596919081019061584b565b905060006145a2611855565b905060005b82518161ffff1610156110f9576000838261ffff16815181106145cc576145cc61555d565b6020908102919091018101516001600160e01b031981166000908152918590526040909120549091506001600160a01b0386811691161461460f5761460f6158e7565b6001600160e01b0319811660009081526020849052604090205460018085018054600160a01b90930461ffff1692909161464891615529565b815481106146585761465861555d565b90600052602060002090600891828204019190066004029054906101000a900460e01b846001018261ffff16815481106146945761469461555d565b90600052602060002090600891828204019190066004026101000a81548163ffffffff021916908360e01c021790555080846000016000866001018461ffff16815481106146e4576146e461555d565b6000918252602080832060088304015460079092166004026101000a90910460e01b6001600160e01b03191683528201929092526040019020805461ffff60a01b1916600160a01b61ffff939093169290920291909117905560018401805480614750576147506157b1565b60008281526020808220600860001990940193840401805463ffffffff600460078716026101000a0219169055919092556001600160e01b0319909316815291849052506040902080546001600160b01b0319169055806147b0816158fd565b9150506145a7565b6000816001600160a01b03166389f8132e6040518163ffffffff1660e01b8152600401600060405180830381865afa1580156147f8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052614820919081019061584b565b9050600061482c611855565b600181015490915060005b8351811015611a7d5760008482815181106148545761485461555d565b6020908102919091018101516001600160e01b031981166000908152918690526040909120549091506001600160a01b031680156148c057604051632c18df3360e01b81526001600160e01b0319831660048201526001600160a01b0382166024820152604401610268565b6040805180820182526001600160a01b03808a16825261ffff80881660208085019182526001600160e01b0319881660009081528b8252958620945185549251909316600160a01b026001600160b01b0319909216929093169190911717909155600180880180549182018155835291206008820401805460e085901c60046007909416939093026101000a92830263ffffffff909302191691909117905583614969816158fd565b9450505050808061497990615611565b915050614837565b6000806000806149918686614a61565b909250905060008260038111156149aa576149aa6153e7565b146149bb5750915060009050612129565b60006149c682614a49565b9350935050509250929050565b6000806000806149918686614acf565b600061085f8383604051806040016040528060178152602001766d756c7469706c69636174696f6e206f766572666c6f7760481b815250614b34565b614a27614d06565b6040518060200160405280614a408560000151856149e3565b90529392505050565b805160009061106a90670de0b6b3a76400009061570c565b6000614a6b614d06565b600080614a7c8660000151866120ee565b90925090506000826003811115614a9557614a956153e7565b14614ab457506040805160208101909152600081529092509050612129565b60408051602081019091529081526000969095509350505050565b6000614ad9614d06565b600080614aee670de0b6b3a7640000876120ee565b90925090506000826003811115614b0757614b076153e7565b14614b2657506040805160208101909152600081529092509050612129565b6149c6818660000151614b87565b6000831580614b41575082155b15614b4e5750600061085f565b6000614b5a848661591f565b905083614b67868361570c565b1483906113625760405162461bcd60e51b81526004016102689190614f4c565b6000614b91614d06565b600080614ba686670de0b6b3a76400006120ee565b90925090506000826003811115614bbf57614bbf6153e7565b14614bde57506040805160208101909152600081529092509050612129565b600080614beb8388612130565b90925090506000826003811115614c0457614c046153e7565b14614c275781604051806020016040528060008152509550955050505050612129565b604080516020810190915290815260009890975095505050505050565b828054614c50906153b2565b90600052602060002090601f016020900481019282614c725760008555614cb8565b82601f10614c8b57805160ff1916838001178555614cb8565b82800160010185558215614cb8579182015b82811115614cb8578251825591602001919060010190614c9d565b50614cc4929150614d19565b5090565b6040805160e0810190915280600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6040518060200160405280600081525090565b5b80821115614cc45760008155600101614d1a565b6001600160e01b031991909116815260200190565b6001600160a01b038116811461114e57600080fd5b8035614d6381614d43565b919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715614da657614da6614d68565b604052919050565b60006001600160401b03821115614dc757614dc7614d68565b50601f01601f191660200190565b6000614de8614de384614dae565b614d7e565b9050828152838383011115614dfc57600080fd5b828260208301376000602084830101529392505050565b600082601f830112614e2457600080fd5b61085f83833560208501614dd5565b600080600080600080600080610100898b031215614e5057600080fd5b8835614e5b81614d43565b97506020890135614e6b81614d43565b96506040890135614e7b81614d43565b95506060890135614e8b81614d43565b945060808901356001600160401b0380821115614ea757600080fd5b614eb38c838d01614e13565b955060a08b0135915080821115614ec957600080fd5b50614ed68b828c01614e13565b93505060c0890135915060e089013590509295985092959890939650565b60005b83811015614f0f578181015183820152602001614ef7565b838111156110f95750506000910152565b60008151808452614f38816020860160208601614ef4565b601f01601f19169290920160200192915050565b60208152600061085f6020830184614f20565b600060208284031215614f7157600080fd5b5035919050565b6001600160a01b0391909116815260200190565b600060208284031215614f9e57600080fd5b813561085f81614d43565b60ff8116811461114e57600080fd5b8035614d6381614fa9565b60008060008060008060008060006101208a8c031215614fe257600080fd5b8935614fed81614d43565b985060208a0135614ffd81614d43565b975061500b60408b01614d58565b965060608a0135955060808a01356001600160401b038082111561502e57600080fd5b61503a8d838e01614e13565b965060a08c013591508082111561505057600080fd5b5061505d8c828d01614e13565b94505061506c60c08b01614fb8565b925060e08a013591506101008a013590509295985092959850929598565b6000806040838503121561509d57600080fd5b82356150a881614d43565b946020939093013593505050565b801515811461114e57600080fd5b600080600080606085870312156150da57600080fd5b84356150e581614d43565b935060208501356150f5816150b6565b925060408501356001600160401b038082111561511157600080fd5b818701915087601f83011261512557600080fd5b81358181111561513457600080fd5b88602082850101111561514657600080fd5b95989497505060200194505050565b60006020828403121561516757600080fd5b81356001600160401b0381111561517d57600080fd5b8201601f8101841361518e57600080fd5b6127a984823560208401614dd5565b6020808252825182820181905260009190848201906040850190845b818110156151de5783516001600160a01b0316835292840192918401916001016151b9565b50909695505050505050565b600080604083850312156151fd57600080fd5b823561520881614d43565b9150602083013561521881614d43565b809150509250929050565b6000806020838503121561523657600080fd5b82356001600160401b038082111561524d57600080fd5b818501915085601f83011261526157600080fd5b81358181111561527057600080fd5b8660208260051b850101111561528557600080fd5b60209290920196919550909350505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b828110156152ec57603f198886030184526152da858351614f20565b945092850192908501906001016152be565b5092979650505050505050565b60008060006060848603121561530e57600080fd5b833561531981614d43565b9250602084013561532981614d43565b929592945050506040919091013590565b60008060006060848603121561534f57600080fd5b833561535a81614d43565b925060208401359150604084013561537181614d43565b809150509250925092565b60006020828403121561538e57600080fd5b815161085f81614fa9565b6000602082840312156153ab57600080fd5b5051919050565b600181811c908216806153c657607f821691505b60208210811415610adc57634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b60006020828403121561540f57600080fd5b815161085f816150b6565b6000615428614de384614dae565b905082815283838301111561543c57600080fd5b61085f836020830184614ef4565b60008060006060848603121561545f57600080fd5b835161546a81614d43565b602085015190935061547b816150b6565b60408501519092506001600160401b0381111561549757600080fd5b8401601f810186136154a857600080fd5b6154b78682516020840161541a565b9150509250925092565b60208082526006908201526510b0b236b4b760d11b604082015260600190565b6001600160a01b0392831681529116602082015260400190565b634e487b7160e01b600052601160045260246000fd5b60008219821115615524576155246154fb565b500190565b60008282101561553b5761553b6154fb565b500390565b60006020828403121561555257600080fd5b815161085f81614d43565b634e487b7160e01b600052603260045260246000fd5b6000808335601e1984360301811261558a57600080fd5b8301803591506001600160401b038211156155a457600080fd5b60200191503681900382131561212957600080fd5b8183823760009101908152919050565b6000602082840312156155db57600080fd5b81516001600160401b038111156155f157600080fd5b8201601f8101841361560257600080fd5b6127a98482516020840161541a565b6000600019821415615625576156256154fb565b5060010190565b6001600160a01b039384168152919092166020820152901515604082015260600190565b60006001600160401b0382111561566957615669614d68565b5060051b60200190565b6000602080838503121561568657600080fd5b82516001600160401b0381111561569c57600080fd5b8301601f810185136156ad57600080fd5b80516156bb614de382615650565b81815260059190911b820183019083810190878311156156da57600080fd5b928401925b828410156157015783516156f281614d43565b825292840192908401906156df565b979650505050505050565b60008261572957634e487b7160e01b600052601260045260246000fd5b500490565b9283526020830191909152604082015260600190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b039586168152938516602085015291841660408401529092166060820152608081019190915260a00190565b6001600160a01b039390931683526020830191909152604082015260600190565b634e487b7160e01b600052603160045260246000fd5b600060ff821660ff8114156157de576157de6154fb565b60010192915050565b600082516157f9818460208701614ef4565b9190910192915050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6000806040838503121561583a57600080fd5b505080516020909101519092909150565b6000602080838503121561585e57600080fd5b82516001600160401b0381111561587457600080fd5b8301601f8101851361588557600080fd5b8051615893614de382615650565b81815260059190911b820183019083810190878311156158b257600080fd5b928401925b828410156157015783516001600160e01b0319811681146158d85760008081fd5b825292840192908401906158b7565b634e487b7160e01b600052600160045260246000fd5b600061ffff80831681811415615915576159156154fb565b6001019392505050565b6000816000190483118215151615615939576159396154fb565b50029056fe45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa164736f6c634300080a000a
Deployed Bytecode
0x60806040526004361061020d5760003560e01c806306db3ecd1461029557806306fdde03146102b75780630e752702146102e257806315761d5114610310578063173b99041461033d57806317bfdfbc1461035357806318160ddd146103735780631db7894414610389578063219ef65c146103915780632608f818146103b1578063313ce567146103d15780633b1d21a2146103fd57806347bd37181461041257806350d85b731461042857806356e67728146104485780635c60da1b146104685780635fe3b5671461048857806361feacff146104a85780636333d001146104be5780636752e702146104e05780636c540baf146104fb5780636f307dc314610511578063852a12e31461053157806389cd9855146105515780638d02d9a1146105715780638f840ddd1461058757806395d89b411461059d57806395dd9193146105b25780639f5ef272146105d2578063a03dce8d146105e5578063a0712d6814610605578063a7b820df14610625578063aa5af0fd14610645578063ac784ddc1461065b578063ac9650d81461067b578063b2a02ff11461069b578063be99f119146106bb578063c37f68e2146106d7578063c5ebeaec14610717578063cb2ef6f714610737578063db006a751461076e578063dbfe7c191461078e578063dc028ab1146107a4578063f3fdb15a146107ba578063f5e3c462146107da578063fe9c44ae146107fa575b34801561021957600080fd5b5060006102316000356001600160e01b03191661080e565b90506001600160a01b038116610271576000356001600160e01b031916604051630a82dd7360e31b81526004016102689190614d2e565b60405180910390fd5b3660008037600080366000845af43d6000803e808015610290573d6000f35b3d6000fd5b3480156102a157600080fd5b506102b56102b0366004614e33565b610866565b005b3480156102c357600080fd5b506102cc610974565b6040516102d99190614f4c565b60405180910390f35b3480156102ee57600080fd5b506103026102fd366004614f5f565b610a02565b6040519081526020016102d9565b34801561031c57600080fd5b50600154610330906001600160a01b031681565b6040516102d99190614f78565b34801561034957600080fd5b50610302600b5481565b34801561035f57600080fd5b5061030261036e366004614f8c565b610a16565b34801561037f57600080fd5b5061030260125481565b6102b5610ae2565b34801561039d57600080fd5b506102b56103ac366004614fc3565b610c18565b3480156103bd57600080fd5b506103026103cc36600461508a565b611058565b3480156103dd57600080fd5b506005546103eb9060ff1681565b60405160ff90911681526020016102d9565b34801561040957600080fd5b50610302611070565b34801561041e57600080fd5b50610302600e5481565b34801561043457600080fd5b506102b56104433660046150c4565b61107f565b34801561045457600080fd5b506102b5610463366004615155565b6110ff565b34801561047457600080fd5b50600054610330906001600160a01b031681565b34801561049457600080fd5b50600654610330906001600160a01b031681565b3480156104b457600080fd5b5061030260105481565b3480156104ca57600080fd5b506104d3611151565b6040516102d9919061519d565b3480156104ec57600080fd5b50610302666379da05b6000081565b34801561050757600080fd5b50610302600c5481565b34801561051d57600080fd5b50601654610330906001600160a01b031681565b34801561053d57600080fd5b5061030261054c366004614f5f565b61115b565b34801561055d57600080fd5b506102b561056c3660046151ea565b611166565b34801561057d57600080fd5b5061030260095481565b34801561059357600080fd5b50610302600f5481565b3480156105a957600080fd5b506102cc61123a565b3480156105be57600080fd5b506103026105cd366004614f8c565b611247565b3480156105de57600080fd5b5030610330565b3480156105f157600080fd5b50610302610600366004614f5f565b61136b565b34801561061157600080fd5b50610302610620366004614f5f565b61148c565b34801561063157600080fd5b50610302610640366004614f5f565b611498565b34801561065157600080fd5b50610302600d5481565b34801561066757600080fd5b5060005b60405190151581526020016102d9565b61068e610689366004615223565b611609565b6040516102d99190615297565b3480156106a757600080fd5b506103026106b63660046152f9565b611760565b3480156106c757600080fd5b5061030267016345785d8a000081565b3480156106e357600080fd5b506106f76106f2366004614f8c565b611784565b6040805194855260208501939093529183015260608201526080016102d9565b34801561072357600080fd5b50610302610732366004614f5f565b611827565b34801561074357600080fd5b5060408051808201909152600e81526d43457263323044656c656761746560901b60208201526102cc565b34801561077a57600080fd5b50610302610789366004614f5f565b611832565b34801561079a57600080fd5b50610302600a5481565b3480156107b057600080fd5b5061030260115481565b3480156107c657600080fd5b50600754610330906001600160a01b031681565b3480156107e657600080fd5b506103026107f536600461533a565b61183d565b34801561080657600080fd5b50600161066b565b600080610819611855565b6001600160e01b031984166000908152602082905260409020549091506001600160a01b03168061085f5783604051631f3f429960e31b81526004016102689190614d2e565b9392505050565b60006702c68af0bb14000090506000896001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108d7919061537c565b90506108ea898989858a8a878b8b610c18565b601680546001600160a01b0319166001600160a01b038c16908117909155604080516318160ddd60e01b815290516318160ddd916004808201926020929091908290030181865afa158015610943573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109679190615399565b5050505050505050505050565b60038054610981906153b2565b80601f01602080910402602001604051908101604052809291908181526020018280546109ad906153b2565b80156109fa5780601f106109cf576101008083540402835291602001916109fa565b820191906000526020600020905b8154815290600101906020018083116109dd57829003601f168201915b505050505081565b600080610a0e83611879565b509392505050565b600080610a228161193d565b6000306001600160a01b031663a6afed956040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610a64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a889190615399565b14610ac75760405162461bcd60e51b815260206004820152600f60248201526e085858d8dc9d59525b9d195c995cdd608a1b6044820152606401610268565b610ad083611247565b91505b610adc81611a01565b50919050565b333014801590610b645750600660009054906101000a90046001600160a01b03166001600160a01b031663dd5cd22c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b40573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b6491906153fd565b15610c1657600154600080546040516345cc970560e01b81529192839283926001600160a01b03928316926345cc970592610ba59290911690600401614f78565b600060405180830381865afa158015610bc2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610bea919081019061544a565b60005492955090935091506001600160a01b03808516911614610c1257610c12838383611a84565b5050505b565b336001600160a01b03891614610c405760405162461bcd60e51b8152600401610268906154c1565b600c54158015610c505750600d54155b610c8b5760405162461bcd60e51b815260206004820152600c60248201526b085a5b9a5d1a585b1a5e995960a21b6044820152606401610268565b600180546001600160a01b0319166001600160a01b038a16179055600886905585610cea5760405162461bcd60e51b815260206004820152600f60248201526e02165786368616e6765526174653e3608c1b6044820152606401610268565b600680546001600160a01b0319166001600160a01b038b81169190911790915543600c55670de0b6b3a7640000600d55604080516310c8fc9560e11b8152905191891691632191f92a916004808201926020929091908290030181865afa158015610d59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d7d91906153fd565b610db35760405162461bcd60e51b8152602060048201526007602482015266216e6f7449726d60c81b6044820152606401610268565b600780546001600160a01b0319166001600160a01b0389161790556040517fedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f92690610e01906000908a906154e1565b60405180910390a18451610e1c906003906020880190614c44565b508351610e30906004906020870190614c44565b506005805460ff191660ff8516179055600a54600954670de0b6b3a76400009190610e5b9085615511565b610e659190615511565b1115610e9d5760405162461bcd60e51b8152602060048201526007602482015266085c998e9cd95d60ca1b6044820152606401610268565b600b8290556040805160008152602081018490527faaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460910160405180910390a1600019811415610eeb57506009545b6001546040805163dd86fea160e01b815290516000926001600160a01b03169163dd86fea19160048083019260209291908290030181865afa158015610f35573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f599190615399565b9050670de0b6b3a76400008183600b54610f739190615511565b610f7d9190615511565b1115610fbb5760405162461bcd60e51b815260206004820152600d60248201526c0858591b5a5b9199594e9cd95d609a1b6044820152606401610268565b60098290556040805160008152602081018490527fcdd0b588250e1398549f79cfdb8217c186688822905d6715b0834ea1c865594a910160405180910390a1600a8190556040805160008152602081018390527f92eef861b6533b7d3417f39c2ad7b460eed4e88a32fa3604f30e718b7602e7dc910160405180910390a150506002805460ff60b01b1916600160b01b1790555050505050505050565b6000806110658484611d11565b509150505b92915050565b600061107a611dd7565b905090565b611087611e51565b6110a35760405162461bcd60e51b8152600401610268906154c1565b6000546001600160a01b038581169116146110f9576110f9848484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611a8492505050565b50505050565b333014806111105750611110611e51565b61114e5760405162461bcd60e51b815260206004820152600f60248201526e10b9b2b633103e3e1010b0b236b4b760891b6044820152606401610268565b50565b606061107a611fbc565b600061106a82612027565b6006546001546001600160a01b039182169116331480156111e45750806001600160a01b0316632f1069ba6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e491906153fd565b6112305760405162461bcd60e51b815260206004820152601f60248201527f21756e617574686f72697a6564202d206e6f2061646d696e20726967687473006044820152606401610268565b610c1283836120c9565b60048054610981906153b2565b6001600160a01b03811660009081526015602052604081208054829182918291906112785750600095945050505050565b6112888160000154600d546120ee565b909450925060008460038111156112a1576112a16153e7565b146112ee5760405162461bcd60e51b815260206004820152601e60248201527f216d756c55496e74206f766572666c6f7720636865636b206661696c656400006044820152606401610268565b6112fc838260010154612130565b90945091506000846003811115611315576113156153e7565b146113625760405162461bcd60e51b815260206004820152601e60248201527f2164697655496e74206f766572666c6f7720636865636b206661696c656400006044820152606401610268565b50949350505050565b6000806113778161193d565b6000306001600160a01b031663a6afed956040518163ffffffff1660e01b81526004016020604051808303816000875af11580156113b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113dd9190615399565b90508015611409576114018160118111156113fa576113fa6153e7565b603361215b565b925050610ad3565b43600c541461141e57611401600a603561215b565b83611427611dd7565b101561143957611401600e603461215b565b60115484111561144f576114016002603661215b565b60008460115461145f9190615529565b601181905560015490915061147d906001600160a01b0316866121bb565b600093505050610adc81611a01565b600080610a0e83612243565b6000806114a48161193d565b6000306001600160a01b031663a6afed956040518163ffffffff1660e01b81526004016020604051808303816000875af11580156114e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061150a9190615399565b9050801561152e57611401816011811115611527576115276153e7565b603761215b565b43600c541461154357611401600a603961215b565b8361154c611dd7565b101561155e57611401600e603861215b565b601054841115611574576114016002603a61215b565b836010546115829190615529565b601055600654604080516303e1469160e61b815290516115fa926001600160a01b03169163f851a4409160048083019260209291908290030181865afa1580156115d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115f49190615540565b856121bb565b60005b925050610adc81611a01565b6060816001600160401b0381111561162357611623614d68565b60405190808252806020026020018201604052801561165657816020015b60608152602001906001900390816116415790505b50905060005b82811015611759576000803086868581811061167a5761167a61555d565b905060200281019061168c9190615573565b60405161169a9291906155b9565b600060405180830381855af49150503d80600081146116d5576040519150601f19603f3d011682016040523d82523d6000602084013e6116da565b606091505b509150915081611726576044815110156116f357600080fd5b6004810190508080602001905181019061170d91906155c9565b60405162461bcd60e51b81526004016102689190614f4c565b808484815181106117395761173961555d565b60200260200101819052505050808061175190615611565b91505061165c565b5092915050565b6000600161176d8161193d565b611779338686866122e5565b9150610a0e81611a01565b6001600160a01b0381166000908152601360205260408120548190819081908180806117af89611247565b9250306001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa1580156117ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118139190615399565b915060009993985091965094509092505050565b600061106a826127b1565b600061106a82612851565b60008061184b8585856128ec565b5095945050505050565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c90565b60008060006118878161193d565b6000306001600160a01b031663a6afed956040518163ffffffff1660e01b81526004016020604051808303816000875af11580156118c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ed9190615399565b9050801561191d5761191181601181111561190a5761190a6153e7565b604161215b565b6000935093505061192e565b611928333387612a9d565b93509350505b61193781611a01565b50915091565b600254600160b01b900460ff166119835760405162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b6044820152606401610268565b806119f157600660009054906101000a90046001600160a01b03166001600160a01b031663c90c20b16040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156119d857600080fd5b505af11580156119ec573d6000803e3d6000fd5b505050505b506002805460ff60b01b19169055565b6002805460ff60b01b1916600160b01b1790558061114e57600660009054906101000a90046001600160a01b03166001600160a01b031663632e51426040518163ffffffff1660e01b8152600401600060405180830381600087803b158015611a6957600080fd5b505af1158015611a7d573d6000803e3d6000fd5b5050505050565b6001546000546040516338e6a07360e11b81526001600160a01b03928316926371cd40e692611abc929116908790879060040161562c565b602060405180830381865afa158015611ad9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611afd91906153fd565b611b315760405162461bcd60e51b8152602060048201526005602482015264085a5b5c1b60da1b6044820152606401610268565b600080546001600160a01b038581166001600160a01b03198316811784556001546040516311a0e21760e01b815293831694939216916311a0e21791611b7991600401614f78565b600060405180830381865afa158015611b96573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611bbe9190810190615673565b90506000611bca611fbc565b905060005b8151811015611c0c57611bfa828281518110611bed57611bed61555d565b6020026020010151612e3f565b80611c0481615611565b915050611bcf565b5060005b8251811015611c4d57611c3b838281518110611c2e57611c2e61555d565b6020026020010151612f6c565b80611c4581615611565b915050611c10565b50303b611c6257611c5d846110ff565b611cc4565b611cc23085604051602401611c779190614f4c565b60408051601f19818403018152918152602080830180516001600160e01b0316630adccee560e31b17905281518083019092526007825266216265636f6d6560c81b9082015261305b565b505b6000546040517fd604de94d45953f9138079ec1b82d533cb2160c906d1076d1f7ed54befbca97a91611d019186916001600160a01b0316906154e1565b60405180910390a1505050505050565b6000806000611d1f8161193d565b6000306001600160a01b031663a6afed956040518163ffffffff1660e01b81526004016020604051808303816000875af1158015611d61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d859190615399565b90508015611db557611da9816011811115611da257611da26153e7565b604061215b565b60009350935050611dc6565b611dc0338787612a9d565b93509350505b611dcf81611a01565b509250929050565b6016546040516370a0823160e01b81526000916001600160a01b03169081906370a0823190611e0a903090600401614f78565b602060405180830381865afa158015611e27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e4b9190615399565b91505090565b600654604080516303e1469160e61b815290516000926001600160a01b031691829163f851a440916004808201926020929091908290030181865afa158015611e9e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec29190615540565b6001600160a01b0316336001600160a01b0316148015611f3f5750806001600160a01b0316630a755ec26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f3f91906153fd565b80611e4b57506001546001600160a01b031633148015611e4b5750806001600160a01b0316632f1069ba6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f98573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e4b91906153fd565b6060611fc6611855565b60020180548060200260200160405190810160405280929190818152602001828054801561201d57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611fff575b5050505050905090565b6000806120338161193d565b6000306001600160a01b031663a6afed956040518163ffffffff1660e01b81526004016020604051808303816000875af1158015612075573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120999190615399565b905080156120bd576114018160118111156120b6576120b66153e7565b602a61215b565b6115fd336000866130f7565b6001600160a01b038116156120e1576120e181612e3f565b6120ea82612f6c565b5050565b6000808361210157506000905080612129565b8383028361210f868361570c565b1461212257600260009250925050612129565b6000925090505b9250929050565b600080826121445750600190506000612129565b6000612150848661570c565b915091509250929050565b600060008051602061593f83398151915283601181111561217e5761217e6153e7565b836061811115612190576121906153e7565b60006040516121a19392919061572e565b60405180910390a182601181111561085f5761085f6153e7565b6120ea63a9059cbb60e01b83836040516024016121d9929190615744565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b038381831617835250505050604051806040016040528060198152602001781513d2d15397d514905394d1915497d3d55517d19052531151603a1b815250613698565b60008060006122518161193d565b6000306001600160a01b031663a6afed956040518163ffffffff1660e01b81526004016020604051808303816000875af1158015612293573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122b79190615399565b905080156122db576119118160118111156122d4576122d46153e7565b602061215b565b61192833866136ef565b60065460405163d02f735160e01b815260009182916001600160a01b039091169063d02f7351906123229030908a908a908a908a9060040161575d565b6020604051808303816000875af1158015612341573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123659190615399565b905080156123825761237a6003601d83613a24565b9150506127a9565b846001600160a01b0316846001600160a01b031614156123a85761237a6006601e61215b565b61240d604080516101808101909152806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6001600160a01b0385166000908152601360205260409020546124309085613aad565b602083018190528282600381111561244a5761244a6153e7565b600381111561245b5761245b6153e7565b9052506000905081516003811115612475576124756153e7565b146124a55761249c6009601c83600001516003811115612497576124976153e7565b613a24565b925050506127a9565b6124c4846040518060200160405280666379da05b60000815250613ad8565b6080820152604080516020810190915267016345785d8a000081526124ea908590613ad8565b610140820181905260808201516125019086615529565b61250b9190615529565b6060820152306001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa15801561254e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125729190615399565b60c0820190815260408051602081019091529051815260808201516125979190613afb565b60a0820152604080516020810190915260c082015181526101408201516125be9190613afb565b61016082015260a0810151600f546125d69190615511565b60e082015261014081015160808201516012546125f39190615529565b6125fd9190615529565b6101208201526101608101516011546126169190615511565b6101008201526001600160a01b03861660009081526013602052604090205460608201516126449190613b13565b604083018190528282600381111561265e5761265e6153e7565b600381111561266f5761266f6153e7565b9052506000905081516003811115612689576126896153e7565b146126ab5761249c6009601b83600001516003811115612497576124976153e7565b60e0810151600f556101208101516012556101008101516011556020808201516001600160a01b0387811660008181526013855260408082209490945583860151928b168082529084902092909255606085015192519283529092909160008051602061595f833981519152910160405180910390a3306001600160a01b0316856001600160a01b031660008051602061595f833981519152836080015160405161275891815260200190565b60405180910390a360a081015160e08201516040517fa91e67c5ea634cd43a12c5a482724b03de01e85ca68702a53d0c2f45cb7c1dc59261279a923092615790565b60405180910390a16000925050505b949350505050565b6000806127bd8161193d565b6000306001600160a01b031663a6afed956040518163ffffffff1660e01b81526004016020604051808303816000875af11580156127ff573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128239190615399565b9050801561284757611401816011811115612840576128406153e7565b600a61215b565b6115fd3385613b39565b60008061285d8161193d565b6000306001600160a01b031663a6afed956040518163ffffffff1660e01b81526004016020604051808303816000875af115801561289f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128c39190615399565b905080156128e0576114018160118111156120b6576120b66153e7565b6115fd338560006130f7565b60008060006128fa8161193d565b6000306001600160a01b031663a6afed956040518163ffffffff1660e01b81526004016020604051808303816000875af115801561293c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129609190615399565b905080156129905761298481601181111561297d5761297d6153e7565b601161215b565b60009350935050612a8b565b846001600160a01b0316639f5ef2726040518163ffffffff1660e01b8152600401602060405180830381865afa1580156129ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129f29190615540565b6001600160a01b031663a6afed956040518163ffffffff1660e01b81526004016020604051808303816000875af1158015612a31573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a559190615399565b90508015612a7957612984816011811115612a7257612a726153e7565b601261215b565b612a8533888888613e66565b93509350505b612a9481611a01565b50935093915050565b600654604051631200453160e11b81523060048201526001600160a01b03858116602483015284811660448301526064820184905260009283928392909116906324008a62906084016020604051808303816000875af1158015612b05573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b299190615399565b90508015612b4a57612b3e6003604383613a24565b60009250925050612e37565b43600c5414612b5f57612b3e600a604461215b565b612ba86040805161010081019091528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6001600160a01b0386166000908152601560205260409020600101546060820152612bd286611247565b6080820152600019851415612bf05760808101516040820152612bf8565b604081018590525b612c06878260400151614362565b60e082018190526080820151612c1b91613aad565b60a0830181905260208301826003811115612c3857612c386153e7565b6003811115612c4957612c496153e7565b9052506000905081602001516003811115612c6657612c666153e7565b14612cd65760405162461bcd60e51b815260206004820152603a60248201527f52455041595f424f52524f575f4e45575f4143434f554e545f424f52524f575f604482015279109053105390d157d0d05310d55310551253d397d1905253115160321b6064820152608401610268565b612ce6600e548260e00151613aad565b60c0830181905260208301826003811115612d0357612d036153e7565b6003811115612d1457612d146153e7565b9052506000905081602001516003811115612d3157612d316153e7565b14612d985760405162461bcd60e51b815260206004820152603160248201527f52455041595f424f52524f575f4e45575f544f54414c5f42414c414e43455f43604482015270105310d55310551253d397d19052531151607a1b6064820152608401610268565b60a081810180516001600160a01b03898116600081815260156020908152604091829020948555600d5460019095019490945560c0870151600e81905560e088015195518251948f16855294840192909252820193909352606081019190915260808101919091527f1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a1910160405180910390a160e00151600093509150505b935093915050565b6000612e49611855565b9050612e548261452e565b60005b600282015460ff82161015610c1257826001600160a01b0316826002018260ff1681548110612e8857612e8861555d565b6000918252602090912001546001600160a01b03161415612f5a57600282018054612eb590600190615529565b81548110612ec557612ec561555d565b6000918252602090912001546002830180546001600160a01b039092169160ff8416908110612ef657612ef661555d565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555081600201805480612f3757612f376157b1565b600082815260209020810160001990810180546001600160a01b03191690550190555b80612f64816157c7565b915050612e57565b6000612f76611855565b905060005b600282015460ff8216101561301b57826001600160a01b0316826002018260ff1681548110612fac57612fac61555d565b6000918252602090912001546001600160a01b031614156130095760405162461bcd60e51b8152602060048201526017602482015276195e1d195b9cda5bdb88185b1c9958591e481859191959604a1b6044820152606401610268565b80613013816157c7565b915050612f7b565b50613025826147b8565b6002018054600181018255600091825260209091200180546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080856001600160a01b03168560405161307891906157e7565b6000604051808303816000865af19150503d80600081146130b5576040519150601f19603f3d011682016040523d82523d6000602084013e6130ba565b606091505b5091509150816130ee578051156130d45780518082602001fd5b8360405162461bcd60e51b81526004016102689190614f4c565b95945050505050565b6000821580613104575081155b61314a5760405162461bcd60e51b815260206004820152601760248201527602172656465656d546f6b656e73496e6f724f7574213d3604c1b6044820152606401610268565b613152614cc8565b306001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015613190573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131b49190615399565b604082015260001983141561323e57600654604051630cbb414760e11b81526001600160a01b0390911690631976828e906131f8908890309060009060040161562c565b6020604051808303816000875af1158015613217573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061323b9190615399565b92505b83156132df5760608101849052604080516020810182529082015181526132659085614981565b6080830181905260208301826003811115613282576132826153e7565b6003811115613293576132936153e7565b90525060009050816020015160038111156132b0576132b06153e7565b146132da576132d26009602c83602001516003811115612497576124976153e7565b91505061085f565b613370565b6132fb83604051806020016040528084604001518152506149d3565b6060830181905260208301826003811115613318576133186153e7565b6003811115613329576133296153e7565b9052506000905081602001516003811115613346576133466153e7565b14613368576132d26009602d83602001516003811115612497576124976153e7565b608081018390525b600654606082015160405163eabe7d9160e01b81526000926001600160a01b03169163eabe7d91916133a99130918b9190600401615803565b6020604051808303816000875af11580156133c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133ec9190615399565b9050801561340a576134016003602b83613a24565b9250505061085f565b43600c541461341f57613401600a602f61215b565b61342f6012548360600151613aad565b60a084018190526020840182600381111561344c5761344c6153e7565b600381111561345d5761345d6153e7565b905250600090508260200151600381111561347a5761347a6153e7565b1461349c576134016009603184602001516003811115612497576124976153e7565b6001600160a01b03861660009081526013602052604090205460608301516134c49190613aad565b60c08401819052602084018260038111156134e1576134e16153e7565b60038111156134f2576134f26153e7565b905250600090508260200151600381111561350f5761350f6153e7565b14613531576134016009603084602001516003811115612497576124976153e7565b816080015161353e611dd7565b101561355057613401600e603261215b565b60a082015160125560c08201516001600160a01b03871660009081526013602052604090205560808201516135869087906121bb565b306001600160a01b0316866001600160a01b031660008051602061595f83398151915284606001516040516135bd91815260200190565b60405180910390a3608082015160608301516040517fe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a929926135ff928a92615790565b60405180910390a1600654608083015160608401516040516351dff98960e01b81523060048201526001600160a01b038a81166024830152604482019390935260648101919091529116906351dff98990608401600060405180830381600087803b15801561366d57600080fd5b505af1158015613681573d6000803e3d6000fd5b506000925061368e915050565b9695505050505050565b6016546000906136b2906001600160a01b0316848461305b565b805190915015610c1257808060200190518101906136d091906153fd565b82906110f95760405162461bcd60e51b81526004016102689190614f4c565b600654604051634ef4c3e160e01b8152600091829182916001600160a01b031690634ef4c3e19061372890309089908990600401615803565b6020604051808303816000875af1158015613747573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061376b9190615399565b9050801561378c576137806003602183613a24565b60009250925050612129565b43600c54146137a157613780600a602461215b565b6137a9614cc8565b306001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa1580156137e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061380b9190615399565b604082015261381a8686614362565b60c082018190526040805160208101825290830151815261383b91906149d3565b6060830181905260208301826003811115613858576138586153e7565b6003811115613869576138696153e7565b9052506000905081602001516003811115613886576138866153e7565b146138d35760405162461bcd60e51b815260206004820181905260248201527f4d494e545f45584348414e47455f43414c43554c4154494f4e5f4641494c45446044820152606401610268565b60008160600151116139245760405162461bcd60e51b815260206004820152601a6024820152791352539517d6915493d7d0d513d2d15394d7d491529150d5115160321b6044820152606401610268565b80606001516012546139369190615511565b608082015260608101516001600160a01b0387166000908152601360205260409020546139639190615511565b60a0820181905260808201516012556001600160a01b038716600090815260136020526040908190209190915560c0820151606083015191517f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f926139cc928a92909190615790565b60405180910390a1856001600160a01b0316306001600160a01b031660008051602061595f8339815191528360600151604051613a0b91815260200190565b60405180910390a360c001516000969095509350505050565b600060008051602061593f833981519152846011811115613a4757613a476153e7565b846061811115613a5957613a596153e7565b84604051613a699392919061572e565b60405180910390a16003846011811115613a8557613a856153e7565b14613aa157836011811115613a9c57613a9c6153e7565b6127a9565b6127a9826103e8615511565b600080838311613acc576000613ac38486615529565b91509150612129565b50600390506000612129565b6000670de0b6b3a7640000613af18484600001516149e3565b61085f919061570c565b600080613b088484614a1f565b90506127a981614a49565b600080838301848110613b2b57600092509050612129565b600260009250925050612129565b60065460405163368f515360e21b815260009182916001600160a01b039091169063da3d454c90613b7290309088908890600401615803565b6020604051808303816000875af1158015613b91573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613bb59190615399565b90508015613bd257613bca6003601083613a24565b91505061106a565b43600c5414613be757613bca600a600c61215b565b6000613bf1611dd7565b905083811015613c1057613c07600e600b61215b565b9250505061106a565b613c3c604080516080810190915280600081526020016000815260200160008152602001600081525090565b613c4586611247565b60208201819052613c569086613b13565b6040830181905282826003811115613c7057613c706153e7565b6003811115613c8157613c816153e7565b9052506000905081516003811115613c9b57613c9b6153e7565b14613cc757613cbd6009600e83600001516003811115612497576124976153e7565b935050505061106a565b6006546040808301519051631de6c8a560e21b81526001600160a01b039092169163779b229491613cfd91309190600401615744565b602060405180830381865afa158015613d1a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d3e9190615399565b92508215613d5357613cbd6003601085613a24565b613d5f600e5486613b13565b6060830181905282826003811115613d7957613d796153e7565b6003811115613d8a57613d8a6153e7565b9052506000905081516003811115613da457613da46153e7565b14613dc657613cbd6009600d83600001516003811115612497576124976153e7565b6040808201516001600160a01b0388166000908152601560205291909120908155600d546001909101556060810151600e55613e0286866121bb565b60408082015160608084015183516001600160a01b038b168152602081018a9052938401929092528201527f13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab809060800160405180910390a160009695505050505050565b600654604051632fe3f38f60e11b8152600091829182916001600160a01b031690635fc7e71e90613ea390309088908c908c908c9060040161575d565b6020604051808303816000875af1158015613ec2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ee69190615399565b90508015613f0757613efb6003601483613a24565b60009250925050614359565b43600c5414613f1c57613efb600a601861215b565b43846001600160a01b0316636c540baf6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613f5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f7f9190615399565b14613f9057613efb600a601361215b565b866001600160a01b0316866001600160a01b03161415613fb657613efb6006601961215b565b84613fc757613efb6007601761215b565b600019851415613fdd57613efb6007601661215b565b600080613feb898989612a9d565b909250905081156140205761401282601181111561400b5761400b6153e7565b601a61215b565b600094509450505050614359565b60065460405163c488847b60e01b815260009182916001600160a01b039091169063c488847b906140599030908c908890600401615803565b6040805180830381865afa158015614075573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140999190615827565b909250905081156141085760405162461bcd60e51b815260206004820152603360248201527f4c49515549444154455f434f4d5054524f4c4c45525f43414c43554c4154455f604482015272105353d5539517d4d152569157d19052531151606a1b6064820152608401610268565b80886001600160a01b0316639f5ef2726040518163ffffffff1660e01b8152600401602060405180830381865afa158015614147573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061416b9190615540565b6001600160a01b03166370a082318c6040518263ffffffff1660e01b81526004016141969190614f78565b602060405180830381865afa1580156141b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141d79190615399565b10156142205760405162461bcd60e51b815260206004820152601860248201527709892a2aa928882a88abea68a92b48abea89e9ebe9aaa86960431b6044820152606401610268565b60006001600160a01b0389163014156142465761423f308d8d856122e5565b90506142bc565b60405163b2a02ff160e01b81526001600160a01b038a169063b2a02ff190614276908f908f908790600401615803565b6020604051808303816000875af1158015614295573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142b99190615399565b90505b80156142f35760405162461bcd60e51b8152602060048201526006602482015265217365697a6560d01b6044820152606401610268565b604080516001600160a01b038e811682528d811660208301528183018790528b1660608201526080810184905290517f298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb529181900360a00190a16000975092955050505050505b94509492505050565b6016546040516370a0823160e01b815260009182916001600160a01b03909116906370a0823190614397903090600401614f78565b602060405180830381865afa1580156143b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143d89190615399565b90506144636323b872dd60e01b8530866040516024016143fa93929190615803565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b038381831617835250505050604051806040016040528060188152602001771513d2d15397d514905394d1915497d25397d1905253115160421b815250613698565b6016546040516370a0823160e01b81526000916001600160a01b0316906370a0823190614494903090600401614f78565b602060405180830381865afa1580156144b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144d59190615399565b9050818110156145245760405162461bcd60e51b815260206004820152601a602482015279544f4b454e5f5452414e534645525f494e5f4f564552464c4f5760301b6044820152606401610268565b6130ee8282615529565b6000816001600160a01b03166389f8132e6040518163ffffffff1660e01b8152600401600060405180830381865afa15801561456e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052614596919081019061584b565b905060006145a2611855565b905060005b82518161ffff1610156110f9576000838261ffff16815181106145cc576145cc61555d565b6020908102919091018101516001600160e01b031981166000908152918590526040909120549091506001600160a01b0386811691161461460f5761460f6158e7565b6001600160e01b0319811660009081526020849052604090205460018085018054600160a01b90930461ffff1692909161464891615529565b815481106146585761465861555d565b90600052602060002090600891828204019190066004029054906101000a900460e01b846001018261ffff16815481106146945761469461555d565b90600052602060002090600891828204019190066004026101000a81548163ffffffff021916908360e01c021790555080846000016000866001018461ffff16815481106146e4576146e461555d565b6000918252602080832060088304015460079092166004026101000a90910460e01b6001600160e01b03191683528201929092526040019020805461ffff60a01b1916600160a01b61ffff939093169290920291909117905560018401805480614750576147506157b1565b60008281526020808220600860001990940193840401805463ffffffff600460078716026101000a0219169055919092556001600160e01b0319909316815291849052506040902080546001600160b01b0319169055806147b0816158fd565b9150506145a7565b6000816001600160a01b03166389f8132e6040518163ffffffff1660e01b8152600401600060405180830381865afa1580156147f8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052614820919081019061584b565b9050600061482c611855565b600181015490915060005b8351811015611a7d5760008482815181106148545761485461555d565b6020908102919091018101516001600160e01b031981166000908152918690526040909120549091506001600160a01b031680156148c057604051632c18df3360e01b81526001600160e01b0319831660048201526001600160a01b0382166024820152604401610268565b6040805180820182526001600160a01b03808a16825261ffff80881660208085019182526001600160e01b0319881660009081528b8252958620945185549251909316600160a01b026001600160b01b0319909216929093169190911717909155600180880180549182018155835291206008820401805460e085901c60046007909416939093026101000a92830263ffffffff909302191691909117905583614969816158fd565b9450505050808061497990615611565b915050614837565b6000806000806149918686614a61565b909250905060008260038111156149aa576149aa6153e7565b146149bb5750915060009050612129565b60006149c682614a49565b9350935050509250929050565b6000806000806149918686614acf565b600061085f8383604051806040016040528060178152602001766d756c7469706c69636174696f6e206f766572666c6f7760481b815250614b34565b614a27614d06565b6040518060200160405280614a408560000151856149e3565b90529392505050565b805160009061106a90670de0b6b3a76400009061570c565b6000614a6b614d06565b600080614a7c8660000151866120ee565b90925090506000826003811115614a9557614a956153e7565b14614ab457506040805160208101909152600081529092509050612129565b60408051602081019091529081526000969095509350505050565b6000614ad9614d06565b600080614aee670de0b6b3a7640000876120ee565b90925090506000826003811115614b0757614b076153e7565b14614b2657506040805160208101909152600081529092509050612129565b6149c6818660000151614b87565b6000831580614b41575082155b15614b4e5750600061085f565b6000614b5a848661591f565b905083614b67868361570c565b1483906113625760405162461bcd60e51b81526004016102689190614f4c565b6000614b91614d06565b600080614ba686670de0b6b3a76400006120ee565b90925090506000826003811115614bbf57614bbf6153e7565b14614bde57506040805160208101909152600081529092509050612129565b600080614beb8388612130565b90925090506000826003811115614c0457614c046153e7565b14614c275781604051806020016040528060008152509550955050505050612129565b604080516020810190915290815260009890975095505050505050565b828054614c50906153b2565b90600052602060002090601f016020900481019282614c725760008555614cb8565b82601f10614c8b57805160ff1916838001178555614cb8565b82800160010185558215614cb8579182015b82811115614cb8578251825591602001919060010190614c9d565b50614cc4929150614d19565b5090565b6040805160e0810190915280600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6040518060200160405280600081525090565b5b80821115614cc45760008155600101614d1a565b6001600160e01b031991909116815260200190565b6001600160a01b038116811461114e57600080fd5b8035614d6381614d43565b919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715614da657614da6614d68565b604052919050565b60006001600160401b03821115614dc757614dc7614d68565b50601f01601f191660200190565b6000614de8614de384614dae565b614d7e565b9050828152838383011115614dfc57600080fd5b828260208301376000602084830101529392505050565b600082601f830112614e2457600080fd5b61085f83833560208501614dd5565b600080600080600080600080610100898b031215614e5057600080fd5b8835614e5b81614d43565b97506020890135614e6b81614d43565b96506040890135614e7b81614d43565b95506060890135614e8b81614d43565b945060808901356001600160401b0380821115614ea757600080fd5b614eb38c838d01614e13565b955060a08b0135915080821115614ec957600080fd5b50614ed68b828c01614e13565b93505060c0890135915060e089013590509295985092959890939650565b60005b83811015614f0f578181015183820152602001614ef7565b838111156110f95750506000910152565b60008151808452614f38816020860160208601614ef4565b601f01601f19169290920160200192915050565b60208152600061085f6020830184614f20565b600060208284031215614f7157600080fd5b5035919050565b6001600160a01b0391909116815260200190565b600060208284031215614f9e57600080fd5b813561085f81614d43565b60ff8116811461114e57600080fd5b8035614d6381614fa9565b60008060008060008060008060006101208a8c031215614fe257600080fd5b8935614fed81614d43565b985060208a0135614ffd81614d43565b975061500b60408b01614d58565b965060608a0135955060808a01356001600160401b038082111561502e57600080fd5b61503a8d838e01614e13565b965060a08c013591508082111561505057600080fd5b5061505d8c828d01614e13565b94505061506c60c08b01614fb8565b925060e08a013591506101008a013590509295985092959850929598565b6000806040838503121561509d57600080fd5b82356150a881614d43565b946020939093013593505050565b801515811461114e57600080fd5b600080600080606085870312156150da57600080fd5b84356150e581614d43565b935060208501356150f5816150b6565b925060408501356001600160401b038082111561511157600080fd5b818701915087601f83011261512557600080fd5b81358181111561513457600080fd5b88602082850101111561514657600080fd5b95989497505060200194505050565b60006020828403121561516757600080fd5b81356001600160401b0381111561517d57600080fd5b8201601f8101841361518e57600080fd5b6127a984823560208401614dd5565b6020808252825182820181905260009190848201906040850190845b818110156151de5783516001600160a01b0316835292840192918401916001016151b9565b50909695505050505050565b600080604083850312156151fd57600080fd5b823561520881614d43565b9150602083013561521881614d43565b809150509250929050565b6000806020838503121561523657600080fd5b82356001600160401b038082111561524d57600080fd5b818501915085601f83011261526157600080fd5b81358181111561527057600080fd5b8660208260051b850101111561528557600080fd5b60209290920196919550909350505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b828110156152ec57603f198886030184526152da858351614f20565b945092850192908501906001016152be565b5092979650505050505050565b60008060006060848603121561530e57600080fd5b833561531981614d43565b9250602084013561532981614d43565b929592945050506040919091013590565b60008060006060848603121561534f57600080fd5b833561535a81614d43565b925060208401359150604084013561537181614d43565b809150509250925092565b60006020828403121561538e57600080fd5b815161085f81614fa9565b6000602082840312156153ab57600080fd5b5051919050565b600181811c908216806153c657607f821691505b60208210811415610adc57634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b60006020828403121561540f57600080fd5b815161085f816150b6565b6000615428614de384614dae565b905082815283838301111561543c57600080fd5b61085f836020830184614ef4565b60008060006060848603121561545f57600080fd5b835161546a81614d43565b602085015190935061547b816150b6565b60408501519092506001600160401b0381111561549757600080fd5b8401601f810186136154a857600080fd5b6154b78682516020840161541a565b9150509250925092565b60208082526006908201526510b0b236b4b760d11b604082015260600190565b6001600160a01b0392831681529116602082015260400190565b634e487b7160e01b600052601160045260246000fd5b60008219821115615524576155246154fb565b500190565b60008282101561553b5761553b6154fb565b500390565b60006020828403121561555257600080fd5b815161085f81614d43565b634e487b7160e01b600052603260045260246000fd5b6000808335601e1984360301811261558a57600080fd5b8301803591506001600160401b038211156155a457600080fd5b60200191503681900382131561212957600080fd5b8183823760009101908152919050565b6000602082840312156155db57600080fd5b81516001600160401b038111156155f157600080fd5b8201601f8101841361560257600080fd5b6127a98482516020840161541a565b6000600019821415615625576156256154fb565b5060010190565b6001600160a01b039384168152919092166020820152901515604082015260600190565b60006001600160401b0382111561566957615669614d68565b5060051b60200190565b6000602080838503121561568657600080fd5b82516001600160401b0381111561569c57600080fd5b8301601f810185136156ad57600080fd5b80516156bb614de382615650565b81815260059190911b820183019083810190878311156156da57600080fd5b928401925b828410156157015783516156f281614d43565b825292840192908401906156df565b979650505050505050565b60008261572957634e487b7160e01b600052601260045260246000fd5b500490565b9283526020830191909152604082015260600190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b039586168152938516602085015291841660408401529092166060820152608081019190915260a00190565b6001600160a01b039390931683526020830191909152604082015260600190565b634e487b7160e01b600052603160045260246000fd5b600060ff821660ff8114156157de576157de6154fb565b60010192915050565b600082516157f9818460208701614ef4565b9190910192915050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6000806040838503121561583a57600080fd5b505080516020909101519092909150565b6000602080838503121561585e57600080fd5b82516001600160401b0381111561587457600080fd5b8301601f8101851361588557600080fd5b8051615893614de382615650565b81815260059190911b820183019083810190878311156158b257600080fd5b928401925b828410156157015783516001600160e01b0319811681146158d85760008081fd5b825292840192908401906158b7565b634e487b7160e01b600052600160045260246000fd5b600061ffff80831681811415615915576159156154fb565b6001019392505050565b6000816000190483118215151615615939576159396154fb565b50029056fe45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa164736f6c634300080a000a
Deployed Bytecode Sourcemap
269:4177:2:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1275:17:16;1295:43;1330:7;;-1:-1:-1;;;;;;1330:7:16;1295:34;:43::i;:::-;1275:63;-1:-1:-1;;;;;;1348:23:16;;1344:61;;1397:7;;-1:-1:-1;;;;;;1397:7:16;1380:25;;-1:-1:-1;;;1380:25:16;;;;;;;;:::i;:::-;;;;;;;;1344:61;1586:14;1583:1;1580;1567:34;1726:1;1723;1707:14;1704:1;1693:9;1686:5;1673:55;1786:16;1783:1;1780;1765:38;1878:6;1891:52;;;;1978:16;1975:1;1968:27;1891:52;1918:16;1915:1;1908:27;874:804:1;;;;;;;;;;-1:-1:-1;874:804:1;;;;;:::i;:::-;;:::i;:::-;;848:18:4;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3658:155:1;;;;;;;;;;-1:-1:-1;3658:155:1;;;;;:::i;:::-;;:::i;:::-;;;4070:25:19;;;4058:2;4043:18;3658:155:1;3924:177:19;265:32:4;;;;;;;;;;-1:-1:-1;265:32:4;;;;-1:-1:-1;;;;;265:32:4;;;;;;;;;;:::i;2169:36::-;;;;;;;;;;;;;;;;5233:255:3;;;;;;;;;;-1:-1:-1;5233:255:3;;;;;:::i;:::-;;:::i;3010:26:4:-;;;;;;;;;;;;;;;;3826:501:2;;;:::i;1891:2225:3:-;;;;;;;;;;-1:-1:-1;1891:2225:3;;;;;:::i;:::-;;:::i;4079:195:1:-;;;;;;;;;;-1:-1:-1;4079:195:1;;;;;:::i;:::-;;:::i;1018:21:4:-;;;;;;;;;;-1:-1:-1;1018:21:4;;;;;;;;;;;6577:4:19;6565:17;;;6547:36;;6535:2;6520:18;1018:21:4;6405:184:19;6927:92:3;;;;;;;;;;;;;:::i;2548:27:4:-;;;;;;;;;;;;;;;;3267:390:2;;;;;;;;;;-1:-1:-1;3267:390:2;;;;;:::i;:::-;;:::i;479:160::-;;;;;;;;;;-1:-1:-1;479:160:2;;;;;:::i;:::-;;:::i;163:29:0:-;;;;;;;;;;-1:-1:-1;163:29:0;;;;-1:-1:-1;;;;;163:29:0;;;1532:39:4;;;;;;;;;;-1:-1:-1;1532:39:4;;;;-1:-1:-1;;;;;1532:39:4;;;2791:29;;;;;;;;;;;;;;;;1134:111:16;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;3875:59:4:-;;;;;;;;;;;;3928:6;3875:59;;2282:33;;;;;;;;;;;;;;;;9334:25;;;;;;;;;;-1:-1:-1;9334:25:4;;;;-1:-1:-1;;;;;9334:25:4;;;2964:140:1;;;;;;;;;;-1:-1:-1;2964:140:1;;;;;:::i;:::-;;:::i;42641:424:3:-;;;;;;;;;;-1:-1:-1;42641:424:3;;;;;:::i;:::-;;:::i;1939:31:4:-;;;;;;;;;;;;;;;;2668:28;;;;;;;;;;;;;;;;931:20;;;;;;;;;;;;;:::i;5678:1095:3:-;;;;;;;;;;-1:-1:-1;5678:1095:3;;;;;:::i;:::-;;:::i;6820:142:4:-;;;;;;;;;;-1:-1:-1;6951:4:4;6820:142;;39723:1273:3;;;;;;;;;;-1:-1:-1;39723:1273:3;;;;;:::i;:::-;;:::i;2042:139:1:-;;;;;;;;;;-1:-1:-1;2042:139:1;;;;;:::i;:::-;;:::i;41229:1198:3:-;;;;;;;;;;-1:-1:-1;41229:1198:3;;;;;:::i;:::-;;:::i;2423:26:4:-;;;;;;;;;;;;;;;;7220:75;;;;;;;;;;-1:-1:-1;7266:4:4;7220:75;;;9995:14:19;;9988:22;9970:41;;9958:2;9943:18;7220:75:4;9830:187:19;273:565:18;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;33963:223:3:-;;;;;;;;;;-1:-1:-1;33963:223:3;;;;;:::i;:::-;;:::i;4003:52:4:-;;;;;;;;;;;;4051:4;4003:52;;4440:521:3;;;;;;;;;;-1:-1:-1;4440:521:3;;;;;:::i;:::-;;:::i;:::-;;;;12151:25:19;;;12207:2;12192:18;;12185:34;;;;12235:18;;;12228:34;12293:2;12278:18;;12271:34;12138:3;12123:19;4440:521:3;11920:391:19;3349:120:1;;;;;;;;;;-1:-1:-1;3349:120:1;;;;;:::i;:::-;;:::i;4331:113:2:-;;;;;;;;;;-1:-1:-1;4416:23:2;;;;;;;;;;;;-1:-1:-1;;;4416:23:2;;;;4331:113;;2510:120:1;;;;;;;;;;-1:-1:-1;2510:120:1;;;;;:::i;:::-;;:::i;2055:30:4:-;;;;;;;;;;;;;;;;2914:28;;;;;;;;;;;;;;;;1660:42;;;;;;;;;;-1:-1:-1;1660:42:4;;;;-1:-1:-1;;;;;1660:42:4;;;4728:259:1;;;;;;;;;;-1:-1:-1;4728:259:1;;;;;:::i;:::-;;:::i;7049:74:4:-;;;;;;;;;;-1:-1:-1;7114:4:4;7049:74;;2475:294:16;2546:7;2561:34;2598:16;:14;:16::i;:::-;-1:-1:-1;;;;;;2640:20:16;;2620:17;2640:20;;;;;;;;;;:35;2561:53;;-1:-1:-1;;;;;;2640:35:16;2685:23;2681:61;;2735:6;2717:25;;-1:-1:-1;;;2717:25:16;;;;;;;;:::i;2681:61::-;2755:9;2475:294;-1:-1:-1;;;2475:294:16:o;874:804:1:-;1219:36;1258:6;1219:45;;1270:15;1303:11;-1:-1:-1;;;;;1288:36:1;;:38;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1270:56;;1332:222;1356:12;1376:10;1394:18;1420:28;1456:5;1469:7;1484:9;1501:22;1531:17;1332:16;:222::i;:::-;1603:10;:24;;-1:-1:-1;;;;;;1603:24:1;-1:-1:-1;;;;;1603:24:1;;;;;;;;1633:40;;;-1:-1:-1;;;1633:40:1;;;;:38;;:40;;;;;;;;;;;;;;;1603:24;1633:40;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;1162:516;;874:804;;;;;;;;:::o;848:18:4:-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;3658:155:1:-;3727:7;3743:11;3760:32;3780:11;3760:19;:32::i;:::-;-1:-1:-1;3742:50:1;3658:155;-1:-1:-1;;;3658:155:1:o;5233:255:3:-;5327:7;5311:5;43230:30;43250:9;43230:19;:30::i;:::-;5407:14:::1;6951:4:4::0;-1:-1:-1;;;;;5350:43:3::1;;:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:72;5342:100;;;::::0;-1:-1:-1;;;5342:100:3;;14195:2:19;5342:100:3::1;::::0;::::1;14177:21:19::0;14234:2;14214:18;;;14207:30;-1:-1:-1;;;14253:18:19;;;14246:45;14308:18;;5342:100:3::1;13993:339:19::0;5342:100:3::1;5455:28;5475:7;5455:19;:28::i;:::-;5448:35;;43266:1;43273:29:::0;43292:9;43273:18;:29::i;:::-;5233:255;;;;:::o;3826:501:2:-;3882:10;3904:4;3882:27;;;;:94;;;3942:11;;;;;;;;;-1:-1:-1;;;;;3942:11:2;-1:-1:-1;;;;;3913:61:2;;:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;3878:445;;;4105:9;;3987:28;4144:14;;4076:83;;-1:-1:-1;;;4076:83:2;;3987:28;;;;;;-1:-1:-1;;;;;4105:9:2;;;;4076:67;;:83;;4144:14;;;;4076:83;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;4076:83:2;;;;;;;;;;;;:::i;:::-;4171:14;;3986:173;;-1:-1:-1;3986:173:2;;-1:-1:-1;3986:173:2;-1:-1:-1;;;;;;4171:38:2;;;:14;;:38;4167:150;;4221:87;4248:20;4270:11;4283:24;4221:26;:87::i;:::-;3978:345;;;3878:445;3826:501::o;1891:2225:3:-;2231:10;-1:-1:-1;;;;;2231:24:3;;;2223:43;;;;-1:-1:-1;;;2223:43:3;;;;;;;:::i;:::-;2280:18;;:23;:43;;;;-1:-1:-1;2307:11:3;;:16;2280:43;2272:68;;;;-1:-1:-1;;;2272:68:3;;16154:2:19;2272:68:3;;;16136:21:19;16193:2;16173:18;;;16166:30;-1:-1:-1;;;16212:18:19;;;16205:42;16264:18;;2272:68:3;15952:336:19;2272:68:3;2347:9;:22;;-1:-1:-1;;;;;;2347:22:3;-1:-1:-1;;;;;2347:22:3;;;;;2409:27;:58;;;;2473:59;;;;-1:-1:-1;;;2473:59:3;;16495:2:19;2473:59:3;;;16477:21:19;16534:2;16514:18;;;16507:30;-1:-1:-1;;;16553:18:19;;;16546:45;16608:18;;2473:59:3;16293:339:19;2473:59:3;2566:11;:26;;-1:-1:-1;;;;;;2566:26:3;-1:-1:-1;;;;;2566:26:3;;;;;;;;;;2721:12;2700:18;:33;450:4:12;2739:11:3;:25;2855:40;;;-1:-1:-1;;;2855:40:3;;;;:38;;;;;;:40;;;;;;;;;;;;;;;:38;:40;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;2847:60;;;;-1:-1:-1;;;2847:60:3;;16839:2:19;2847:60:3;;;16821:21:19;16878:1;16858:18;;;16851:29;-1:-1:-1;;;16896:18:19;;;16889:37;16943:18;;2847:60:3;16637:330:19;2847:60:3;2913:17;:38;;-1:-1:-1;;;;;;2913:38:3;-1:-1:-1;;;;;2913:38:3;;;;;2962:77;;;;;;-1:-1:-1;;2913:38:3;;2962:77;:::i;:::-;;;;;;;;3046:12;;;;:4;;:12;;;;;:::i;:::-;-1:-1:-1;3064:16:3;;;;:6;;:16;;;;;:::i;:::-;-1:-1:-1;3086:8:3;:20;;-1:-1:-1;;3086:20:3;;;;;;;3242:15;;3223:16;;1334:4:4;;3242:15:3;3198:41;;:22;:41;:::i;:::-;:59;;;;:::i;:::-;:95;;3190:115;;;;-1:-1:-1;;;3190:115:3;;17800:2:19;3190:115:3;;;17782:21:19;17839:1;17819:18;;;17812:29;-1:-1:-1;;;17857:18:19;;;17850:37;17904:18;;3190:115:3;17598:330:19;3190:115:3;3311:21;:46;;;3368:43;;;3385:1;18115:25:19;;18171:2;18156:18;;18149:34;;;3368:43:3;;18088:18:19;3368:43:3;;;;;;;-1:-1:-1;;3477:17:3;:38;3473:80;;;-1:-1:-1;3537:16:3;;3473:80;3635:9;;3615:48;;;-1:-1:-1;;;3615:48:3;;;;3586:26;;-1:-1:-1;;;;;3635:9:3;;3615:46;;:48;;;;;;;;;;;;;;3635:9;3615:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;3586:77;;1334:4:4;3728:18:3;3708:17;3684:21;;:41;;;;:::i;:::-;:62;;;;:::i;:::-;:98;;3669:142;;;;-1:-1:-1;;;3669:142:3;;18396:2:19;3669:142:3;;;18378:21:19;18435:2;18415:18;;;18408:30;-1:-1:-1;;;18454:18:19;;;18447:43;18507:18;;3669:142:3;18194:337:19;3669:142:3;3817:16;:36;;;3864:33;;;3876:1;18115:25:19;;18171:2;18156:18;;18149:34;;;3864:33:3;;18088:18:19;3864:33:3;;;;;;;3903:15;:36;;;3950:33;;;3961:1;18115:25:19;;18171:2;18156:18;;18149:34;;;3950:33:3;;18088:18:19;3950:33:3;;;;;;;-1:-1:-1;;4093:11:3;:18;;-1:-1:-1;;;;4093:18:3;-1:-1:-1;;;4093:18:3;;;-1:-1:-1;;;;;;;;1891:2225:3:o;4079:195:1:-;4172:7;4188:11;4205:48;4231:8;4241:11;4205:25;:48::i;:::-;-1:-1:-1;4187:66:1;-1:-1:-1;;4079:195:1;;;;;:::o;6927:92:3:-;6978:7;7000:14;:12;:14::i;:::-;6993:21;;6927:92;:::o;3267:390:2:-;3457:16;:14;:16::i;:::-;3449:35;;;;-1:-1:-1;;;3449:35:2;;;;;;;:::i;:::-;3521:14;;-1:-1:-1;;;;;3521:33:2;;;:14;;:33;3517:136;;3564:82;3591:15;3608:11;3621:24;;3564:82;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;3564:26:2;;-1:-1:-1;;;3564:82:2:i;:::-;3267:390;;;;:::o;479:160::-;567:10;589:4;567:27;;:47;;;598:16;:14;:16::i;:::-;559:75;;;;-1:-1:-1;;;559:75:2;;18738:2:19;559:75:2;;;18720:21:19;18777:2;18757:18;;;18750:30;-1:-1:-1;;;18796:18:19;;;18789:45;18851:18;;559:75:2;18536:339:19;559:75:2;479:160;:::o;1134:111:16:-;1182:16;1213:27;:25;:27::i;2964:140:1:-;3039:7;3061:38;3086:12;3061:24;:38::i;42641:424:3:-;42834:11;;;42890:9;-1:-1:-1;;;;;42834:11:3;;;;42890:9;42868:10;:32;:75;;;;;42904:18;-1:-1:-1;;;;;42904:37:3;;:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;42853:137;;;;-1:-1:-1;;;42853:137:3;;19082:2:19;42853:137:3;;;19064:21:19;19121:2;19101:18;;;19094:30;19160:33;19140:18;;;19133:61;19211:18;;42853:137:3;18880:355:19;42853:137:3;42996:64;43025:14;43041:18;42996:28;:64::i;931:20:4:-;;;;;;;:::i;5678:1095:3:-;-1:-1:-1;;;;;5993:23:3;;5754:7;5993:23;;;:14;:23;;;;;6201:24;;5754:7;;;;;;5993:23;6197:58;;-1:-1:-1;6247:1:3;;5678:1095;-1:-1:-1;;;;;5678:1095:3:o;6197:58::-;6461:46;6469:14;:24;;;6495:11;;6461:7;:46::i;:::-;6428:79;;-1:-1:-1;6428:79:3;-1:-1:-1;6532:18:3;6521:7;:29;;;;;;;;:::i;:::-;;6513:72;;;;-1:-1:-1;;;6513:72:3;;19442:2:19;6513:72:3;;;19424:21:19;19481:2;19461:18;;;19454:30;19520:32;19500:18;;;19493:60;19570:18;;6513:72:3;19240:354:19;6513:72:3;6612:58;6620:19;6641:14;:28;;;6612:7;:58::i;:::-;6592:78;;-1:-1:-1;6592:78:3;-1:-1:-1;6695:18:3;6684:7;:29;;;;;;;;:::i;:::-;;6676:72;;;;-1:-1:-1;;;6676:72:3;;19801:2:19;6676:72:3;;;19783:21:19;19840:2;19820:18;;;19813:30;19879:32;19859:18;;;19852:60;19929:18;;6676:72:3;19599:354:19;6676:72:3;-1:-1:-1;6762:6:3;5678:1095;-1:-1:-1;;;;5678:1095:3:o;39723:1273::-;39821:7;39805:5;43230:30;43250:9;43230:19;:30::i;:::-;39836:13:::1;6951:4:4::0;-1:-1:-1;;;;;39852:43:3::1;;:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;39836:61:::0;-1:-1:-1;39907:32:3;;39903:268:::1;;40091:73;40102:5;40096:12;;;;;;;;:::i;:::-;40110:53;40091:4;:73::i;:::-;40084:80;;;;;39903:268;40203:12;40181:18;;:34;40177:134;;40232:72;40237:22;40261:42;40232:4;:72::i;40177:134::-;40338:14;40321;:12;:14::i;:::-;:31;40317:145;;;40369:86;40374:29;40405:49;40369:4;:86::i;40317:145::-;40489:13;;40472:14;:30;40468:122;;;40519:64;40524:15;40541:41;40519:4;:64::i;40468:122::-;40701:24;40744:14;40728:13;;:30;;;;:::i;:::-;40764:13;:32:::0;;;40927:9:::1;::::0;40701:57;;-1:-1:-1;40905:49:3::1;::::0;-1:-1:-1;;;;;40927:9:3::1;40939:14:::0;40905:13:::1;:49::i;:::-;40976:14;40961:30;;;;43273:29:::0;43292:9;43273:18;:29::i;2042:139:1:-;2103:7;2119:11;2136:24;2149:10;2136:12;:24::i;41229:1198:3:-;41328:7;41312:5;43230:30;43250:9;43230:19;:30::i;:::-;41343:13:::1;6951:4:4::0;-1:-1:-1;;;;;41359:43:3::1;;:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;41343:61:::0;-1:-1:-1;41414:32:3;;41410:134:::1;;41463:74;41474:5;41468:12;;;;;;;;:::i;:::-;41482:54;41463:4;:74::i;41410:134::-;41576:12;41554:18;;:34;41550:135;;41605:73;41610:22;41634:43;41605:4;:73::i;41550:135::-;41780:14;41763;:12;:14::i;:::-;:31;41759:146;;;41811:87;41816:29;41847:50;41811:4;:87::i;41759:146::-;41932:14;;41915;:31;41911:124;;;41963:65;41968:15;41985:42;41963:4;:65::i;41911:124::-;42179:14;42162;;:31;;;;:::i;:::-;42145:14;:48:::0;42347:11:::1;::::0;42316:52:::1;::::0;;-1:-1:-1;;;42316:52:3;;;;42302:83:::1;::::0;-1:-1:-1;;;;;42347:11:3::1;::::0;42316:50:::1;::::0;:52:::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;;42347:11;42316:52:::1;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;42370:14;42302:13;:83::i;:::-;42407:14;42399:23;42392:30;;;43273:29:::0;43292:9;43273:18;:29::i;273:565:18:-;348:22;400:4;-1:-1:-1;;;;;388:24:18;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;378:34;;423:9;418:416;438:15;;;418:416;;;469:12;;514:4;533;;538:1;533:7;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;506:35;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;468:73;;;;555:7;550:250;;666:2;650:6;:13;:18;646:32;;;670:8;;;646:32;731:4;723:6;719:17;709:27;;773:6;762:28;;;;;;;;;;;;:::i;:::-;755:36;;-1:-1:-1;;;755:36:18;;;;;;;;:::i;550:250::-;821:6;808:7;816:1;808:10;;;;;;;;:::i;:::-;;;;;;:19;;;;460:374;;455:3;;;;;:::i;:::-;;;;418:416;;;;273:565;;;;:::o;33963:223:3:-;34099:7;34084:4;43230:30;43250:9;43230:19;:30::i;:::-;34121:60:::1;34135:10;34147;34159:8;34169:11;34121:13;:60::i;:::-;34114:67;;43273:29:::0;43292:9;43273:18;:29::i;4440:521::-;-1:-1:-1;;;;;4631:22:3;;4540:7;4631:22;;;:13;:22;;;;;;4540:7;;;;;;;;;4758:28;4645:7;4758:19;:28::i;:::-;4742:44;-1:-1:-1;6951:4:4;-1:-1:-1;;;;;4816:47:3;;:49;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;4793:72;-1:-1:-1;4888:14:3;4872:84;4905:13;;-1:-1:-1;4920:13:3;;-1:-1:-1;4920:13:3;-1:-1:-1;4440:521:3;;-1:-1:-1;;;4440:521:3:o;3349:120:1:-;3414:7;3436:28;3451:12;3436:14;:28::i;2510:120::-;2575:7;2597:28;2612:12;2597:14;:28::i;4728:259::-;4869:7;4885:11;4902:64;4926:8;4936:11;4949:16;4902:23;:64::i;:::-;-1:-1:-1;4884:82:1;4728:259;-1:-1:-1;;;;;4728:259:1:o;2773:175:16:-;2182:45;;2773:175::o;22733:581:3:-;22821:7;22830;22805:5;43230:30;43250:9;43230:19;:30::i;:::-;22845:13:::1;6951:4:4::0;-1:-1:-1;;;;;22861:43:3::1;;:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;22845:61:::0;-1:-1:-1;22916:32:3;;22912:244:::1;;23078:67;23089:5;23083:12;;;;;;;;:::i;:::-;23097:47;23078:4;:67::i;:::-;23147:1;23070:79;;;;;;;22912:244;23256:53;23273:10;23285;23297:11;23256:16;:53::i;:::-;23249:60;;;;;43266:1;43273:29:::0;43292:9;43273:18;:29::i;:::-;22733:581;;;;:::o;43608:178::-;43675:11;;-1:-1:-1;;;43675:11:3;;;;43667:34;;;;-1:-1:-1;;;43667:34:3;;22083:2:19;43667:34:3;;;22065:21:19;22122:2;22102:18;;;22095:30;-1:-1:-1;;;22141:18:19;;;22134:40;22191:18;;43667:34:3;21881:334:19;43667:34:3;43712:9;43707:49;;43723:11;;;;;;;;;-1:-1:-1;;;;;43723:11:3;-1:-1:-1;;;;;43723:31:3;;:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;43707:49;-1:-1:-1;43762:11:3;:19;;-1:-1:-1;;;;43762:19:3;;;43608:178::o;44086:169::-;44144:11;:18;;-1:-1:-1;;;;44144:18:3;-1:-1:-1;;;44144:18:3;;;44207:9;44202:48;;44218:11;;;;;;;;;-1:-1:-1;;;;;44218:11:3;-1:-1:-1;;;;;44218:30:3;;:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;44086:169;:::o;1284:1604:2:-;1491:9;;;1526:14;1471:100;;-1:-1:-1;;;1471:100:2;;-1:-1:-1;;;;;1491:9:2;;;;1471:54;;:100;;1526:14;;;1542:15;;1559:11;;1471:100;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1456:136;;;;-1:-1:-1;;;1456:136:2;;22812:2:19;1456:136:2;;;22794:21:19;22851:1;22831:18;;;22824:29;-1:-1:-1;;;22869:18:19;;;22862:35;22914:18;;1456:136:2;22610:328:19;1456:136:2;1714:25;1742:14;;-1:-1:-1;;;;;1762:32:2;;;-1:-1:-1;;;;;;1762:32:2;;;;;;1742:14;1909:9;1889:74;;-1:-1:-1;;;1889:74:2;;1742:14;;;;1714:25;1909:9;;;1889:58;;:74;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;1889:74:2;;;;;;;;;;;;:::i;:::-;1853:110;;1969:34;2006:27;:25;:27::i;:::-;1969:64;;2088:9;2083:136;2107:17;:24;2103:1;:28;2083:136;;;2146:66;2190:17;2208:1;2190:20;;;;;;;;:::i;:::-;;;;;;;2146:26;:66::i;:::-;2133:3;;;;:::i;:::-;;;;2083:136;;;;2259:9;2254:131;2278:16;:23;2274:1;:27;2254:131;;;2316:62;2357:16;2374:1;2357:19;;;;;;;;:::i;:::-;;;;;;;2316:23;:62::i;:::-;2303:3;;;;:::i;:::-;;;;2254:131;;;-1:-1:-1;2403:4:2;2395:25;2391:429;;2508:47;2530:24;2508:21;:47::i;:::-;2391:429;;;2659:154;2690:4;2761:24;2705:81;;;;;;;;:::i;:::-;;;;-1:-1:-1;;2705:81:2;;;;;;;;;;;;;;;-1:-1:-1;;;;;2705:81:2;-1:-1:-1;;;2705:81:2;;;2659:154;;;;;;;;;;;-1:-1:-1;;;2659:154:2;;;;:13;:154::i;:::-;;2391:429;2868:14;;2831:52;;;;;;2849:17;;-1:-1:-1;;;;;2868:14:2;;2831:52;:::i;:::-;;;;;;;;1427:1461;;;1284:1604;;;:::o;23625:617:3:-;23749:7;23758;23729:5;43230:30;43250:9;43230:19;:30::i;:::-;23775:13:::1;6951:4:4::0;-1:-1:-1;;;;;23791:43:3::1;;:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;23775:61:::0;-1:-1:-1;23846:32:3;;23842:244:::1;;24008:67;24019:5;24013:12;;;;;;;;:::i;:::-;24027:47;24008:4;:67::i;:::-;24077:1;24000:79;;;;;;;23842:244;24186:51;24203:10;24215:8;24225:11;24186:16;:51::i;:::-;24179:58;;;;;43266:1;43273:29:::0;43292:9;43273:18;:29::i;:::-;23625:617;;;;;;:::o;5232:176:1:-;5349:10;;5373:30;;-1:-1:-1;;;5373:30:1;;5296:7;;-1:-1:-1;;;;;5349:10:1;;;;5373:15;;:30;;5397:4;;5373:30;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5366:37;;;5232:176;:::o;1071:337:3:-;1203:11;;1250:26;;;-1:-1:-1;;;1250:26:3;;;;1120:4;;-1:-1:-1;;;;;1203:11:3;;;;1250:24;;:26;;;;;;;;;;;;;;;1203:11;1250:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;1236:40:3;:10;-1:-1:-1;;;;;1236:40:3;;:79;;;;;1280:18;-1:-1:-1;;;;;1280:33:3;;:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1235:168;;;-1:-1:-1;1349:9:3;;-1:-1:-1;;;;;1349:9:3;1327:10;:32;:75;;;;;1363:18;-1:-1:-1;;;;;1363:37:3;;:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;2952:112:16:-;3001:16;3032;:14;:16::i;:::-;:27;;3025:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;3025:34:16;;;;;;;;;;;;;;;;;;;;;;;2952:112;:::o;12785:543:3:-;12879:7;12863:5;43230:30;43250:9;43230:19;:30::i;:::-;12894:13:::1;6951:4:4::0;-1:-1:-1;;;;;12910:43:3::1;;:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;12894:61:::0;-1:-1:-1;12965:32:3;;12961:233:::1;;13126:61;13137:5;13131:12;;;;;;;;:::i;:::-;13145:41;13126:4;:61::i;12961:233::-;13283:40;13295:10;13307:1;13310:12;13283:11;:40::i;3068:247:16:-:0;-1:-1:-1;;;;;3184:41:16;;;3180:97;;3235:35;3251:18;3235:15;:35::i;:::-;3282:28;3295:14;3282:12;:28::i;:::-;3068:247;;:::o;544:330:5:-;606:9;;636:6;632:57;;-1:-1:-1;660:18:5;;-1:-1:-1;660:18:5;652:30;;632:57;732:5;;;736:1;754:5;732:1;:5;754;:::i;:::-;:10;750:120;;782:26;810:1;774:38;;;;;;;750:120;841:18;;-1:-1:-1;861:1:5;-1:-1:-1;544:330:5;;;;;;:::o;958:198::-;1020:9;;1050:6;1046:65;;-1:-1:-1;1074:26:5;;-1:-1:-1;1102:1:5;1066:38;;1046:65;1125:18;1145:5;1149:1;1145;:5;:::i;:::-;1117:34;;;;958:198;;;;;:::o;7749:151:10:-;7810:7;-1:-1:-1;;;;;;;;;;;7846:3:10;7838:12;;;;;;;;:::i;:::-;7860:4;7852:13;;;;;;;;:::i;:::-;7867:1;7830:39;;;;;;;;:::i;:::-;;;;;;;;7891:3;7883:12;;;;;;;;:::i;7340:247:1:-;7423:159;7473:55;;;7530:2;7534:6;7450:91;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;-1:-1:-1;;;;;7450:91:1;;;;;;;-1:-1:-1;;;;;7450:91:1;;;;;;;;;;;7423:159;;;;;;;;;;;;;-1:-1:-1;;;7423:159:1;;;:19;:159::i;7395:556:3:-;7475:7;7484;7459:5;43230:30;43250:9;43230:19;:30::i;:::-;7499:13:::1;6951:4:4::0;-1:-1:-1;;;;;7515:43:3::1;;:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;7499:61:::0;-1:-1:-1;7570:32:3;;7566:236:::1;;7732:59;7743:5;7737:12;;;;;;;;:::i;:::-;7751:39;7732:4;:59::i;7566:236::-;7913:33;7923:10;7935;7913:9;:33::i;35231:3167::-:0;35441:11;;:87;;-1:-1:-1;;;35441:87:3;;35372:7;;;;-1:-1:-1;;;;;35441:11:3;;;;:24;;:87;;35474:4;;35481:11;;35494:10;;35506:8;;35516:11;;35441:87;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;35423:105;-1:-1:-1;35538:12:3;;35534:139;;35567:99;35578:27;35607:49;35658:7;35567:10;:99::i;:::-;35560:106;;;;;35534:139;35735:10;-1:-1:-1;;;;;35723:22:3;:8;-1:-1:-1;;;;;35723:22:3;;35719:134;;;35762:84;35767:26;35795:50;35762:4;:84::i;35719:134::-;35859:34;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;35859:34:3;-1:-1:-1;;;;;36199:23:3;;;;;;:13;:23;;;;;;36191:45;;36224:11;36191:7;:45::i;:::-;36165:22;;;36150:86;;;36151:4;36150:86;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;-1:-1:-1;36262:18:3;;-1:-1:-1;36246:12:3;;:34;;;;;;;;:::i;:::-;;36242:167;;36297:105;36308:16;36326:52;36388:4;:12;;;36380:21;;;;;;;;:::i;:::-;36297:10;:105::i;:::-;36290:112;;;;;;36242:167;36442:64;36447:11;36460:45;;;;;;;;3928:6:4;36460:45:3;;;36442:4;:64::i;:::-;36415:24;;;:91;36552:40;;;;;;;;;4051:4:4;36552:40:3;;36534:59;;36539:11;;36534:4;:59::i;:::-;36512:19;;;:81;;;36642:24;;;;36628:38;;:11;:38;:::i;:::-;:60;;;;:::i;:::-;36599:26;;;:89;6951:4:4;-1:-1:-1;;;;;36723:47:3;;:49;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;36695:25;;;:77;;;36832:44;;;;;;;;;36848:25;;36832:44;;-1:-1:-1;;;36884:24:3;36806:108;;36832:44;36806:18;:108::i;:::-;36779:24;;;:135;36961:44;;;;;;;;;36977:25;;;;36961:44;;37007:19;;;;36942:85;;36961:44;36942:18;:85::i;:::-;36920:19;;;:107;37074:24;;;;37058:13;;:40;;37074:24;37058:40;:::i;:::-;37034:21;;;:64;37167:19;;;;37140:24;;;;37126:11;;:38;;37140:24;37126:38;:::i;:::-;:60;;;;:::i;:::-;37104:19;;;:82;37231:19;;;;37215:13;;:35;;37231:19;37215:35;:::i;:::-;37192:20;;;:58;-1:-1:-1;;;;;37308:25:3;;;;;;:13;:25;;;;;;37335:26;;;;37300:62;;37308:25;37300:7;:62::i;:::-;37272:24;;;37257:105;;;37258:4;37257:105;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;-1:-1:-1;37388:18:3;;-1:-1:-1;37372:12:3;;:34;;;;;;;;:::i;:::-;;37368:167;;37423:105;37434:16;37452:52;37514:4;:12;;;37506:21;;;;;;;;:::i;37368:167::-;37727:21;;;;37711:13;:37;37768:19;;;;37754:11;:33;37809:20;;;;37793:13;:36;37862:22;;;;;-1:-1:-1;;;;;37836:23:3;;;-1:-1:-1;37836:23:3;;;:13;:23;;;;;;:48;;;;37918:24;;;;37890:25;;;;;;;;;;:52;;;;38017:26;;;;37986:58;;4070:25:19;;;37890::3;;37836:23;;-1:-1:-1;;;;;;;;;;;37986:58:3;4043:18:19;37986:58:3;;;;;;;38082:4;-1:-1:-1;;;;;38055:59:3;38064:8;-1:-1:-1;;;;;38055:59:3;-1:-1:-1;;;;;;;;;;;38089:4:3;:24;;;38055:59;;;;4070:25:19;;4058:2;4043:18;;3924:177;38055:59:3;;;;;;;;38154:24;;;;38180:21;;;;38125:77;;;;;;38147:4;;38125:77;:::i;:::-;;;;;;;;38378:14;38363:30;;;;35231:3167;;;;;;;:::o;18626:530::-;18710:7;18694:5;43230:30;43250:9;43230:19;:30::i;:::-;18725:13:::1;6951:4:4::0;-1:-1:-1;;;;;18741:43:3::1;;:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;18725:61:::0;-1:-1:-1;18796:32:3;;18792:233:::1;;18957:61;18968:5;18962:12;;;;;;;;:::i;:::-;18976:41;18957:4;:61::i;18792:233::-;19114:37;19126:10;19138:12;19114:11;:37::i;11894:533::-:0;11978:7;11962:5;43230:30;43250:9;43230:19;:30::i;:::-;11993:13:::1;6951:4:4::0;-1:-1:-1;;;;;12009:43:3::1;;:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;11993:61:::0;-1:-1:-1;12064:32:3;;12060:233:::1;;12225:61;12236:5;12230:12;;;;;;;;:::i;12060:233::-;12382:40;12394:10;12406:12;12420:1;12382:11;:40::i;28368:1020::-:0;28528:7;28537;28512:5;43230:30;43250:9;43230:19;:30::i;:::-;28552:13:::1;6951:4:4::0;-1:-1:-1;;;;;28568:43:3::1;;:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;28552:61:::0;-1:-1:-1;28623:32:3;;28619:253:::1;;28790:71;28801:5;28795:12;;;;;;;;:::i;:::-;28809:51;28790:4;:71::i;:::-;28863:1;28782:83;;;;;;;28619:253;28886:16;-1:-1:-1::0;;;;;28886:43:3::1;;:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;28886:60:3::1;;:62;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;28878:70:::0;-1:-1:-1;28958:32:3;;28954:257:::1;;29125:75;29136:5;29130:12;;;;;;;;:::i;:::-;29144:55;29125:4;:75::i;28954:257::-;29310:73;29331:10;29343:8;29353:11;29366:16;29310:20;:73::i;:::-;29303:80;;;;;43266:1;43273:29:::0;43292:9;43273:18;:29::i;:::-;28368:1020;;;;;;;:::o;24893:2976::-;25091:11;;:75;;-1:-1:-1;;;25091:75:3;;25130:4;25091:75;;;26907:34:19;-1:-1:-1;;;;;26977:15:19;;;26957:18;;;26950:43;27029:15;;;27009:18;;;27002:43;27061:18;;;27054:34;;;25007:7:3;;;;;;25091:11;;;;:30;;26841:19:19;;25091:75:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;25073:93;-1:-1:-1;25176:12:3;;25172:141;;25206:96;25217:27;25246:46;25294:7;25206:10;:96::i;:::-;25304:1;25198:108;;;;;;;25172:141;25412:12;25390:18;;:34;25386:137;;25442:70;25447:22;25471:40;25442:4;:70::i;25386:137::-;25529:32;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;25529:32:3;-1:-1:-1;;;;;25664:24:3;;;;;;:14;:24;;;;;:38;;;25643:18;;;:59;25806:29;25679:8;25806:19;:29::i;:::-;25784:19;;;:51;-1:-1:-1;;25907:32:3;;25903:142;;;25968:19;;;;25949:16;;;:38;25903:142;;;26008:16;;;:30;;;25903:142;26586:37;26599:5;26606:4;:16;;;26586:12;:37::i;:::-;26561:22;;;:62;;;26902:19;;;;26894:52;;:7;:52::i;:::-;26868:22;;;26853:93;;;26854:12;;;26853:93;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;-1:-1:-1;26976:18:3;;-1:-1:-1;26960:4:3;:12;;;:34;;;;;;;;:::i;:::-;;26952:105;;;;-1:-1:-1;;;26952:105:3;;27301:2:19;26952:105:3;;;27283:21:19;27340:2;27320:18;;;27313:30;27379:34;27359:18;;;27352:62;-1:-1:-1;;;27430:18:19;;;27423:56;27496:19;;26952:105:3;27099:422:19;26952:105:3;27103:45;27111:12;;27125:4;:22;;;27103:7;:45::i;:::-;27079:20;;;27064:84;;;27065:12;;;27064:84;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;-1:-1:-1;27178:18:3;;-1:-1:-1;27162:4:3;:12;;;:34;;;;;;;;:::i;:::-;;27154:96;;;;-1:-1:-1;;;27154:96:3;;27728:2:19;27154:96:3;;;27710:21:19;27767:2;27747:18;;;27740:30;27806:34;27786:18;;;27779:62;-1:-1:-1;;;27857:18:19;;;27850:47;27914:19;;27154:96:3;27526:413:19;27154:96:3;27359:22;;;;;;-1:-1:-1;;;;;27322:24:3;;;;;;;:14;:24;;;;;;;;;:59;;;27428:11;;27387:38;;;;:52;;;;27460:20;;;;27445:12;:35;;;27559:22;;;;27583;;27530:98;;28259:15:19;;;28241:34;;28291:18;;;28284:43;;;;28343:18;;28336:34;;;;28401:2;28386:18;;28379:34;;;;28444:3;28429:19;;28422:35;;;;27530:98:3;;28175:19:19;27530:98:3;;;;;;;27841:22;;;27824:14;;-1:-1:-1;27841:22:3;-1:-1:-1;;24893:2976:3;;;;;;;:::o;3319:430:16:-;3387:23;3413:16;:14;:16::i;:::-;3387:42;;3491:35;3516:9;3491:24;:35::i;:::-;3537:7;3532:213;3554:13;;;:20;3550:24;;;;3532:213;;;3621:9;-1:-1:-1;;;;;3593:38:16;:2;:13;;3607:1;3593:16;;;;;;;;;;:::i;:::-;;;;;;;;;;;-1:-1:-1;;;;;3593:16:16;:38;3589:150;;;3662:13;;;3676:20;;:24;;3699:1;;3676:24;:::i;:::-;3662:39;;;;;;;;:::i;:::-;;;;;;;;;;;3643:13;;;:16;;-1:-1:-1;;;;;3662:39:16;;;;3643:16;;;;;;;;;;:::i;:::-;;;;;;;;;:58;;;;;-1:-1:-1;;;;;3643:58:16;;;;;-1:-1:-1;;;;;3643:58:16;;;;;;3711:2;:13;;:19;;;;;;;:::i;:::-;;;;;;;;;;-1:-1:-1;;3711:19:16;;;;;-1:-1:-1;;;;;;3711:19:16;;;;;;3589:150;3576:3;;;;:::i;:::-;;;;3532:213;;3753:337;3818:23;3844:16;:14;:16::i;:::-;3818:42;;3871:7;3866:138;3888:13;;;:20;3884:24;;;;3866:138;;;3959:9;-1:-1:-1;;;;;3931:38:16;:2;:13;;3945:1;3931:16;;;;;;;;;;:::i;:::-;;;;;;;;;;;-1:-1:-1;;;;;3931:16:16;:38;;3923:74;;;;-1:-1:-1;;;3923:74:16;;28982:2:19;3923:74:16;;;28964:21:19;29021:2;29001:18;;;28994:30;-1:-1:-1;;;29040:18:19;;;29033:53;29103:18;;3923:74:16;28780:347:19;3923:74:16;3910:3;;;;:::i;:::-;;;;3866:138;;;;4009:32;4031:9;4009:21;:32::i;:::-;4047:13;;:38;;;;;;;-1:-1:-1;4047:38:16;;;;;;;;;;-1:-1:-1;;;;;;4047:38:16;-1:-1:-1;;;;;4047:38:16;;;;;;;;;;3753:337::o;44944:679:3:-;45064:12;45085;45099:23;45126:6;-1:-1:-1;;;;;45126:11:3;45138:4;45126:17;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;45084:59;;;;45155:7;45150:445;;45236:17;;:21;45232:357;;45460:10;45454:17;45510:15;45497:10;45493:2;45489:19;45482:44;45232:357;45567:12;45560:20;;-1:-1:-1;;;45560:20:3;;;;;;;;:::i;45232:357::-;45608:10;44944:679;-1:-1:-1;;;;;44944:679:3:o;14162:4219::-;14283:7;14306:19;;;:42;;-1:-1:-1;14329:19:3;;14306:42;14298:78;;;;-1:-1:-1;;;14298:78:3;;29613:2:19;14298:78:3;;;29595:21:19;29652:2;29632:18;;;29625:30;-1:-1:-1;;;29671:18:19;;;29664:53;29734:18;;14298:78:3;29411:347:19;14298:78:3;14383:27;;:::i;:::-;6951:4:4;-1:-1:-1;;;;;14500:47:3;;:49;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;14472:25;;;:77;-1:-1:-1;;14560:35:3;;14556:137;;;14622:11;;:64;;-1:-1:-1;;;14622:64:3;;-1:-1:-1;;;;;14622:11:3;;;;:32;;:64;;14655:8;;14673:4;;14622:11;;:64;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;14605:81;;14556:137;14736:18;;14732:1211;;14970:17;;;:34;;;15076:44;;;;;;;;15092:25;;;;15076:44;;15049:103;;14990:14;15049:17;:103::i;:::-;15028:17;;;15013:139;;;15014:12;;;15013:139;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;-1:-1:-1;15180:18:3;;-1:-1:-1;15164:4:3;:12;;;:34;;;;;;;;:::i;:::-;;15160:182;;15227:106;15238:16;15256:53;15319:4;:12;;;15311:21;;;;;;;;:::i;15227:106::-;15210:123;;;;;15160:182;14732:1211;;;15596:108;15628:14;15652:44;;;;;;;;15668:4;:25;;;15652:44;;;15596:22;:108::i;:::-;15575:17;;;15560:144;;;15561:12;;;15560:144;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;-1:-1:-1;15732:18:3;;-1:-1:-1;15716:4:3;:12;;;:34;;;;;;;;:::i;:::-;;15712:182;;15779:106;15790:16;15808:53;15871:4;:12;;;15863:21;;;;;;;;:::i;15712:182::-;15902:17;;;:34;;;14732:1211;16004:11;;16055:17;;;;16004:69;;-1:-1:-1;;;16004:69:3;;15986:15;;-1:-1:-1;;;;;16004:11:3;;:25;;:69;;16038:4;;16045:8;;16055:17;16004:69;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;15986:87;-1:-1:-1;16083:12:3;;16079:130;;16112:90;16123:27;16152:40;16194:7;16112:10;:90::i;:::-;16105:97;;;;;;16079:130;16308:12;16286:18;;:34;16282:126;;16337:64;16342:22;16366:34;16337:4;:64::i;16282:126::-;16672:39;16680:11;;16693:4;:17;;;16672:7;:39::i;:::-;16649:19;;;16634:77;;;16635:12;;;16634:77;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;-1:-1:-1;16737:18:3;;-1:-1:-1;16721:4:3;:12;;;:34;;;;;;;;:::i;:::-;;16717:177;;16780:107;16791:16;16809:54;16873:4;:12;;;16865:21;;;;;;;;:::i;16717:177::-;-1:-1:-1;;;;;16948:23:3;;;;;;:13;:23;;;;;;16973:17;;;;16940:51;;16948:23;16940:7;:51::i;:::-;16915:21;;;16900:91;;;16901:12;;;16900:91;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;-1:-1:-1;17017:18:3;;-1:-1:-1;17001:4:3;:12;;;:34;;;;;;;;:::i;:::-;;16997:180;;17060:110;17071:16;17089:57;17156:4;:12;;;17148:21;;;;;;;;:::i;16997:180::-;17264:4;:17;;;17247:14;:12;:14::i;:::-;:34;17243:143;;;17298:81;17303:29;17334:44;17298:4;:81::i;17243:143::-;17572:19;;;;17558:11;:33;17623:21;;;;-1:-1:-1;;;;;17597:23:3;;;;;;:13;:23;;;;;:47;18008:17;;;;17984:42;;17611:8;;17984:13;:42::i;:::-;18120:4;-1:-1:-1;;;;;18093:52:3;18102:8;-1:-1:-1;;;;;18093:52:3;-1:-1:-1;;;;;;;;;;;18127:4:3;:17;;;18093:52;;;;4070:25:19;;4058:2;4043:18;;3924:177;18093:52:3;;;;;;;;18173:17;;;;18192;;;;18156:54;;;;;;18163:8;;18156:54;:::i;:::-;;;;;;;;18252:11;;18302:17;;;;18321;;;;18252:87;;-1:-1:-1;;;18252:87:3;;18285:4;18252:87;;;30412:34:19;-1:-1:-1;;;;;30482:15:19;;;30462:18;;;30455:43;30514:18;;;30507:34;;;;30557:18;;;30550:34;;;;18252:11:3;;;:24;;30346:19:19;;18252:87:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;18361:14:3;;-1:-1:-1;18353:23:3;;-1:-1:-1;;18353:23:3;;18346:30;14162:4219;-1:-1:-1;;;;;;14162:4219:3:o;7971:253:1:-;8102:10;;8062:23;;8088:45;;-1:-1:-1;;;;;8102:10:1;8114:4;8120:12;8088:13;:45::i;:::-;8143:17;;8062:71;;-1:-1:-1;8143:21:1;8139:80;;8185:10;8174:30;;;;;;;;;;;;:::i;:::-;8206:12;8166:53;;;;;-1:-1:-1;;;8166:53:1;;;;;;;;:::i;8609:2956:3:-;8759:11;;:58;;-1:-1:-1;;;8759:58:3;;8682:7;;;;;;-1:-1:-1;;;;;8759:11:3;;:23;;:58;;8791:4;;8798:6;;8806:10;;8759:58;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;8741:76;-1:-1:-1;8827:12:3;;8823:133;;8857:88;8868:27;8897:38;8937:7;8857:10;:88::i;:::-;8947:1;8849:100;;;;;;;8823:133;9055:12;9033:18;;:34;9029:129;;9085:62;9090:22;9114:32;9085:4;:62::i;9029:129::-;9164:25;;:::i;:::-;6951:4:4;-1:-1:-1;;;;;9224:47:3;;:49;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;9196:25;;;:77;10171:32;10184:6;10192:10;10171:12;:32::i;:::-;10147:21;;;:56;;;10462:44;;;;;;;;10478:25;;;;10462:44;;10403:109;;10147:56;10403:22;:109::i;:::-;10384:15;;;10369:143;;;10370:12;;;10369:143;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;-1:-1:-1;10542:18:3;;-1:-1:-1;10526:4:3;:12;;;:34;;;;;;;;:::i;:::-;;10518:79;;;;-1:-1:-1;;;10518:79:3;;30797:2:19;10518:79:3;;;30779:21:19;;;30816:18;;;30809:30;30875:34;30855:18;;;30848:62;30927:18;;10518:79:3;30595:356:19;10518:79:3;10629:1;10611:4;:15;;;:19;10603:58;;;;-1:-1:-1;;;10603:58:3;;31158:2:19;10603:58:3;;;31140:21:19;31197:2;31177:18;;;31170:30;-1:-1:-1;;;31216:18:19;;;31209:56;31282:18;;10603:58:3;30956:350:19;10603:58:3;10932:4;:15;;;10918:11;;:29;;;;:::i;:::-;10896:19;;;:51;11002:15;;;;-1:-1:-1;;;;;10978:21:3;;;;;;:13;:21;;;;;;:39;;11002:15;10978:39;:::i;:::-;10954:21;;;:63;;;11099:19;;;;11085:11;:33;-1:-1:-1;;;;;11124:21:3;;;;;;:13;:21;;;;;;;:45;;;;11247:21;;;;11270:15;;;;11234:52;;;;;;11138:6;;11247:21;;11270:15;11234:52;:::i;:::-;;;;;;;;11321:6;-1:-1:-1;;;;;11297:48:3;11314:4;-1:-1:-1;;;;;11297:48:3;-1:-1:-1;;;;;;;;;;;11329:4:3;:15;;;11297:48;;;;4070:25:19;;4058:2;4043:18;;3924:177;11297:48:3;;;;;;;;11538:21;;;11521:14;;11538:21;;-1:-1:-1;8609:2956:3;-1:-1:-1;;;;8609:2956:3:o;8008:262:10:-;8112:7;-1:-1:-1;;;;;;;;;;;8148:3:10;8140:12;;;;;;;;:::i;:::-;8162:4;8154:13;;;;;;;;:::i;:::-;8169:11;8132:49;;;;;;;;:::i;:::-;;;;;;;;8202:27;8195:3;:34;;;;;;;;:::i;:::-;;:70;;8261:3;8253:12;;;;;;;;:::i;:::-;8195:70;;;8232:18;8239:11;8232:4;:18;:::i;1280:213:5:-;1342:9;1353:7;1377:1;1372;:6;1368:121;;1396:18;1416:5;1420:1;1416;:5;:::i;:::-;1388:34;;;;;;1368:121;-1:-1:-1;1451:27:5;;-1:-1:-1;1480:1:5;1443:39;;4229:119:12;4291:7;450:4;4313:19;4318:1;4321;:10;;;4313:4;:19::i;:::-;:30;;;;:::i;1117:167::-;1198:7;1213:18;1234:15;1239:1;1242:6;1234:4;:15::i;:::-;1213:36;;1262:17;1271:7;1262:8;:17::i;1567:263:5:-;1629:9;;1692:5;;;1714:6;;;1710:116;;1738:18;;-1:-1:-1;1758:1:5;-1:-1:-1;1730:30:5;;1710:116;1789:26;1817:1;1781:38;;;;;;;19542:2957:3;19691:11;;:64;;-1:-1:-1;;;19691:64:3;;19621:7;;;;-1:-1:-1;;;;;19691:11:3;;;;:25;;:64;;19725:4;;19732:8;;19742:12;;19691:64;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;19673:82;-1:-1:-1;19765:12:3;;19761:130;;19794:90;19805:27;19834:40;19876:7;19794:10;:90::i;:::-;19787:97;;;;;19761:130;19990:12;19968:18;;:34;19964:126;;20019:64;20024:22;20048:34;20019:4;:64::i;19964:126::-;20167:17;20187:14;:12;:14::i;:::-;20167:34;;20224:12;20212:9;:24;20208:126;;;20253:74;20258:29;20289:37;20253:4;:74::i;:::-;20246:81;;;;;;20208:126;20340:27;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20340:27:3;20608:29;20628:8;20608:19;:29::i;:::-;20586:19;;;:51;;;20685:42;;20714:12;20685:7;:42::i;:::-;20659:22;;;20644:83;;;20645:4;20644:83;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;-1:-1:-1;20753:18:3;;-1:-1:-1;20737:12:3;;:34;;;;;;;;:::i;:::-;;20733:227;;20796:157;20818:16;20846:64;20930:4;:12;;;20922:21;;;;;;;;:::i;20796:157::-;20781:172;;;;;;;20733:227;21029:11;;21075:22;;;;;21029:69;;-1:-1:-1;;;21029:69:3;;-1:-1:-1;;;;;21029:11:3;;;;:30;;:69;;21068:4;;21075:22;21029:69;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;21019:79;-1:-1:-1;21108:12:3;;21104:130;;21137:90;21148:27;21177:40;21219:7;21137:10;:90::i;21104:130::-;21279:35;21287:12;;21301;21279:7;:35::i;:::-;21255:20;;;21240:74;;;21241:4;21240:74;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;-1:-1:-1;21340:18:3;;-1:-1:-1;21324:12:3;;:34;;;;;;;;:::i;:::-;;21320:178;;21383:108;21394:16;21412:55;21477:4;:12;;;21469:21;;;;;;;;:::i;21320:178::-;21711:22;;;;;-1:-1:-1;;;;;21674:24:3;;;;;;:14;:24;;;;;;:59;;;21780:11;;21739:38;;;;:52;21812:20;;;;21797:12;:35;22168:37;21689:8;22192:12;22168:13;:37::i;:::-;22281:22;;;;;22305:20;;;;;22250:76;;-1:-1:-1;;;;;31884:32:19;;31866:51;;31948:2;31933:18;;31926:34;;;31976:18;;;31969:34;;;;32019:18;;32012:34;22250:76:3;;31853:3:19;31838:19;22250:76:3;;;;;;;22479:14;22464:30;19542:2957;-1:-1:-1;;;;;;19542:2957:3:o;29969:3464::-;30212:11;;:147;;-1:-1:-1;;;30212:147:3;;30130:7;;;;;;-1:-1:-1;;;;;30212:11:3;;:34;;:147;;30262:4;;30283:16;;30308:10;;30326:8;;30342:11;;30212:147;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;30194:165;-1:-1:-1;30369:12:3;;30365:138;;30399:93;30410:27;30439:43;30484:7;30399:10;:93::i;:::-;30494:1;30391:105;;;;;;;30365:138;30602:12;30580:18;;:34;30576:134;;30632:67;30637:22;30661:37;30632:4;:67::i;30576:134::-;30845:12;30804:16;-1:-1:-1;;;;;30804:35:3;;:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:53;30800:164;;30875:78;30880:22;30904:48;30875:4;:78::i;30800:164::-;31026:10;-1:-1:-1;;;;;31014:22:3;:8;-1:-1:-1;;;;;31014:22:3;;31010:133;;;31054:78;31059:26;31087:44;31054:4;:78::i;31010:133::-;31187:16;31183:135;;31221:86;31226:36;31264:42;31221:4;:86::i;31183:135::-;-1:-1:-1;;31363:11:3;:32;31359:155;;;31413:90;31418:36;31456:46;31413:4;:90::i;31359:155::-;31557:24;31583:25;31612:51;31629:10;31641:8;31651:11;31612:16;:51::i;:::-;31556:107;;-1:-1:-1;31556:107:3;-1:-1:-1;31673:43:3;;31669:154;;31734:78;31745:16;31739:23;;;;;;;;:::i;:::-;31764:47;31734:4;:78::i;:::-;31814:1;31726:90;;;;;;;;;31669:154;32059:11;;:126;;-1:-1:-1;;;32059:126:3;;32010:24;;;;-1:-1:-1;;;;;32059:11:3;;;;:41;;:126;;32116:4;;32137:16;;32162:17;;32059:126;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;32009:176;;-1:-1:-1;32009:176:3;-1:-1:-1;32199:43:3;;32191:107;;;;-1:-1:-1;;;32191:107:3;;32509:2:19;32191:107:3;;;32491:21:19;32548:2;32528:18;;;32521:30;32587:34;32567:18;;;32560:62;-1:-1:-1;;;32638:18:19;;;32631:49;32697:19;;32191:107:3;32307:415:19;32191:107:3;32457:11;32388:16;-1:-1:-1;;;;;32388:43:3;;:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;32388:55:3;;32444:8;32388:65;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:80;;32373:135;;;;-1:-1:-1;;;32373:135:3;;32929:2:19;32373:135:3;;;32911:21:19;32968:2;32948:18;;;32941:30;-1:-1:-1;;;32987:18:19;;;32980:54;33051:18;;32373:135:3;32727:348:19;32373:135:3;32626:18;-1:-1:-1;;;;;32654:42:3;;32691:4;32654:42;32650:230;;;32719:63;32741:4;32748:10;32760:8;32770:11;32719:13;:63::i;:::-;32706:76;;32650:230;;;32816:57;;-1:-1:-1;;;32816:57:3;;-1:-1:-1;;;;;32816:22:3;;;;;:57;;32839:10;;32851:8;;32861:11;;32816:57;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;32803:70;;32650:230;32975:37;;32967:56;;;;-1:-1:-1;;;32967:56:3;;33282:2:19;32967:56:3;;;33264:21:19;33321:1;33301:18;;;33294:29;-1:-1:-1;;;33339:18:19;;;33332:36;33385:18;;32967:56:3;33080:329:19;32967:56:3;33077:96;;;-1:-1:-1;;;;;33729:15:19;;;33711:34;;33781:15;;;33776:2;33761:18;;33754:43;33813:18;;;33806:34;;;33876:15;;33871:2;33856:18;;33849:43;33923:3;33908:19;;33901:35;;;33077:96:3;;;;;;;33660:3:19;33077:96:3;;;33393:14;33377:51;-1:-1:-1;33410:17:3;;-1:-1:-1;;;;;;29969:3464:3;;;;;;;;:::o;5994:673:1:-;6135:10;;6120:51;;-1:-1:-1;;;6120:51:1;;6081:7;;;;-1:-1:-1;;;;;6135:10:1;;;;6120:36;;:51;;6165:4;;6120:51;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;6096:75;;6177:179;6227:59;;;6288:4;6302;6309:6;6204:112;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;-1:-1:-1;;;;;6204:112:1;;;;;;;-1:-1:-1;;;;;6204:112:1;;;;;;;;;;;6177:179;;;;;;;;;;;;;-1:-1:-1;;;6177:179:1;;;:19;:179::i;:::-;6461:10;;6446:51;;-1:-1:-1;;;6446:51:1;;6423:20;;-1:-1:-1;;;;;6461:10:1;;6446:36;;:51;;6491:4;;6446:51;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;6423:74;;6527:13;6511:12;:29;;6503:68;;;;-1:-1:-1;;;6503:68:1;;34149:2:19;6503:68:1;;;34131:21:19;34188:2;34168:18;;;34161:30;-1:-1:-1;;;34207:18:19;;;34200:56;34273:18;;6503:68:1;33947:350:19;6503:68:1;6584:28;6599:13;6584:12;:28;:::i;4094:809:16:-;4171:27;4201:9;-1:-1:-1;;;;;4201:32:16;;:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;4201:34:16;;;;;;;;;;;;:::i;:::-;4171:64;;4241:23;4267:16;:14;:16::i;:::-;4241:42;;4294:8;4289:610;4312:11;:18;4308:1;:22;;;4289:610;;;4345:23;4371:11;4383:1;4371:14;;;;;;;;;;:::i;:::-;;;;;;;;;;;;-1:-1:-1;;;;;;4447:30:16;;:12;:30;;;;;;;;;;;:45;4371:14;;-1:-1:-1;;;;;;4425:67:16;;;4447:45;;4425:67;4418:75;;;;:::i;:::-;-1:-1:-1;;;;;;4615:30:16;;4594:18;4615:30;;;;;;;;;;:36;4693:18;;;;4712:25;;-1:-1:-1;;;4615:36:16;;;;;;4693:18;;4712:29;;;:::i;:::-;4693:49;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;4659:2;:18;;4678:11;4659:31;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;:83;;;;;;;;;;;;;;;;;;4804:11;4750:2;:12;;:45;4763:2;:18;;4782:11;4763:31;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;4750:45:16;;;;;;;;;;;;;:65;;-1:-1:-1;;;;4750:65:16;-1:-1:-1;;;4750:65:16;;;;;;;;;;;;;;;-1:-1:-1;4823:18:16;;:24;;;;;;;:::i;:::-;;;;;;;;;;-1:-1:-1;;4823:24:16;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;4862:30:16;;;;;;;;;-1:-1:-1;4862:30:16;;;4855:37;;-1:-1:-1;;;;;;4855:37:16;;;4332:3;;;;:::i;:::-;;;;4289:610;;4907:707;4981:24;5008:9;-1:-1:-1;;;;;5008:32:16;;:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;5008:34:16;;;;;;;;;;;;:::i;:::-;4981:61;;5048:23;5074:16;:14;:16::i;:::-;5126:18;;;:25;5048:42;;-1:-1:-1;5096:20:16;5158:452;5206:8;:15;5190:13;:31;5158:452;;;5248:15;5266:8;5275:13;5266:23;;;;;;;;:::i;:::-;;;;;;;;;;;;-1:-1:-1;;;;;;5325:22:16;;5297:25;5325:22;;;;;;;;;;;:37;5266:23;;-1:-1:-1;;;;;;5325:37:16;5374:31;;5370:93;;5414:49;;-1:-1:-1;;;5414:49:16;;-1:-1:-1;;;;;;35896:33:19;;5414:49:16;;;35878:52:19;-1:-1:-1;;;;;35966:32:19;;35946:18;;;35939:60;35851:18;;5414:49:16;35706:299:19;5370:93:16;5496:43;;;;;;;;-1:-1:-1;;;;;5496:43:16;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;5471:22:16;;-1:-1:-1;5471:22:16;;;;;;;;;:68;;;;;;;;;-1:-1:-1;;;5471:68:16;-1:-1:-1;;;;;;5471:68:16;;;;;;;;;;;;;;;;5547:18;;;:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5471:68;5547:33;;;;;;;;;;;;;;;;5525:13;5588:15;5525:13;5588:15;:::i;:::-;;;;5240:370;;5223:15;;;;;:::i;:::-;;;;5158:452;;2379:288:11;2459:9;2470:7;2486:13;2501:18;2523:20;2533:1;2536:6;2523:9;:20::i;:::-;2485:58;;-1:-1:-1;2485:58:11;-1:-1:-1;2560:18:11;2553:3;:25;;;;;;;;:::i;:::-;;2549:61;;-1:-1:-1;2596:3:11;-1:-1:-1;2601:1:11;;-1:-1:-1;2588:15:11;;2549:61;2624:18;2644:17;2653:7;2644:8;:17::i;:::-;2616:46;;;;;;2379:288;;;;;:::o;3834:312::-;3925:9;3936:7;3952:13;3967:19;3990:31;4005:6;4013:7;3990:14;:31::i;4796:123:12:-;4855:7;4877:37;4882:1;4885;4877:37;;;;;;;;;;;;;-1:-1:-1;;;4877:37:12;;;:4;:37::i;4095:130::-;4157:10;;:::i;:::-;4182:38;;;;;;;;4198:19;4203:1;:10;;;4215:1;4198:4;:19::i;:::-;4182:38;;4175:45;4095:130;-1:-1:-1;;;4095:130:12:o;814:203::-;989:12;;871:7;;989:23;;450:4;;989:23;:::i;1947:332:11:-;2019:9;2030:10;;:::i;:::-;2049:14;2065:22;2091:27;2099:1;:10;;;2111:6;2091:7;:27::i;:::-;2048:70;;-1:-1:-1;2048:70:11;-1:-1:-1;2136:18:11;2128:4;:26;;;;;;;;:::i;:::-;;2124:82;;-1:-1:-1;2178:20:11;;;;;;;;;-1:-1:-1;2178:20:11;;2172:4;;-1:-1:-1;2178:20:11;-1:-1:-1;2164:35:11;;2124:82;2240:33;;;;;;;;;;;;-1:-1:-1;;2240:33:11;;-1:-1:-1;1947:332:11;-1:-1:-1;;;;1947:332:11:o;3151:585::-;3234:9;3245:10;;:::i;:::-;3534:14;3550:17;3571:25;450:4:12;3589:6:11;3571:7;:25::i;:::-;3533:63;;-1:-1:-1;3533:63:11;-1:-1:-1;3614:18:11;3606:4;:26;;;;;;;;:::i;:::-;;3602:82;;-1:-1:-1;3656:20:11;;;;;;;;;-1:-1:-1;3656:20:11;;3650:4;;-1:-1:-1;3656:20:11;-1:-1:-1;3642:35:11;;3602:82;3696:35;3703:9;3714:7;:16;;;3696:6;:35::i;4923:243:12:-;5026:7;5045:6;;;:16;;-1:-1:-1;5055:6:12;;5045:16;5041:45;;;-1:-1:-1;5078:1:12;5071:8;;5041:45;5091:9;5103:5;5107:1;5103;:5;:::i;:::-;5091:17;-1:-1:-1;5131:1:12;5122:5;5126:1;5091:17;5122:5;:::i;:::-;:10;5134:12;5114:33;;;;;-1:-1:-1;;;5114:33:12;;;;;;;;:::i;799:479:11:-;866:9;877:10;;:::i;:::-;896:14;912:23;939:22;947:3;450:4:12;939:7:11;:22::i;:::-;895:66;;-1:-1:-1;895:66:11;-1:-1:-1;979:18:11;971:4;:26;;;;;;;;:::i;:::-;;967:82;;-1:-1:-1;1021:20:11;;;;;;;;;-1:-1:-1;1021:20:11;;1015:4;;-1:-1:-1;1021:20:11;-1:-1:-1;1007:35:11;;967:82;1056:14;1072:16;1092:31;1100:15;1117:5;1092:7;:31::i;:::-;1055:68;;-1:-1:-1;1055:68:11;-1:-1:-1;1141:18:11;1133:4;:26;;;;;;;;:::i;:::-;;1129:82;;1177:4;1183:20;;;;;;;;1199:1;1183:20;;;1169:35;;;;;;;;;;1129:82;1245:27;;;;;;;;;;;;-1:-1:-1;;1245:27:11;;-1:-1:-1;799:479:11;-1:-1:-1;;;;;;799:479:11:o;-1:-1:-1:-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;14:202:19;-1:-1:-1;;;;;;176:33:19;;;;158:52;;146:2;131:18;;14:202::o;221:131::-;-1:-1:-1;;;;;296:31:19;;286:42;;276:70;;342:1;339;332:12;357:142;433:20;;462:31;433:20;462:31;:::i;:::-;357:142;;;:::o;504:127::-;565:10;560:3;556:20;553:1;546:31;596:4;593:1;586:15;620:4;617:1;610:15;636:275;707:2;701:9;772:2;753:13;;-1:-1:-1;;749:27:19;737:40;;-1:-1:-1;;;;;792:34:19;;828:22;;;789:62;786:88;;;854:18;;:::i;:::-;890:2;883:22;636:275;;-1:-1:-1;636:275:19:o;916:187::-;965:4;-1:-1:-1;;;;;987:30:19;;984:56;;;1020:18;;:::i;:::-;-1:-1:-1;1086:2:19;1065:15;-1:-1:-1;;1061:29:19;1092:4;1057:40;;916:187::o;1108:338::-;1173:5;1202:53;1218:36;1247:6;1218:36;:::i;:::-;1202:53;:::i;:::-;1193:62;;1278:6;1271:5;1264:21;1318:3;1309:6;1304:3;1300:16;1297:25;1294:45;;;1335:1;1332;1325:12;1294:45;1384:6;1379:3;1372:4;1365:5;1361:16;1348:43;1438:1;1431:4;1422:6;1415:5;1411:18;1407:29;1400:40;1108:338;;;;;:::o;1451:222::-;1494:5;1547:3;1540:4;1532:6;1528:17;1524:27;1514:55;;1565:1;1562;1555:12;1514:55;1587:80;1663:3;1654:6;1641:20;1634:4;1626:6;1622:17;1587:80;:::i;1678:1305::-;1883:6;1891;1899;1907;1915;1923;1931;1939;1992:3;1980:9;1971:7;1967:23;1963:33;1960:53;;;2009:1;2006;1999:12;1960:53;2048:9;2035:23;2067:31;2092:5;2067:31;:::i;:::-;2117:5;-1:-1:-1;2174:2:19;2159:18;;2146:32;2187:33;2146:32;2187:33;:::i;:::-;2239:7;-1:-1:-1;2298:2:19;2283:18;;2270:32;2311:33;2270:32;2311:33;:::i;:::-;2363:7;-1:-1:-1;2422:2:19;2407:18;;2394:32;2435:33;2394:32;2435:33;:::i;:::-;2487:7;-1:-1:-1;2545:3:19;2530:19;;2517:33;-1:-1:-1;;;;;2599:14:19;;;2596:34;;;2626:1;2623;2616:12;2596:34;2649:50;2691:7;2682:6;2671:9;2667:22;2649:50;:::i;:::-;2639:60;;2752:3;2741:9;2737:19;2724:33;2708:49;;2782:2;2772:8;2769:16;2766:36;;;2798:1;2795;2788:12;2766:36;;2821:52;2865:7;2854:8;2843:9;2839:24;2821:52;:::i;:::-;2811:62;;;2920:3;2909:9;2905:19;2892:33;2882:43;;2972:3;2961:9;2957:19;2944:33;2934:43;;1678:1305;;;;;;;;;;;:::o;2988:258::-;3060:1;3070:113;3084:6;3081:1;3078:13;3070:113;;;3160:11;;;3154:18;3141:11;;;3134:39;3106:2;3099:10;3070:113;;;3201:6;3198:1;3195:13;3192:48;;;-1:-1:-1;;3236:1:19;3218:16;;3211:27;2988:258::o;3251:::-;3293:3;3331:5;3325:12;3358:6;3353:3;3346:19;3374:63;3430:6;3423:4;3418:3;3414:14;3407:4;3400:5;3396:16;3374:63;:::i;:::-;3491:2;3470:15;-1:-1:-1;;3466:29:19;3457:39;;;;3498:4;3453:50;;3251:258;-1:-1:-1;;3251:258:19:o;3514:220::-;3663:2;3652:9;3645:21;3626:4;3683:45;3724:2;3713:9;3709:18;3701:6;3683:45;:::i;3739:180::-;3798:6;3851:2;3839:9;3830:7;3826:23;3822:32;3819:52;;;3867:1;3864;3857:12;3819:52;-1:-1:-1;3890:23:19;;3739:180;-1:-1:-1;3739:180:19:o;4106:219::-;-1:-1:-1;;;;;4286:32:19;;;;4268:51;;4256:2;4241:18;;4106:219::o;4330:247::-;4389:6;4442:2;4430:9;4421:7;4417:23;4413:32;4410:52;;;4458:1;4455;4448:12;4410:52;4497:9;4484:23;4516:31;4541:5;4516:31;:::i;4582:114::-;4666:4;4659:5;4655:16;4648:5;4645:27;4635:55;;4686:1;4683;4676:12;4701:130;4767:20;;4796:29;4767:20;4796:29;:::i;4836:1244::-;5048:6;5056;5064;5072;5080;5088;5096;5104;5112;5165:3;5153:9;5144:7;5140:23;5136:33;5133:53;;;5182:1;5179;5172:12;5133:53;5221:9;5208:23;5240:31;5265:5;5240:31;:::i;:::-;5290:5;-1:-1:-1;5347:2:19;5332:18;;5319:32;5360:33;5319:32;5360:33;:::i;:::-;5412:7;-1:-1:-1;5438:46:19;5480:2;5465:18;;5438:46;:::i;:::-;5428:56;-1:-1:-1;5531:2:19;5516:18;;5503:32;;-1:-1:-1;5586:3:19;5571:19;;5558:33;-1:-1:-1;;;;;5640:14:19;;;5637:34;;;5667:1;5664;5657:12;5637:34;5690:50;5732:7;5723:6;5712:9;5708:22;5690:50;:::i;:::-;5680:60;;5793:3;5782:9;5778:19;5765:33;5749:49;;5823:2;5813:8;5810:16;5807:36;;;5839:1;5836;5829:12;5807:36;;5862:52;5906:7;5895:8;5884:9;5880:24;5862:52;:::i;:::-;5852:62;;;5933:37;5965:3;5954:9;5950:19;5933:37;:::i;:::-;5923:47;;6017:3;6006:9;6002:19;5989:33;5979:43;;6069:3;6058:9;6054:19;6041:33;6031:43;;4836:1244;;;;;;;;;;;:::o;6085:315::-;6153:6;6161;6214:2;6202:9;6193:7;6189:23;6185:32;6182:52;;;6230:1;6227;6220:12;6182:52;6269:9;6256:23;6288:31;6313:5;6288:31;:::i;:::-;6338:5;6390:2;6375:18;;;;6362:32;;-1:-1:-1;;;6085:315:19:o;6594:118::-;6680:5;6673:13;6666:21;6659:5;6656:32;6646:60;;6702:1;6699;6692:12;6717:861;6802:6;6810;6818;6826;6879:2;6867:9;6858:7;6854:23;6850:32;6847:52;;;6895:1;6892;6885:12;6847:52;6934:9;6921:23;6953:31;6978:5;6953:31;:::i;:::-;7003:5;-1:-1:-1;7060:2:19;7045:18;;7032:32;7073:30;7032:32;7073:30;:::i;:::-;7122:7;-1:-1:-1;7180:2:19;7165:18;;7152:32;-1:-1:-1;;;;;7233:14:19;;;7230:34;;;7260:1;7257;7250:12;7230:34;7298:6;7287:9;7283:22;7273:32;;7343:7;7336:4;7332:2;7328:13;7324:27;7314:55;;7365:1;7362;7355:12;7314:55;7405:2;7392:16;7431:2;7423:6;7420:14;7417:34;;;7447:1;7444;7437:12;7417:34;7492:7;7487:2;7478:6;7474:2;7470:15;7466:24;7463:37;7460:57;;;7513:1;7510;7503:12;7460:57;6717:861;;;;-1:-1:-1;;7544:2:19;7536:11;;-1:-1:-1;;;6717:861:19:o;7583:450::-;7651:6;7704:2;7692:9;7683:7;7679:23;7675:32;7672:52;;;7720:1;7717;7710:12;7672:52;7747:23;;-1:-1:-1;;;;;7782:30:19;;7779:50;;;7825:1;7822;7815:12;7779:50;7848:22;;7901:4;7893:13;;7889:27;-1:-1:-1;7879:55:19;;7930:1;7927;7920:12;7879:55;7953:74;8019:7;8014:2;8001:16;7996:2;7992;7988:11;7953:74;:::i;8483:658::-;8654:2;8706:21;;;8776:13;;8679:18;;;8798:22;;;8625:4;;8654:2;8877:15;;;;8851:2;8836:18;;;8625:4;8920:195;8934:6;8931:1;8928:13;8920:195;;;8999:13;;-1:-1:-1;;;;;8995:39:19;8983:52;;9090:15;;;;9055:12;;;;9031:1;8949:9;8920:195;;;-1:-1:-1;9132:3:19;;8483:658;-1:-1:-1;;;;;;8483:658:19:o;9146:438::-;9264:6;9272;9325:2;9313:9;9304:7;9300:23;9296:32;9293:52;;;9341:1;9338;9331:12;9293:52;9380:9;9367:23;9399:31;9424:5;9399:31;:::i;:::-;9449:5;-1:-1:-1;9506:2:19;9491:18;;9478:32;9519:33;9478:32;9519:33;:::i;:::-;9571:7;9561:17;;;9146:438;;;;;:::o;10022:626::-;10119:6;10127;10180:2;10168:9;10159:7;10155:23;10151:32;10148:52;;;10196:1;10193;10186:12;10148:52;10223:23;;-1:-1:-1;;;;;10295:14:19;;;10292:34;;;10322:1;10319;10312:12;10292:34;10360:6;10349:9;10345:22;10335:32;;10405:7;10398:4;10394:2;10390:13;10386:27;10376:55;;10427:1;10424;10417:12;10376:55;10467:2;10454:16;10493:2;10485:6;10482:14;10479:34;;;10509:1;10506;10499:12;10479:34;10562:7;10557:2;10547:6;10544:1;10540:14;10536:2;10532:23;10528:32;10525:45;10522:65;;;10583:1;10580;10573:12;10522:65;10614:2;10606:11;;;;;10636:6;;-1:-1:-1;10022:626:19;;-1:-1:-1;;;;10022:626:19:o;10653:801::-;10813:4;10842:2;10882;10871:9;10867:18;10912:2;10901:9;10894:21;10935:6;10970;10964:13;11001:6;10993;10986:22;11039:2;11028:9;11024:18;11017:25;;11101:2;11091:6;11088:1;11084:14;11073:9;11069:30;11065:39;11051:53;;11139:2;11131:6;11127:15;11160:1;11170:255;11184:6;11181:1;11178:13;11170:255;;;11277:2;11273:7;11261:9;11253:6;11249:22;11245:36;11240:3;11233:49;11305:40;11338:6;11329;11323:13;11305:40;:::i;:::-;11295:50;-1:-1:-1;11403:12:19;;;;11368:15;;;;11206:1;11199:9;11170:255;;;-1:-1:-1;11442:6:19;;10653:801;-1:-1:-1;;;;;;;10653:801:19:o;11459:456::-;11536:6;11544;11552;11605:2;11593:9;11584:7;11580:23;11576:32;11573:52;;;11621:1;11618;11611:12;11573:52;11660:9;11647:23;11679:31;11704:5;11679:31;:::i;:::-;11729:5;-1:-1:-1;11786:2:19;11771:18;;11758:32;11799:33;11758:32;11799:33;:::i;:::-;11459:456;;11851:7;;-1:-1:-1;;;11905:2:19;11890:18;;;;11877:32;;11459:456::o;12550:480::-;12651:6;12659;12667;12720:2;12708:9;12699:7;12695:23;12691:32;12688:52;;;12736:1;12733;12726:12;12688:52;12775:9;12762:23;12794:31;12819:5;12794:31;:::i;:::-;12844:5;-1:-1:-1;12896:2:19;12881:18;;12868:32;;-1:-1:-1;12952:2:19;12937:18;;12924:32;12965:33;12924:32;12965:33;:::i;:::-;13017:7;13007:17;;;12550:480;;;;;:::o;13035:247::-;13103:6;13156:2;13144:9;13135:7;13131:23;13127:32;13124:52;;;13172:1;13169;13162:12;13124:52;13204:9;13198:16;13223:29;13246:5;13223:29;:::i;13287:184::-;13357:6;13410:2;13398:9;13389:7;13385:23;13381:32;13378:52;;;13426:1;13423;13416:12;13378:52;-1:-1:-1;13449:16:19;;13287:184;-1:-1:-1;13287:184:19:o;13476:380::-;13555:1;13551:12;;;;13598;;;13619:61;;13673:4;13665:6;13661:17;13651:27;;13619:61;13726:2;13718:6;13715:14;13695:18;13692:38;13689:161;;;13772:10;13767:3;13763:20;13760:1;13753:31;13807:4;13804:1;13797:15;13835:4;13832:1;13825:15;13861:127;13922:10;13917:3;13913:20;13910:1;13903:31;13953:4;13950:1;13943:15;13977:4;13974:1;13967:15;14337:245;14404:6;14457:2;14445:9;14436:7;14432:23;14428:32;14425:52;;;14473:1;14470;14463:12;14425:52;14505:9;14499:16;14524:28;14546:5;14524:28;:::i;14587:308::-;14662:5;14691:53;14707:36;14736:6;14707:36;:::i;14691:53::-;14682:62;;14767:6;14760:5;14753:21;14807:3;14798:6;14793:3;14789:16;14786:25;14783:45;;;14824:1;14821;14814:12;14783:45;14837:52;14882:6;14875:4;14868:5;14864:16;14859:3;14837:52;:::i;14900:713::-;14994:6;15002;15010;15063:2;15051:9;15042:7;15038:23;15034:32;15031:52;;;15079:1;15076;15069:12;15031:52;15111:9;15105:16;15130:31;15155:5;15130:31;:::i;:::-;15230:2;15215:18;;15209:25;15180:5;;-1:-1:-1;15243:30:19;15209:25;15243:30;:::i;:::-;15343:2;15328:18;;15322:25;15292:7;;-1:-1:-1;;;;;;15359:30:19;;15356:50;;;15402:1;15399;15392:12;15356:50;15425:22;;15478:4;15470:13;;15466:27;-1:-1:-1;15456:55:19;;15507:1;15504;15497:12;15456:55;15530:77;15599:7;15594:2;15588:9;15583:2;15579;15575:11;15530:77;:::i;:::-;15520:87;;;14900:713;;;;;:::o;15618:329::-;15820:2;15802:21;;;15859:1;15839:18;;;15832:29;-1:-1:-1;;;15892:2:19;15877:18;;15870:36;15938:2;15923:18;;15618:329::o;16972:356::-;-1:-1:-1;;;;;17254:15:19;;;17236:34;;17306:15;;17301:2;17286:18;;17279:43;17186:2;17171:18;;16972:356::o;17333:127::-;17394:10;17389:3;17385:20;17382:1;17375:31;17425:4;17422:1;17415:15;17449:4;17446:1;17439:15;17465:128;17505:3;17536:1;17532:6;17529:1;17526:13;17523:39;;;17542:18;;:::i;:::-;-1:-1:-1;17578:9:19;;17465:128::o;19958:125::-;19998:4;20026:1;20023;20020:8;20017:34;;;20031:18;;:::i;:::-;-1:-1:-1;20068:9:19;;19958:125::o;20088:251::-;20158:6;20211:2;20199:9;20190:7;20186:23;20182:32;20179:52;;;20227:1;20224;20217:12;20179:52;20259:9;20253:16;20278:31;20303:5;20278:31;:::i;20344:127::-;20405:10;20400:3;20396:20;20393:1;20386:31;20436:4;20433:1;20426:15;20460:4;20457:1;20450:15;20476:521;20553:4;20559:6;20619:11;20606:25;20713:2;20709:7;20698:8;20682:14;20678:29;20674:43;20654:18;20650:68;20640:96;;20732:1;20729;20722:12;20640:96;20759:33;;20811:20;;;-1:-1:-1;;;;;;20843:30:19;;20840:50;;;20886:1;20883;20876:12;20840:50;20919:4;20907:17;;-1:-1:-1;20950:14:19;20946:27;;;20936:38;;20933:58;;;20987:1;20984;20977:12;21002:271;21185:6;21177;21172:3;21159:33;21141:3;21211:16;;21236:13;;;21211:16;21002:271;-1:-1:-1;21002:271:19:o;21278:458::-;21358:6;21411:2;21399:9;21390:7;21386:23;21382:32;21379:52;;;21427:1;21424;21417:12;21379:52;21454:16;;-1:-1:-1;;;;;21482:30:19;;21479:50;;;21525:1;21522;21515:12;21479:50;21548:22;;21601:4;21593:13;;21589:27;-1:-1:-1;21579:55:19;;21630:1;21627;21620:12;21579:55;21653:77;21722:7;21717:2;21711:9;21706:2;21702;21698:11;21653:77;:::i;21741:135::-;21780:3;-1:-1:-1;;21801:17:19;;21798:43;;;21821:18;;:::i;:::-;-1:-1:-1;21868:1:19;21857:13;;21741:135::o;22220:385::-;-1:-1:-1;;;;;22472:15:19;;;22454:34;;22524:15;;;;22519:2;22504:18;;22497:43;22583:14;;22576:22;22571:2;22556:18;;22549:50;22404:2;22389:18;;22220:385::o;22943:183::-;23003:4;-1:-1:-1;;;;;23025:30:19;;23022:56;;;23058:18;;:::i;:::-;-1:-1:-1;23103:1:19;23099:14;23115:4;23095:25;;22943:183::o;23131:956::-;23226:6;23257:2;23300;23288:9;23279:7;23275:23;23271:32;23268:52;;;23316:1;23313;23306:12;23268:52;23343:16;;-1:-1:-1;;;;;23371:30:19;;23368:50;;;23414:1;23411;23404:12;23368:50;23437:22;;23490:4;23482:13;;23478:27;-1:-1:-1;23468:55:19;;23519:1;23516;23509:12;23468:55;23548:2;23542:9;23571:60;23587:43;23627:2;23587:43;:::i;23571:60::-;23665:15;;;23747:1;23743:10;;;;23735:19;;23731:28;;;23696:12;;;;23771:19;;;23768:39;;;23803:1;23800;23793:12;23768:39;23827:11;;;;23847:210;23863:6;23858:3;23855:15;23847:210;;;23936:3;23930:10;23953:31;23978:5;23953:31;:::i;:::-;23997:18;;23880:12;;;;24035;;;;23847:210;;;24076:5;23131:956;-1:-1:-1;;;;;;;23131:956:19:o;24624:217::-;24664:1;24690;24680:132;;24734:10;24729:3;24725:20;24722:1;24715:31;24769:4;24766:1;24759:15;24797:4;24794:1;24787:15;24680:132;-1:-1:-1;24826:9:19;;24624:217::o;24846:327::-;25056:25;;;25112:2;25097:18;;25090:34;;;;25155:2;25140:18;;25133:34;25044:2;25029:18;;24846:327::o;25178:274::-;-1:-1:-1;;;;;25370:32:19;;;;25352:51;;25434:2;25419:18;;25412:34;25340:2;25325:18;;25178:274::o;25457:537::-;-1:-1:-1;;;;;25772:15:19;;;25754:34;;25824:15;;;25819:2;25804:18;;25797:43;25876:15;;;25871:2;25856:18;;25849:43;25928:15;;;25923:2;25908:18;;25901:43;25975:3;25960:19;;25953:35;;;;25703:3;25688:19;;25457:537::o;25999:345::-;-1:-1:-1;;;;;26219:32:19;;;;26201:51;;26283:2;26268:18;;26261:34;;;;26326:2;26311:18;;26304:34;26189:2;26174:18;;25999:345::o;28468:127::-;28529:10;28524:3;28520:20;28517:1;28510:31;28560:4;28557:1;28550:15;28584:4;28581:1;28574:15;28600:175;28637:3;28681:4;28674:5;28670:16;28710:4;28701:7;28698:17;28695:43;;;28718:18;;:::i;:::-;28767:1;28754:15;;28600:175;-1:-1:-1;;28600:175:19:o;29132:274::-;29261:3;29299:6;29293:13;29315:53;29361:6;29356:3;29349:4;29341:6;29337:17;29315:53;:::i;:::-;29384:16;;;;;29132:274;-1:-1:-1;;29132:274:19:o;29763:375::-;-1:-1:-1;;;;;30021:15:19;;;30003:34;;30073:15;;;;30068:2;30053:18;;30046:43;30120:2;30105:18;;30098:34;;;;29953:2;29938:18;;29763:375::o;32057:245::-;32136:6;32144;32197:2;32185:9;32176:7;32172:23;32168:32;32165:52;;;32213:1;32210;32203:12;32165:52;-1:-1:-1;;32236:16:19;;32292:2;32277:18;;;32271:25;32236:16;;32271:25;;-1:-1:-1;32057:245:19:o;34302:1065::-;34396:6;34427:2;34470;34458:9;34449:7;34445:23;34441:32;34438:52;;;34486:1;34483;34476:12;34438:52;34513:16;;-1:-1:-1;;;;;34541:30:19;;34538:50;;;34584:1;34581;34574:12;34538:50;34607:22;;34660:4;34652:13;;34648:27;-1:-1:-1;34638:55:19;;34689:1;34686;34679:12;34638:55;34718:2;34712:9;34741:60;34757:43;34797:2;34757:43;:::i;34741:60::-;34835:15;;;34917:1;34913:10;;;;34905:19;;34901:28;;;34866:12;;;;34941:19;;;34938:39;;;34973:1;34970;34963:12;34938:39;34997:11;;;;35017:320;35033:6;35028:3;35025:15;35017:320;;;35100:10;;-1:-1:-1;;;;;;35143:32:19;;35133:43;;35123:141;;35218:1;35247:2;35243;35236:14;35123:141;35277:18;;35050:12;;;;35315;;;;35017:320;;35372:127;35433:10;35428:3;35424:20;35421:1;35414:31;35464:4;35461:1;35454:15;35488:4;35485:1;35478:15;35504:197;35542:3;35570:6;35611:2;35604:5;35600:14;35638:2;35629:7;35626:15;35623:41;;;35644:18;;:::i;:::-;35693:1;35680:15;;35504:197;-1:-1:-1;;;35504:197:19:o;36010:168::-;36050:7;36116:1;36112;36108:6;36104:14;36101:1;36098:21;36093:1;36086:9;36079:17;36075:45;36072:71;;;36123:18;;:::i;:::-;-1:-1:-1;36163:9:19;;36010:168::o
Swarm Source
none
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in GLMR
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.