Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
0x60806040 | 14200812 | 1004 days ago | IN | 0 ETH | 0.80372205 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
CErc20PluginDelegate
Compiler Version
v0.5.17+commit.d19bba13
Contract Source Code (Solidity Standard Json-Input format)
pragma solidity ^0.5.16; pragma experimental ABIEncoderV2; import "./CErc20Delegate.sol"; import "./EIP20Interface.sol"; import "./IERC4626Draft.sol"; /** * @title Rari's CErc20Plugin's Contract * @notice CToken which outsources token logic to a plugin * @author Joey Santoro * * CErc20PluginDelegate deposits and withdraws from a plugin conract * It is also capable of delegating reward functionality to a PluginRewardsDistributor */ contract CErc20PluginDelegate is CErc20Delegate { /** * @notice Plugin address */ IERC4626Draft public plugin; uint256 constant public PRECISION = 1e18; /** * @notice Delegate interface to become the implementation * @param data The encoded arguments for becoming */ function _becomeImplementation(bytes calldata data) external { require(msg.sender == address(this) || hasAdminRights()); (address _plugin) = abi.decode( data, (address) ); require(_plugin != address(0), "0 addr"); if (address(plugin) != address(0)) { plugin.redeem(plugin.balanceOf(address(this)), address(this), address(this)); } plugin = IERC4626Draft(_plugin); EIP20Interface(underlying).approve(_plugin, uint256(-1)); uint256 amount = EIP20Interface(underlying).balanceOf(address(this)); if (amount != 0) { deposit(amount); } } /*** CToken Overrides ***/ /*** Safe Token ***/ /** * @notice Gets balance of the plugin in terms of the underlying * @return The quantity of underlying tokens owned by this contract */ function getCashPrior() internal view returns (uint256) { return plugin.assetsOf(address(this)); } /** * @notice Transfer the underlying to the cToken and trigger a deposit * @param from Address to transfer funds from * @param amount Amount of underlying to transfer * @return The actual amount that is transferred */ function doTransferIn( address from, uint256 amount ) internal returns (uint256) { // Perform the EIP-20 transfer in require(EIP20Interface(underlying).transferFrom(from, address(this), amount), "send fail"); deposit(amount); return amount; } function deposit(uint256 amount) internal { plugin.deposit(amount, address(this)); } /** * @notice Transfer the underlying from plugin to destination * @param to Address to transfer funds to * @param amount Amount of underlying to transfer */ function doTransferOut( address payable to, uint256 amount ) internal { plugin.withdraw(amount, to, address(this)); } }
pragma solidity ^0.5.16; import "./CErc20.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 Construct an empty delegate */ constructor() public {} /** * @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 calldata data) external { // Shh -- currently unused data; // Shh -- we don't ever want this hook to be marked pure if (false) { implementation = address(0); } require(msg.sender == address(this) || hasAdminRights(), "!self"); // Make sure admin storage is set up correctly __admin = address(0); __adminHasRights = false; __fuseAdminHasRights = false; } /** * @notice Called by the delegator on a delegate to forfeit its responsibility */ function _resignImplementation() internal { // 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(fuseAdmin.cErc20DelegateWhitelist(implementation, implementation_, allowResign), "!impl"); // Call _resignImplementation internally (this delegate's code) if (allowResign) _resignImplementation(); // Get old implementation address oldImplementation = implementation; // Store new implementation implementation = implementation_; // Call _becomeImplementation externally (delegating to new delegate's code) _functionCall(address(this), abi.encodeWithSignature("_becomeImplementation(bytes)", becomeImplementationData), "!become"); // Emit event 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 { // Check admin rights require(hasAdminRights(), "!admin"); // Set 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 { if (msg.sender != address(this) && ComptrollerV3Storage(address(comptroller)).autoImplementation()) { (address latestCErc20Delegate, bool allowResign, bytes memory becomeImplementationData) = fuseAdmin.latestCErc20Delegate(implementation); if (implementation != latestCErc20Delegate) _setImplementationInternal(latestCErc20Delegate, allowResign, becomeImplementationData); } } }
pragma solidity ^0.5.16; import "./CToken.sol"; interface CompLike { function delegate(address delegatee) external; } /** * @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 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_, 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_, 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(uint mintAmount) external returns (uint) { (uint 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(uint redeemTokens) external returns (uint) { 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(uint redeemAmount) external returns (uint) { 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(uint borrowAmount) external returns (uint) { 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(uint repayAmount) external returns (uint) { (uint 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, uint repayAmount) external returns (uint) { (uint 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, uint repayAmount, CTokenInterface cTokenCollateral) external returns (uint) { (uint 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 returns (uint) { EIP20Interface token = EIP20Interface(underlying); return token.balanceOf(address(this)); } /** * @dev Similar to EIP20 transfer, except it handles a False result from `transferFrom` and reverts in that case. * This will revert due to insufficient balance or insufficient allowance. * This function returns the actual amount received, * which may be less than `amount` if there is a fee attached to the transfer. * * Note: This wrapper safely handles non-standard ERC-20 tokens that do not return a value. * See here: https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca */ function doTransferIn(address from, uint amount) internal returns (uint) { uint 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 uint 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 payable to, uint amount) internal { _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); } /** * @notice Admin call to delegate the votes of the COMP-like underlying * @param compLikeDelegatee The address to delegate votes to * @dev CTokens whose underlying are not CompLike should revert here */ function _delegateCompLikeTo(address compLikeDelegatee) external { require(hasAdminRights(), "!admin"); CompLike(underlying).delegate(compLikeDelegatee); } }
pragma solidity ^0.5.16; import "./ComptrollerInterface.sol"; import "./CTokenInterfaces.sol"; import "./ErrorReporter.sol"; import "./Exponential.sol"; import "./EIP20Interface.sol"; import "./EIP20NonStandardInterface.sol"; import "./InterestRateModel.sol"; /** * @title Compound's CToken Contract * @notice Abstract base for CTokens * @author Compound */ contract CToken is CTokenInterface, Exponential, TokenErrorReporter { /** * @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 interestRateModel_ The address of the interest rate model * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18 * @param name_ EIP-20 name of this token * @param symbol_ EIP-20 symbol of this token * @param decimals_ EIP-20 decimal precision of this token */ function initialize(ComptrollerInterface comptroller_, InterestRateModel interestRateModel_, uint initialExchangeRateMantissa_, string memory name_, string memory symbol_, uint8 decimals_, uint256 reserveFactorMantissa_, uint256 adminFeeMantissa_) public { require(msg.sender == address(fuseAdmin), "!admin"); require(accrualBlockNumber == 0 && borrowIndex == 0, "init"); // Set initial exchange rate initialExchangeRateMantissa = initialExchangeRateMantissa_; require(initialExchangeRateMantissa > 0, "zero rate"); // Set the comptroller uint err = _setComptroller(comptroller_); require(err == uint(Error.NO_ERROR), "comptroller"); // Initialize block number and borrow index (block number mocks depend on comptroller being set) accrualBlockNumber = getBlockNumber(); borrowIndex = mantissaOne; // Set the interest rate model (depends on block number / borrow index) err = _setInterestRateModelFresh(interestRateModel_); require(err == uint(Error.NO_ERROR), "irm"); name = name_; symbol = symbol_; decimals = decimals_; // Set reserve factor err = _setReserveFactorFresh(reserveFactorMantissa_); require(err == uint(Error.NO_ERROR), "reserve factor"); // Set admin fee err = _setAdminFeeFresh(adminFeeMantissa_); require(err == uint(Error.NO_ERROR), "fee"); // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund) _notEntered = true; } /** * @dev Returns latest pending Fuse fee (to be set with `_setFuseFeeFresh`) */ function getPendingFuseFeeFromAdmin() internal view returns (uint) { return fuseAdmin.interestFeeRate(); } /** * @notice Transfer `tokens` tokens from `src` to `dst` by `spender` * @dev Called by both `transfer` and `transferFrom` internally * @param spender The address of the account performing the transfer * @param src The address of the source account * @param dst The address of the destination account * @param tokens The number of tokens to transfer * @return Whether or not the transfer succeeded */ function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) { /* Fail if transfer not allowed */ uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens); if (allowed != 0) { return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed); } /* Do not allow self-transfers */ if (src == dst) { return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED); } /* Get the allowance, infinite for the account owner */ uint startingAllowance = 0; if (spender == src) { startingAllowance = uint(-1); } else { startingAllowance = transferAllowances[src][spender]; } /* Do the calculations, checking for {under,over}flow */ MathError mathErr; uint allowanceNew; uint srcTokensNew; uint dstTokensNew; (mathErr, allowanceNew) = subUInt(startingAllowance, tokens); if (mathErr != MathError.NO_ERROR) { return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ALLOWED); } (mathErr, srcTokensNew) = subUInt(accountTokens[src], tokens); if (mathErr != MathError.NO_ERROR) { return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ENOUGH); } (mathErr, dstTokensNew) = addUInt(accountTokens[dst], tokens); if (mathErr != MathError.NO_ERROR) { return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_TOO_MUCH); } ///////////////////////// // EFFECTS & INTERACTIONS // (No safe failures beyond this point) accountTokens[src] = srcTokensNew; accountTokens[dst] = dstTokensNew; /* Eat some of the allowance (if necessary) */ if (startingAllowance != uint(-1)) { transferAllowances[src][spender] = allowanceNew; } /* We emit a Transfer event */ emit Transfer(src, dst, tokens); /* We call the defense hook */ // unused function // comptroller.transferVerify(address(this), src, dst, tokens); return uint(Error.NO_ERROR); } /** * @notice Transfer `amount` tokens from `msg.sender` to `dst` * @param dst The address of the destination account * @param amount The number of tokens to transfer * @return Whether or not the transfer succeeded */ function transfer(address dst, uint256 amount) external nonReentrant(false) returns (bool) { return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR); } /** * @notice Transfer `amount` tokens from `src` to `dst` * @param src The address of the source account * @param dst The address of the destination account * @param amount The number of tokens to transfer * @return Whether or not the transfer succeeded */ function transferFrom(address src, address dst, uint256 amount) external nonReentrant(false) returns (bool) { return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR); } /** * @notice Approve `spender` to transfer up to `amount` from `src` * @dev This will overwrite the approval amount for `spender` * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve) * @param spender The address of the account which may transfer tokens * @param amount The number of tokens that are approved (-1 means infinite) * @return Whether or not the approval succeeded */ function approve(address spender, uint256 amount) external returns (bool) { address src = msg.sender; transferAllowances[src][spender] = amount; emit Approval(src, spender, amount); return true; } /** * @notice Get the current allowance from `owner` for `spender` * @param owner The address of the account which owns the tokens to be spent * @param spender The address of the account which may transfer tokens * @return The number of tokens allowed to be spent (-1 means infinite) */ function allowance(address owner, address spender) external view returns (uint256) { return transferAllowances[owner][spender]; } /** * @notice Get the token balance of the `owner` * @param owner The address of the account to query * @return The number of tokens owned by `owner` */ function balanceOf(address owner) external view returns (uint256) { return accountTokens[owner]; } /** * @notice Get the underlying balance of the `owner` * @dev This also accrues interest in a transaction * @param owner The address of the account to query * @return The amount of underlying owned by `owner` */ function balanceOfUnderlying(address owner) external returns (uint) { Exp memory exchangeRate = Exp({mantissa: exchangeRateCurrent()}); (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]); require(mErr == MathError.NO_ERROR, "bal"); return balance; } /** * @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 returns (uint, uint, uint, uint) { uint cTokenBalance = accountTokens[account]; uint borrowBalance; uint exchangeRateMantissa; MathError mErr; (mErr, borrowBalance) = borrowBalanceStoredInternal(account); if (mErr != MathError.NO_ERROR) { return (uint(Error.MATH_ERROR), 0, 0, 0); } (mErr, exchangeRateMantissa) = exchangeRateStoredInternal(); if (mErr != MathError.NO_ERROR) { return (uint(Error.MATH_ERROR), 0, 0, 0); } return (uint(Error.NO_ERROR), cTokenBalance, borrowBalance, exchangeRateMantissa); } /** * @dev Function to simply retrieve block number * This exists mainly for inheriting test contracts to stub this result. */ function getBlockNumber() internal view returns (uint) { return block.number; } /** * @notice Returns the current per-block borrow interest rate for this cToken * @return The borrow interest rate per block, scaled by 1e18 */ function borrowRatePerBlock() external view returns (uint) { return interestRateModel.getBorrowRate(getCashPrior(), totalBorrows, add_(totalReserves, add_(totalAdminFees, totalFuseFees))); } /** * @notice Returns the current per-block supply interest rate for this cToken * @return The supply interest rate per block, scaled by 1e18 */ function supplyRatePerBlock() external view returns (uint) { return interestRateModel.getSupplyRate(getCashPrior(), totalBorrows, add_(totalReserves, add_(totalAdminFees, totalFuseFees)), reserveFactorMantissa + fuseFeeMantissa + adminFeeMantissa); } /** * @notice Returns the current total borrows plus accrued interest * @return The total borrows with interest */ function totalBorrowsCurrent() external nonReentrant(false) returns (uint) { require(accrueInterest() == uint(Error.NO_ERROR), "acc"); return totalBorrows; } /** * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex * @param account The address whose balance should be calculated after updating borrowIndex * @return The calculated balance */ function borrowBalanceCurrent(address account) external nonReentrant(false) returns (uint) { require(accrueInterest() == uint(Error.NO_ERROR), "acc"); 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 returns (uint) { (MathError err, uint result) = borrowBalanceStoredInternal(account); require(err == MathError.NO_ERROR, "borrowBal"); return result; } /** * @notice Return the borrow balance of account based on stored data * @param account The address whose balance should be calculated * @return (error code, the calculated balance or 0 if error code is non-zero) */ function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) { /* Note: we do not assert that the market is up to date */ MathError mathErr; uint principalTimesIndex; uint 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 (MathError.NO_ERROR, 0); } /* Calculate new borrow balance using the interest index: * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex */ (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex); if (mathErr != MathError.NO_ERROR) { return (mathErr, 0); } (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex); if (mathErr != MathError.NO_ERROR) { return (mathErr, 0); } return (MathError.NO_ERROR, result); } /** * @notice Accrue interest then return the up-to-date exchange rate * @return Calculated exchange rate scaled by 1e18 */ function exchangeRateCurrent() public nonReentrant(false) returns (uint) { require(accrueInterest() == uint(Error.NO_ERROR), "acc"); return exchangeRateStored(); } /** * @notice Calculates the exchange rate from the underlying to the CToken * @dev This function does not accrue interest before calculating the exchange rate * @return Calculated exchange rate scaled by 1e18 */ function exchangeRateStored() public view returns (uint) { (MathError err, uint result) = exchangeRateStoredInternal(); require(err == MathError.NO_ERROR, "exRate"); return result; } /** * @notice Calculates the exchange rate from the underlying to the CToken * @dev This function does not accrue interest before calculating the exchange rate * @return (error code, calculated exchange rate scaled by 1e18) */ function exchangeRateStoredInternal() internal view returns (MathError, uint) { uint _totalSupply = totalSupply; if (_totalSupply == 0) { /* * If there are no tokens minted: * exchangeRate = initialExchangeRate */ return (MathError.NO_ERROR, initialExchangeRateMantissa); } else { /* * Otherwise: * exchangeRate = (totalCash + totalBorrows - (totalReserves + totalFuseFees + totalAdminFees)) / totalSupply */ uint totalCash = getCashPrior(); uint cashPlusBorrowsMinusReserves; Exp memory exchangeRate; MathError mathErr; (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, add_(totalReserves, add_(totalAdminFees, totalFuseFees))); if (mathErr != MathError.NO_ERROR) { return (mathErr, 0); } (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply); if (mathErr != MathError.NO_ERROR) { return (mathErr, 0); } return (MathError.NO_ERROR, exchangeRate.mantissa); } } /** * @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 returns (uint) { return getCashPrior(); } /** * @notice Applies accrued interest to total borrows and reserves * @dev This calculates interest accrued from the last checkpointed block * up to the current block and writes new checkpoint to storage. */ function accrueInterest() public returns (uint) { /* Remember the initial block number */ uint currentBlockNumber = getBlockNumber(); /* Short-circuit accumulating 0 interest */ if (accrualBlockNumber == currentBlockNumber) { return uint(Error.NO_ERROR); } /* Read the previous values out of storage */ uint cashPrior = getCashPrior(); /* Calculate the current borrow interest rate */ uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, totalBorrows, add_(totalReserves, add_(totalAdminFees, totalFuseFees))); require(borrowRateMantissa <= borrowRateMaxMantissa, "bor"); /* Calculate the number of blocks elapsed since the last accrual */ (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumber); require(mathErr == MathError.NO_ERROR, "sub"); return finishInterestAccrual(currentBlockNumber, cashPrior, borrowRateMantissa, blockDelta); } /** * @dev Split off from `accrueInterest` to avoid "stack too deep" error". */ function finishInterestAccrual(uint currentBlockNumber, uint cashPrior, uint borrowRateMantissa, uint blockDelta) private returns (uint) { /* * Calculate the interest accumulated into borrows and reserves and the new index: * simpleInterestFactor = borrowRate * blockDelta * interestAccumulated = simpleInterestFactor * totalBorrows * totalBorrowsNew = interestAccumulated + totalBorrows * totalReservesNew = interestAccumulated * reserveFactor + totalReserves * totalFuseFeesNew = interestAccumulated * fuseFee + totalFuseFees * totalAdminFeesNew = interestAccumulated * adminFee + totalAdminFees * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex */ Exp memory simpleInterestFactor = mul_(Exp({mantissa: borrowRateMantissa}), blockDelta); uint interestAccumulated = mul_ScalarTruncate(simpleInterestFactor, totalBorrows); uint totalBorrowsNew = add_(interestAccumulated, totalBorrows); uint totalReservesNew = mul_ScalarTruncateAddUInt(Exp({mantissa: reserveFactorMantissa}), interestAccumulated, totalReserves); uint totalFuseFeesNew = mul_ScalarTruncateAddUInt(Exp({mantissa: fuseFeeMantissa}), interestAccumulated, totalFuseFees); uint totalAdminFeesNew = mul_ScalarTruncateAddUInt(Exp({mantissa: adminFeeMantissa}), interestAccumulated, totalAdminFees); uint borrowIndexNew = mul_ScalarTruncateAddUInt(simpleInterestFactor, borrowIndex, borrowIndex); ///////////////////////// // EFFECTS & INTERACTIONS // (No safe failures beyond this point) /* We write the previously calculated values into storage */ accrualBlockNumber = currentBlockNumber; borrowIndex = borrowIndexNew; totalBorrows = totalBorrowsNew; totalReserves = totalReservesNew; totalFuseFees = totalFuseFeesNew; totalAdminFees = totalAdminFeesNew; /* We emit an AccrueInterest event */ emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew); // Attempt to add interest checkpoint address(interestRateModel).call(abi.encodeWithSignature("checkpointInterest(uint256)", borrowRateMantissa)); return uint(Error.NO_ERROR); } /** * @notice Sender supplies assets into the market and receives cTokens in exchange * @dev Accrues interest whether or not the operation succeeds, unless reverted * @param mintAmount The amount of the underlying asset to supply * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount. */ function mintInternal(uint mintAmount) internal nonReentrant(false) returns (uint, uint) { uint error = accrueInterest(); if (error != uint(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; uint exchangeRateMantissa; uint mintTokens; uint totalSupplyNew; uint accountTokensNew; uint 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, uint mintAmount) internal returns (uint, uint) { /* Fail if mint not allowed */ uint 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 != getBlockNumber()) { return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0); } MintLocalVars memory vars; (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal(); if (vars.mathErr != MathError.NO_ERROR) { return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0); } // 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"); /* * We calculate the new total supply of cTokens and minter token balance, checking for overflow: * totalSupplyNew = totalSupply + mintTokens * accountTokensNew = accountTokens[minter] + mintTokens */ vars.totalSupplyNew = add_(totalSupply, vars.mintTokens); vars.accountTokensNew = add_(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 */ comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens); return (uint(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(uint redeemTokens) internal nonReentrant(false) returns (uint) { uint error = accrueInterest(); if (error != uint(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(uint redeemAmount) internal nonReentrant(false) returns (uint) { uint error = accrueInterest(); if (error != uint(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; uint exchangeRateMantissa; uint redeemTokens; uint redeemAmount; uint totalSupplyNew; uint 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 payable redeemer, uint redeemTokensIn, uint redeemAmountIn) internal returns (uint) { require(redeemTokensIn == 0 || redeemAmountIn == 0, "redeem"); RedeemLocalVars memory vars; /* exchangeRate = invoke Exchange Rate Stored() */ (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal(); if (vars.mathErr != MathError.NO_ERROR) { return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)); } /* 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, uint(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, uint(vars.mathErr)); } vars.redeemAmount = redeemAmountIn; } /* Fail if redeem not allowed */ uint 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 != getBlockNumber()) { 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, uint(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, uint(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 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 write previously calculated values into storage */ totalSupply = vars.totalSupplyNew; accountTokens[redeemer] = vars.accountTokensNew; /* 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 uint(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(uint borrowAmount) internal nonReentrant(false) returns (uint) { uint error = accrueInterest(); if (error != uint(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; uint accountBorrows; uint accountBorrowsNew; uint 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 payable borrower, uint borrowAmount) internal returns (uint) { /* Fail if borrow not allowed */ uint 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 != getBlockNumber()) { return fail(Error.MARKET_NOT_FRESH, FailureInfo.BORROW_FRESHNESS_CHECK); } /* Fail gracefully if protocol has insufficient underlying cash */ uint 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.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower); if (vars.mathErr != MathError.NO_ERROR) { return failOpaque(Error.MATH_ERROR, FailureInfo.BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED, uint(vars.mathErr)); } (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, uint(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, uint(vars.mathErr)); } ///////////////////////// // EFFECTS & INTERACTIONS // (No safe failures beyond this point) /* * 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 write the previously calculated values into storage */ accountBorrows[borrower].principal = vars.accountBorrowsNew; accountBorrows[borrower].interestIndex = borrowIndex; totalBorrows = vars.totalBorrowsNew; /* 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 uint(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(uint repayAmount) internal nonReentrant(false) returns (uint, uint) { uint error = accrueInterest(); if (error != uint(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, uint repayAmount) internal nonReentrant(false) returns (uint, uint) { uint error = accrueInterest(); if (error != uint(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; uint repayAmount; uint borrowerIndex; uint accountBorrows; uint accountBorrowsNew; uint totalBorrowsNew; uint 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, uint repayAmount) internal returns (uint, uint) { /* Fail if repayBorrow not allowed */ uint 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 != getBlockNumber()) { 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.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower); if (vars.mathErr != MathError.NO_ERROR) { return (failOpaque(Error.MATH_ERROR, FailureInfo.REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED, uint(vars.mathErr)), 0); } /* If repayAmount == -1, repayAmount = accountBorrows */ if (repayAmount == uint(-1)) { 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"); (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount); require(vars.mathErr == MathError.NO_ERROR, "REPAY"); /* 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 (uint(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, uint repayAmount, CTokenInterface cTokenCollateral) internal nonReentrant(false) returns (uint, uint) { uint error = accrueInterest(); if (error != uint(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.accrueInterest(); if (error != uint(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, uint repayAmount, CTokenInterface cTokenCollateral) internal returns (uint, uint) { /* Fail if liquidate not allowed */ uint 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 != getBlockNumber()) { return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0); } /* Verify cTokenCollateral market's block number equals current block number */ if (cTokenCollateral.accrualBlockNumber() != getBlockNumber()) { 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 == uint(-1)) { return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0); } /* Fail if repayBorrow fails */ (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount); if (repayBorrowError != uint(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 */ (uint amountSeizeError, uint seizeTokens) = comptroller.liquidateCalculateSeizeTokens(address(this), address(cTokenCollateral), actualRepayAmount); require(amountSeizeError == uint(Error.NO_ERROR), "LIQ"); /* Revert if borrower collateral token balance < seizeTokens */ require(cTokenCollateral.balanceOf(borrower) >= seizeTokens, "LIQ"); // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call uint 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 == uint(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 (uint(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, uint seizeTokens) external nonReentrant(true) returns (uint) { return seizeInternal(msg.sender, liquidator, borrower, seizeTokens); } struct SeizeInternalLocalVars { MathError mathErr; uint borrowerTokensNew; uint liquidatorTokensNew; uint liquidatorSeizeTokens; uint protocolSeizeTokens; uint protocolSeizeAmount; uint exchangeRateMantissa; uint totalReservesNew; uint totalSupplyNew; } /** * @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, uint seizeTokens) internal returns (uint) { /* Fail if seize not allowed */ uint 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, uint(vars.mathErr)); } vars.protocolSeizeTokens = mul_(seizeTokens, Exp({mantissa: protocolSeizeShareMantissa})); vars.liquidatorSeizeTokens = sub_(seizeTokens, vars.protocolSeizeTokens); (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal(); require(vars.mathErr == MathError.NO_ERROR, "exRate"); vars.protocolSeizeAmount = mul_ScalarTruncate(Exp({mantissa: vars.exchangeRateMantissa}), vars.protocolSeizeTokens); vars.totalReservesNew = add_(totalReserves, vars.protocolSeizeAmount); vars.totalSupplyNew = sub_(totalSupply, vars.protocolSeizeTokens); (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, uint(vars.mathErr)); } ///////////////////////// // EFFECTS & INTERACTIONS // (No safe failures beyond this point) /* We write the previously calculated values into storage */ totalReserves = vars.totalReservesNew; totalSupply = vars.totalSupplyNew; 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 uint(Error.NO_ERROR); } /*** Admin Functions ***/ /** * @notice Sets a new comptroller for the market * @dev Internal function to set a new comptroller * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function _setComptroller(ComptrollerInterface newComptroller) internal returns (uint) { ComptrollerInterface oldComptroller = comptroller; // Ensure invoke comptroller.isComptroller() returns true require(newComptroller.isComptroller(), "marker"); // Set market's comptroller to newComptroller comptroller = newComptroller; // Emit NewComptroller(oldComptroller, newComptroller) emit NewComptroller(oldComptroller, newComptroller); return uint(Error.NO_ERROR); } /** * @notice accrues interest and sets a new admin fee for the protocol using _setAdminFeeFresh * @dev Admin function to accrue interest and set a new admin fee * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function _setAdminFee(uint newAdminFeeMantissa) external nonReentrant(false) returns (uint) { uint error = accrueInterest(); if (error != uint(Error.NO_ERROR)) { // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted admin fee change failed. return fail(Error(error), FailureInfo.SET_ADMIN_FEE_ACCRUE_INTEREST_FAILED); } // _setAdminFeeFresh emits reserve-factor-specific logs on errors, so we don't need to. return _setAdminFeeFresh(newAdminFeeMantissa); } /** * @notice Sets a new admin fee for the protocol (*requires fresh interest accrual) * @dev Admin function to set a new admin fee * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function _setAdminFeeFresh(uint newAdminFeeMantissa) internal returns (uint) { // Verify market's block number equals current block number if (accrualBlockNumber != getBlockNumber()) { return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_ADMIN_FEE_FRESH_CHECK); } // Sanitize newAdminFeeMantissa if (newAdminFeeMantissa == uint(-1)) newAdminFeeMantissa = adminFeeMantissa; // Get latest Fuse fee uint newFuseFeeMantissa = getPendingFuseFeeFromAdmin(); // Check reserveFactorMantissa + newAdminFeeMantissa + newFuseFeeMantissa ≤ reserveFactorPlusFeesMaxMantissa if (add_(add_(reserveFactorMantissa, newAdminFeeMantissa), newFuseFeeMantissa) > reserveFactorPlusFeesMaxMantissa) { return fail(Error.BAD_INPUT, FailureInfo.SET_ADMIN_FEE_BOUNDS_CHECK); } // If setting admin fee if (adminFeeMantissa != newAdminFeeMantissa) { // Check caller is admin if (!hasAdminRights()) { return fail(Error.UNAUTHORIZED, FailureInfo.SET_ADMIN_FEE_ADMIN_CHECK); } // Set admin fee uint oldAdminFeeMantissa = adminFeeMantissa; adminFeeMantissa = newAdminFeeMantissa; // Emit event emit NewAdminFee(oldAdminFeeMantissa, newAdminFeeMantissa); } // If setting Fuse fee if (fuseFeeMantissa != newFuseFeeMantissa) { // Set Fuse fee uint oldFuseFeeMantissa = fuseFeeMantissa; fuseFeeMantissa = newFuseFeeMantissa; // Emit event emit NewFuseFee(oldFuseFeeMantissa, newFuseFeeMantissa); } return uint(Error.NO_ERROR); } /** * @notice accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh * @dev Admin function to accrue interest and set a new reserve factor * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function _setReserveFactor(uint newReserveFactorMantissa) external nonReentrant(false) returns (uint) { uint error = accrueInterest(); if (error != uint(Error.NO_ERROR)) { // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed. return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED); } // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to. return _setReserveFactorFresh(newReserveFactorMantissa); } /** * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual) * @dev Admin function to set a new reserve factor * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) { // Check caller is admin if (!hasAdminRights()) { return fail(Error.UNAUTHORIZED, FailureInfo.SET_RESERVE_FACTOR_ADMIN_CHECK); } // Verify market's block number equals current block number if (accrualBlockNumber != getBlockNumber()) { return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK); } // Check newReserveFactor ≤ maxReserveFactor if (add_(add_(newReserveFactorMantissa, adminFeeMantissa), fuseFeeMantissa) > reserveFactorPlusFeesMaxMantissa) { return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK); } uint oldReserveFactorMantissa = reserveFactorMantissa; reserveFactorMantissa = newReserveFactorMantissa; emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa); return uint(Error.NO_ERROR); } /** * @notice Accrues interest and reduces reserves by transferring to admin * @param reduceAmount Amount of reduction to reserves * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function _reduceReserves(uint reduceAmount) external nonReentrant(false) returns (uint) { uint error = accrueInterest(); if (error != uint(Error.NO_ERROR)) { // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed. return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED); } // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to. return _reduceReservesFresh(reduceAmount); } /** * @notice Reduces reserves by transferring to admin * @dev Requires fresh interest accrual * @param reduceAmount Amount of reduction to reserves * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function _reduceReservesFresh(uint reduceAmount) internal returns (uint) { // totalReserves - reduceAmount uint totalReservesNew; // Check caller is admin if (!hasAdminRights()) { return fail(Error.UNAUTHORIZED, FailureInfo.REDUCE_RESERVES_ADMIN_CHECK); } // We fail gracefully unless market's block number equals current block number if (accrualBlockNumber != getBlockNumber()) { return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK); } // Fail gracefully if protocol has insufficient underlying cash if (getCashPrior() < reduceAmount) { return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE); } // Check reduceAmount ≤ reserves[n] (totalReserves) if (reduceAmount > totalReserves) { return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION); } ///////////////////////// // EFFECTS & INTERACTIONS // (No safe failures beyond this point) // We checked reduceAmount <= totalReserves above, so this should never revert. totalReservesNew = sub_(totalReserves, reduceAmount); // Store reserves[n+1] = reserves[n] - reduceAmount totalReserves = totalReservesNew; // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred. doTransferOut(msg.sender, reduceAmount); emit ReservesReduced(msg.sender, reduceAmount, totalReservesNew); return uint(Error.NO_ERROR); } /** * @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(uint withdrawAmount) external nonReentrant(false) returns (uint) { uint error = accrueInterest(); if (error != uint(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); } // _withdrawFuseFeesFresh emits reserve-reduction-specific logs on errors, so we don't need to. return _withdrawFuseFeesFresh(withdrawAmount); } /** * @notice Reduces Fuse fees by transferring to Fuse * @dev Requires fresh interest accrual * @param withdrawAmount Amount of fees to withdraw * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function _withdrawFuseFeesFresh(uint withdrawAmount) internal returns (uint) { // totalFuseFees - reduceAmount uint totalFuseFeesNew; // We fail gracefully unless market's block number equals current block number if (accrualBlockNumber != getBlockNumber()) { return fail(Error.MARKET_NOT_FRESH, FailureInfo.WITHDRAW_FUSE_FEES_FRESH_CHECK); } // Fail gracefully if protocol has insufficient underlying cash if (getCashPrior() < withdrawAmount) { return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.WITHDRAW_FUSE_FEES_CASH_NOT_AVAILABLE); } // Check withdrawAmount ≤ fuseFees[n] (totalFuseFees) if (withdrawAmount > totalFuseFees) { return fail(Error.BAD_INPUT, FailureInfo.WITHDRAW_FUSE_FEES_VALIDATION); } ///////////////////////// // EFFECTS & INTERACTIONS // (No safe failures beyond this point) // We checked withdrawAmount <= totalFuseFees above, so this should never revert. totalFuseFeesNew = sub_(totalFuseFees, withdrawAmount); // Store fuseFees[n+1] = fuseFees[n] - withdrawAmount totalFuseFees = totalFuseFeesNew; // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred. doTransferOut(address(fuseAdmin), withdrawAmount); return uint(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(uint withdrawAmount) external nonReentrant(false) returns (uint) { uint error = accrueInterest(); if (error != uint(Error.NO_ERROR)) { // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted admin fee withdrawal failed. return fail(Error(error), FailureInfo.WITHDRAW_ADMIN_FEES_ACCRUE_INTEREST_FAILED); } // _withdrawAdminFeesFresh emits reserve-reduction-specific logs on errors, so we don't need to. return _withdrawAdminFeesFresh(withdrawAmount); } /** * @notice Reduces admin fees by transferring to admin * @dev Requires fresh interest accrual * @param withdrawAmount Amount of fees to withdraw * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function _withdrawAdminFeesFresh(uint withdrawAmount) internal returns (uint) { // totalAdminFees - reduceAmount uint totalAdminFeesNew; // We fail gracefully unless market's block number equals current block number if (accrualBlockNumber != getBlockNumber()) { 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); } // Check withdrawAmount ≤ adminFees[n] (totalAdminFees) if (withdrawAmount > totalAdminFees) { return fail(Error.BAD_INPUT, FailureInfo.WITHDRAW_ADMIN_FEES_VALIDATION); } ///////////////////////// // EFFECTS & INTERACTIONS // (No safe failures beyond this point) // We checked withdrawAmount <= totalAdminFees above, so this should never revert. totalAdminFeesNew = sub_(totalAdminFees, withdrawAmount); // Store adminFees[n+1] = adminFees[n] - withdrawAmount totalAdminFees = totalAdminFeesNew; // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred. doTransferOut(address(uint160(UnitrollerAdminStorage(address(comptroller)).admin())), withdrawAmount); return uint(Error.NO_ERROR); } /** * @notice accrues interest and updates the interest rate model using _setInterestRateModelFresh * @dev Admin function to accrue interest and update the interest rate model * @param newInterestRateModel the new interest rate model to use * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint) { uint error = accrueInterest(); if (error != uint(Error.NO_ERROR)) { // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED); } // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to. return _setInterestRateModelFresh(newInterestRateModel); } /** * @notice updates the interest rate model (*requires fresh interest accrual) * @dev Admin function to update the interest rate model * @param newInterestRateModel the new interest rate model to use * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal returns (uint) { // Used to store old model for use in the event that is emitted on success InterestRateModel oldInterestRateModel; // Check caller is admin if (!hasAdminRights()) { return fail(Error.UNAUTHORIZED, FailureInfo.SET_INTEREST_RATE_MODEL_OWNER_CHECK); } // We fail gracefully unless market's block number equals current block number if (accrualBlockNumber != getBlockNumber()) { return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK); } // Track the market's current interest rate model oldInterestRateModel = interestRateModel; // Ensure invoke newInterestRateModel.isInterestRateModel() returns true require(newInterestRateModel.isInterestRateModel(), "marker"); // Set the interest rate model to newInterestRateModel interestRateModel = newInterestRateModel; // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel) emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel); // Attempt to reset interest checkpoints on old IRM if (address(oldInterestRateModel) != address(0)) address(oldInterestRateModel).call(abi.encodeWithSignature("resetInterestCheckpoints()")); // Attempt to add first interest checkpoint on new IRM address(newInterestRateModel).call(abi.encodeWithSignature("checkpointInterest()")); return uint(Error.NO_ERROR); } /** * @notice updates the cToken ERC20 name and symbol * @dev Admin function to update the cToken ERC20 name and symbol * @param _name the new ERC20 token name to use * @param _symbol the new ERC20 token symbol to use * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) */ function _setNameAndSymbol(string calldata _name, string calldata _symbol) external { // Check caller is admin require(hasAdminRights(), "!admin"); // Set ERC20 name and symbol name = _name; symbol = _symbol; } /*** 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 returns (uint); /** * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee. * This may revert due to insufficient balance or insufficient allowance. */ function doTransferIn(address from, uint amount) internal returns (uint); /** * @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 payable to, uint amount) internal; /*** 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; } }
pragma solidity ^0.5.16; contract ComptrollerInterface { /// @notice Indicator that this is a Comptroller contract (for inspection) bool public constant isComptroller = true; /*** Assets You Are In ***/ function enterMarkets(address[] calldata cTokens) external returns (uint[] memory); function exitMarket(address cToken) external returns (uint); /*** Policy Hooks ***/ function mintAllowed(address cToken, address minter, uint mintAmount) external returns (uint); function mintWithinLimits(address cToken, uint exchangeRateMantissa, uint accountTokens, uint mintAmount) external returns (uint); function mintVerify(address cToken, address minter, uint mintAmount, uint mintTokens) external; function redeemAllowed(address cToken, address redeemer, uint redeemTokens) external returns (uint); function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) external; function borrowAllowed(address cToken, address borrower, uint borrowAmount) external returns (uint); function borrowWithinLimits(address cToken, uint accountBorrowsNew) external returns (uint); function borrowVerify(address cToken, address borrower, uint borrowAmount) external; function repayBorrowAllowed( address cToken, address payer, address borrower, uint repayAmount) external returns (uint); function repayBorrowVerify( address cToken, address payer, address borrower, uint repayAmount, uint borrowerIndex) external; function liquidateBorrowAllowed( address cTokenBorrowed, address cTokenCollateral, address liquidator, address borrower, uint repayAmount) external returns (uint); function liquidateBorrowVerify( address cTokenBorrowed, address cTokenCollateral, address liquidator, address borrower, uint repayAmount, uint seizeTokens) external; function seizeAllowed( address cTokenCollateral, address cTokenBorrowed, address liquidator, address borrower, uint seizeTokens) external returns (uint); function seizeVerify( address cTokenCollateral, address cTokenBorrowed, address liquidator, address borrower, uint seizeTokens) external; function transferAllowed(address cToken, address src, address dst, uint transferTokens) external returns (uint); function transferVerify(address cToken, address src, address dst, uint transferTokens) external; /*** Liquidity/Liquidation Calculations ***/ function liquidateCalculateSeizeTokens( address cTokenBorrowed, address cTokenCollateral, uint repayAmount) external view returns (uint, uint); /*** Pool-Wide/Cross-Asset Reentrancy Prevention ***/ function _beforeNonReentrant() external; function _afterNonReentrant() external; }
pragma solidity ^0.5.16; import "./IFuseFeeDistributor.sol"; import "./ComptrollerStorage.sol"; import "./ComptrollerInterface.sol"; import "./InterestRateModel.sol"; contract CTokenAdminStorage { /** * @notice Administrator for Fuse */ IFuseFeeDistributor internal constant fuseAdmin = IFuseFeeDistributor(0xa731585ab05fC9f83555cf9Bff8F58ee94e18F85); /** * @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; /** * @notice Maximum borrow rate that can ever be applied (.0005% / block) */ uint internal constant borrowRateMaxMantissa = 0.0005e16; /** * @notice Maximum fraction of interest that can be set aside for reserves + fees */ uint internal constant reserveFactorPlusFeesMaxMantissa = 1e18; /** * @notice 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; /** * @notice Initial exchange rate used when minting the first CTokens (used when totalSupply = 0) */ uint internal initialExchangeRateMantissa; /** * @notice Fraction of interest currently set aside for admin fees */ uint public adminFeeMantissa; /** * @notice Fraction of interest currently set aside for Fuse fees */ uint public fuseFeeMantissa; /** * @notice Fraction of interest currently set aside for reserves */ uint public reserveFactorMantissa; /** * @notice Block number that interest was last accrued at */ uint public accrualBlockNumber; /** * @notice Accumulator of the total earned interest rate since the opening of the market */ uint public borrowIndex; /** * @notice Total amount of outstanding borrows of the underlying in this market */ uint public totalBorrows; /** * @notice Total amount of reserves of the underlying held in this market */ uint public totalReserves; /** * @notice Total amount of admin fees of the underlying held in this market */ uint public totalAdminFees; /** * @notice Total amount of Fuse fees of the underlying held in this market */ uint public totalFuseFees; /** * @notice Total number of tokens in circulation */ uint public totalSupply; /** * @notice Official record of token balances for each account */ mapping (address => uint) internal accountTokens; /** * @notice Approved token transfer amounts on behalf of others */ mapping (address => mapping (address => uint)) internal transferAllowances; /** * @notice Container for borrow balance information * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action * @member interestIndex Global borrowIndex as of the most recent balance-changing action */ struct BorrowSnapshot { uint principal; uint interestIndex; } /** * @notice Mapping of account addresses to outstanding borrow balances */ mapping(address => BorrowSnapshot) internal accountBorrows; /** * @notice Share of seized collateral that is added to reserves */ uint public constant protocolSeizeShareMantissa = 2.8e16; //2.8% } contract CTokenInterface is CTokenStorage { /** * @notice Indicator that this is a CToken contract (for inspection) */ bool public constant isCToken = true; /** * @notice Indicator that this is or is not a CEther contract (for inspection) */ bool public constant isCEther = false; /*** Market Events ***/ /** * @notice Event emitted when interest is accrued */ event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows); /** * @notice Event emitted when tokens are minted */ event Mint(address minter, uint mintAmount, uint mintTokens); /** * @notice Event emitted when tokens are redeemed */ event Redeem(address redeemer, uint redeemAmount, uint redeemTokens); /** * @notice Event emitted when underlying is borrowed */ event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows); /** * @notice Event emitted when a borrow is repaid */ event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows); /** * @notice Event emitted when a borrow is liquidated */ event LiquidateBorrow(address liquidator, address borrower, uint repayAmount, address cTokenCollateral, uint seizeTokens); /*** Admin Events ***/ /** * @notice Event emitted when comptroller is changed */ event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller); /** * @notice Event emitted when interestRateModel is changed */ event NewMarketInterestRateModel(InterestRateModel oldInterestRateModel, InterestRateModel newInterestRateModel); /** * @notice Event emitted when the reserve factor is changed */ event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa); /** * @notice Event emitted when the reserves are added */ event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves); /** * @notice Event emitted when the reserves are reduced */ event ReservesReduced(address admin, uint reduceAmount, uint newTotalReserves); /** * @notice Event emitted when the admin fee is changed */ event NewAdminFee(uint oldAdminFeeMantissa, uint newAdminFeeMantissa); /** * @notice Event emitted when the Fuse fee is changed */ event NewFuseFee(uint oldFuseFeeMantissa, uint newFuseFeeMantissa); /** * @notice EIP20 Transfer event */ event Transfer(address indexed from, address indexed to, uint amount); /** * @notice EIP20 Approval event */ event Approval(address indexed owner, address indexed spender, uint amount); /** * @notice Failure event */ event Failure(uint error, uint info, uint detail); /*** User Interface ***/ function transfer(address dst, uint amount) external returns (bool); function transferFrom(address src, address dst, uint amount) external returns (bool); function approve(address spender, uint amount) external returns (bool); function allowance(address owner, address spender) external view returns (uint); function balanceOf(address owner) external view returns (uint); function balanceOfUnderlying(address owner) external returns (uint); function getAccountSnapshot(address account) external view returns (uint, uint, uint, uint); function borrowRatePerBlock() external view returns (uint); function supplyRatePerBlock() external view returns (uint); function totalBorrowsCurrent() external returns (uint); function borrowBalanceCurrent(address account) external returns (uint); function borrowBalanceStored(address account) public view returns (uint); function exchangeRateCurrent() public returns (uint); function exchangeRateStored() public view returns (uint); function getCash() external view returns (uint); function accrueInterest() public returns (uint); function seize(address liquidator, address borrower, uint seizeTokens) external returns (uint); /*** Admin Functions ***/ function _setReserveFactor(uint newReserveFactorMantissa) external returns (uint); function _reduceReserves(uint reduceAmount) external returns (uint); function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint); } contract CErc20Storage { /** * @notice Underlying asset for this CToken */ address public underlying; } contract CErc20Interface is CErc20Storage { /*** User Interface ***/ function mint(uint mintAmount) external returns (uint); function redeem(uint redeemTokens) external returns (uint); function redeemUnderlying(uint redeemAmount) external returns (uint); function borrow(uint borrowAmount) external returns (uint); function repayBorrow(uint repayAmount) external returns (uint); function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint); function liquidateBorrow(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) external returns (uint); } contract CEtherInterface is CErc20Storage { /** * @notice Indicator that this is a CEther contract (for inspection) */ bool public constant isCEther = true; } contract CDelegationStorage { /** * @notice Implementation address for this contract */ address public implementation; } 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; /** * @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) external; /** * @notice Function called before all delegator functions * @dev Checks comptroller.autoImplementation and upgrades the implementation if necessary */ function _prepare() external payable; }
pragma solidity ^0.5.16; 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 cErc20DelegateWhitelist(address oldImplementation, address newImplementation, bool allowResign) external view returns (bool); function cEtherDelegateWhitelist(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 latestCEtherDelegate(address oldImplementation) external view returns (address cEtherDelegate, bool allowResign, bytes memory becomeImplementationData); function deployCEther(bytes calldata constructorData) external returns (address); function deployCErc20(bytes calldata constructorData) external returns (address); function () external payable; }
pragma solidity ^0.5.16; import "./IFuseFeeDistributor.sol"; import "./CToken.sol"; import "./PriceOracle.sol"; contract UnitrollerAdminStorage { /** * @notice Administrator for Fuse */ IFuseFeeDistributor internal constant fuseAdmin = IFuseFeeDistributor(0xa731585ab05fC9f83555cf9Bff8F58ee94e18F85); /** * @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 */ uint public closeFactorMantissa; /** * @notice Multiplier representing the discount on collateral that a liquidator receives */ uint public liquidationIncentiveMantissa; /** * @notice UNUSED AFTER UPGRADE: Max number of assets a single account can participate in (borrow or use as collateral) */ uint internal maxAssets; /** * @notice Per-account mapping of "assets you are in", capped by maxAssets */ mapping(address => CToken[]) public accountAssets; } contract ComptrollerV2Storage is ComptrollerV1Storage { struct Market { /** * @notice Whether or not this market is listed */ bool isListed; /** * @notice Multiplier representing the most one can borrow against their collateral in this market. * For instance, 0.9 to allow borrowing 90% of collateral value. * Must be between 0 and 1, and stored as a mantissa. */ uint collateralFactorMantissa; /** * @notice 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 CToken[] 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; /// @notice 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 => CToken) 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; /// @notice 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 => uint) public borrowCaps; /// @notice Supply caps enforced by mintAllowed for each cToken address. Defaults to zero which corresponds to unlimited supplying. mapping(address => uint) 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; }
pragma solidity ^0.5.16; import "./CToken.sol"; contract PriceOracle { /// @notice Indicator that this is a PriceOracle contract (for inspection) bool public constant isPriceOracle = true; /** * @notice Get the underlying price of a cToken asset * @param cToken The cToken to get the underlying price of * @return The underlying asset price mantissa (scaled by 1e18). * Zero means the price is unavailable. */ function getUnderlyingPrice(CToken cToken) external view returns (uint); }
pragma solidity ^0.5.16; /** * @title Compound's InterestRateModel Interface * @author Compound */ contract InterestRateModel { /// @notice Indicator that this is an InterestRateModel contract (for inspection) bool public constant isInterestRateModel = true; /** * @notice Calculates the current borrow interest rate per block * @param cash The total amount of cash the market has * @param borrows The total amount of borrows the market has outstanding * @param reserves The total amount of reserves the market has * @return The borrow rate per block (as a percentage, and scaled by 1e18) */ function getBorrowRate(uint cash, uint borrows, uint reserves) external view returns (uint); /** * @notice Calculates the current supply interest rate per block * @param cash The total amount of cash the market has * @param borrows The total amount of borrows the market has outstanding * @param reserves The total amount of reserves the market has * @param reserveFactorMantissa The current reserve factor the market has * @return The supply rate per block (as a percentage, and scaled by 1e18) */ function getSupplyRate(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) external view returns (uint); }
pragma solidity ^0.5.16; contract ComptrollerErrorReporter { enum Error { NO_ERROR, UNAUTHORIZED, COMPTROLLER_MISMATCH, INSUFFICIENT_SHORTFALL, INSUFFICIENT_LIQUIDITY, INVALID_CLOSE_FACTOR, INVALID_COLLATERAL_FACTOR, INVALID_LIQUIDATION_INCENTIVE, MARKET_NOT_ENTERED, // no longer possible MARKET_NOT_LISTED, MARKET_ALREADY_LISTED, MATH_ERROR, NONZERO_BORROW_BALANCE, PRICE_ERROR, REJECTION, SNAPSHOT_ERROR, TOO_MANY_ASSETS, TOO_MUCH_REPAY, 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_MAX_ASSETS_OWNER_CHECK, 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(uint error, uint info, uint detail); /** * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator */ function fail(Error err, FailureInfo info) internal returns (uint) { emit Failure(uint(err), uint(info), 0); return uint(err); } /** * @dev use this when reporting an opaque error from an upgradeable collaborator contract */ function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) { emit Failure(uint(err), uint(info), opaqueError); return uint(err); } } contract TokenErrorReporter { 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, SET_MAX_ASSETS_OWNER_CHECK, SET_ORACLE_MARKET_NOT_LISTED, 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(uint error, uint info, uint detail); /** * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator */ function fail(Error err, FailureInfo info) internal returns (uint) { emit Failure(uint(err), uint(info), 0); return uint(err); } /** * @dev use this when reporting an opaque error from an upgradeable collaborator contract */ function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) { emit Failure(uint(err), uint(info), opaqueError); return err == Error.COMPTROLLER_REJECTION ? 1000 + opaqueError : uint(err); } }
pragma solidity ^0.5.16; 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(uint num, uint denom) pure internal returns (MathError, Exp memory) { (MathError err0, uint scaledNumerator) = mulUInt(num, expScale); if (err0 != MathError.NO_ERROR) { return (err0, Exp({mantissa: 0})); } (MathError err1, uint 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) pure internal returns (MathError, Exp memory) { (MathError error, uint 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) pure internal returns (MathError, Exp memory) { (MathError error, uint 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, uint scalar) pure internal returns (MathError, Exp memory) { (MathError err0, uint 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, uint scalar) pure internal returns (MathError, uint) { (MathError err, Exp memory product) = mulScalar(a, scalar); if (err != MathError.NO_ERROR) { return (err, 0); } return (MathError.NO_ERROR, truncate(product)); } /** * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer. */ function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) pure internal returns (MathError, uint) { (MathError err, Exp memory product) = mulScalar(a, scalar); if (err != MathError.NO_ERROR) { return (err, 0); } return addUInt(truncate(product), addend); } /** * @dev Divide an Exp by a scalar, returning a new Exp. */ function divScalar(Exp memory a, uint scalar) pure internal returns (MathError, Exp memory) { (MathError err0, uint 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(uint scalar, Exp memory divisor) pure internal 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, uint 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(uint scalar, Exp memory divisor) pure internal returns (MathError, uint) { (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) pure internal returns (MathError, Exp memory) { (MathError err0, uint 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, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct); if (err1 != MathError.NO_ERROR) { return (err1, Exp({mantissa: 0})); } (MathError err2, uint 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(uint a, uint b) pure internal 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) pure internal 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) pure internal returns (MathError, Exp memory) { return getExp(a.mantissa, b.mantissa); } }
pragma solidity ^0.5.16; /** * @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(uint a, uint b) internal pure returns (MathError, uint) { if (a == 0) { return (MathError.NO_ERROR, 0); } uint 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(uint a, uint b) internal pure returns (MathError, uint) { 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(uint a, uint b) internal pure returns (MathError, uint) { 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(uint a, uint b) internal pure returns (MathError, uint) { uint 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(uint a, uint b, uint c) internal pure returns (MathError, uint) { (MathError err0, uint sum) = addUInt(a, b); if (err0 != MathError.NO_ERROR) { return (err0, 0); } return subUInt(sum, c); } }
pragma solidity ^0.5.16; /** * @title Exponential module for storing fixed-precision decimals * @author Compound * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places. * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is: * `Exp({mantissa: 5100000000000000000})`. */ contract ExponentialNoError { uint constant expScale = 1e18; uint constant doubleScale = 1e36; uint constant halfExpScale = expScale/2; uint constant mantissaOne = expScale; struct Exp { uint mantissa; } struct Double { uint mantissa; } /** * @dev Truncates the given exp to a whole number value. * For example, truncate(Exp{mantissa: 15 * expScale}) = 15 */ function truncate(Exp memory exp) pure internal returns (uint) { // Note: We are not using careful math here as we're performing a division that cannot fail return exp.mantissa / expScale; } /** * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer. */ function mul_ScalarTruncate(Exp memory a, uint scalar) pure internal returns (uint) { Exp memory product = mul_(a, scalar); return truncate(product); } /** * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer. */ function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) pure internal returns (uint) { Exp memory product = mul_(a, scalar); return add_(truncate(product), addend); } /** * @dev Checks if first Exp is less than second Exp. */ function lessThanExp(Exp memory left, Exp memory right) pure internal returns (bool) { return left.mantissa < right.mantissa; } /** * @dev Checks if left Exp <= right Exp. */ function lessThanOrEqualExp(Exp memory left, Exp memory right) pure internal returns (bool) { return left.mantissa <= right.mantissa; } /** * @dev Checks if left Exp > right Exp. */ function greaterThanExp(Exp memory left, Exp memory right) pure internal returns (bool) { return left.mantissa > right.mantissa; } /** * @dev returns true if Exp is exactly zero */ function isZeroExp(Exp memory value) pure internal returns (bool) { return value.mantissa == 0; } function safe224(uint n, string memory errorMessage) pure internal returns (uint224) { require(n < 2**224, errorMessage); return uint224(n); } function safe32(uint n, string memory errorMessage) pure internal returns (uint32) { require(n < 2**32, errorMessage); return uint32(n); } function add_(Exp memory a, Exp memory b) pure internal returns (Exp memory) { return Exp({mantissa: add_(a.mantissa, b.mantissa)}); } function add_(Double memory a, Double memory b) pure internal returns (Double memory) { return Double({mantissa: add_(a.mantissa, b.mantissa)}); } function add_(uint a, uint b) pure internal returns (uint) { return add_(a, b, "addition overflow"); } function add_(uint a, uint b, string memory errorMessage) pure internal returns (uint) { uint c = a + b; require(c >= a, errorMessage); return c; } function sub_(Exp memory a, Exp memory b) pure internal returns (Exp memory) { return Exp({mantissa: sub_(a.mantissa, b.mantissa)}); } function sub_(Double memory a, Double memory b) pure internal returns (Double memory) { return Double({mantissa: sub_(a.mantissa, b.mantissa)}); } function sub_(uint a, uint b) pure internal returns (uint) { return sub_(a, b, "subtraction underflow"); } function sub_(uint a, uint b, string memory errorMessage) pure internal returns (uint) { require(b <= a, errorMessage); return a - b; } function mul_(Exp memory a, Exp memory b) pure internal returns (Exp memory) { return Exp({mantissa: mul_(a.mantissa, b.mantissa) / expScale}); } function mul_(Exp memory a, uint b) pure internal returns (Exp memory) { return Exp({mantissa: mul_(a.mantissa, b)}); } function mul_(uint a, Exp memory b) pure internal returns (uint) { return mul_(a, b.mantissa) / expScale; } function mul_(Double memory a, Double memory b) pure internal returns (Double memory) { return Double({mantissa: mul_(a.mantissa, b.mantissa) / doubleScale}); } function mul_(Double memory a, uint b) pure internal returns (Double memory) { return Double({mantissa: mul_(a.mantissa, b)}); } function mul_(uint a, Double memory b) pure internal returns (uint) { return mul_(a, b.mantissa) / doubleScale; } function mul_(uint a, uint b) pure internal returns (uint) { return mul_(a, b, "multiplication overflow"); } function mul_(uint a, uint b, string memory errorMessage) pure internal returns (uint) { if (a == 0 || b == 0) { return 0; } uint c = a * b; require(c / a == b, errorMessage); return c; } function div_(Exp memory a, Exp memory b) pure internal returns (Exp memory) { return Exp({mantissa: div_(mul_(a.mantissa, expScale), b.mantissa)}); } function div_(Exp memory a, uint b) pure internal returns (Exp memory) { return Exp({mantissa: div_(a.mantissa, b)}); } function div_(uint a, Exp memory b) pure internal returns (uint) { return div_(mul_(a, expScale), b.mantissa); } function div_(Double memory a, Double memory b) pure internal returns (Double memory) { return Double({mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa)}); } function div_(Double memory a, uint b) pure internal returns (Double memory) { return Double({mantissa: div_(a.mantissa, b)}); } function div_(uint a, Double memory b) pure internal returns (uint) { return div_(mul_(a, doubleScale), b.mantissa); } function div_(uint a, uint b) pure internal returns (uint) { return div_(a, b, "divide by zero"); } function div_(uint a, uint b, string memory errorMessage) pure internal returns (uint) { require(b > 0, errorMessage); return a / b; } function fraction(uint a, uint b) pure internal returns (Double memory) { return Double({mantissa: div_(mul_(a, doubleScale), b)}); } }
pragma solidity ^0.5.16; /** * @title ERC 20 Token Standard Interface * https://eips.ethereum.org/EIPS/eip-20 */ interface EIP20Interface { function name() external view returns (string memory); function symbol() external view returns (string memory); function decimals() external view returns (uint8); /** * @notice Get the total number of tokens in circulation * @return The supply of tokens */ function totalSupply() external view returns (uint256); /** * @notice Gets the balance of the specified address * @param owner The address from which the balance will be retrieved * @return 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 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 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 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 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); }
pragma solidity ^0.5.16; /** * @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 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 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 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); }
pragma solidity ^0.5.16; pragma experimental ABIEncoderV2; import {EIP20Interface} from "./EIP20Interface.sol"; contract IERC4626Draft is EIP20Interface { /*/////////////////////////////////////////////////////////////// Events //////////////////////////////////////////////////////////////*/ event Deposit(address indexed from, address indexed to, uint256 value); event Withdraw(address indexed from, address indexed to, uint256 value); /*/////////////////////////////////////////////////////////////// Mutable Functions //////////////////////////////////////////////////////////////*/ /** @notice Deposit a specific amount of underlying tokens. @param amount The amount of the underlying token to deposit. @param to The address to receive shares corresponding to the deposit @return shares The shares in the vault credited to `to` */ function deposit(uint256 amount, address to) public returns (uint256 shares); /** @notice Mint an exact amount of shares for a variable amount of underlying tokens. @param shares The amount of vault shares to mint. @param to The address to receive shares corresponding to the mint. @return amount The amount of the underlying tokens deposited from the mint call. */ function mint(uint256 shares, address to) public returns (uint256 amount); /** @notice Withdraw a specific amount of underlying tokens. @param amount The amount of the underlying token to withdraw. @param to The address to receive underlying corresponding to the withdrawal. @param from The address to burn shares from corresponding to the withdrawal. @return shares The shares in the vault burned from sender */ function withdraw(uint256 amount, address to, address from) public returns (uint256 shares); /** @notice Redeem a specific amount of shares for underlying tokens. @param from The address to burn shares from corresponding to the redemption. @param to The address to receive underlying corresponding to the redemption. @param shares The amount of shares to redeem. @return amount The underlying amount transferred to `to`. */ function redeem(uint256 shares, address to, address from) public returns (uint256 amount); /*/////////////////////////////////////////////////////////////// View Functions //////////////////////////////////////////////////////////////*/ /** @notice The underlying token the Vault accepts. @return the ERC20 underlying implementation address. */ function asset() public view returns (EIP20Interface); /** @notice Returns a user's Vault balance in underlying tokens. @param user The user to get the underlying balance of. @return amount The user's Vault balance in underlying tokens. */ function assetsOf(address user) public view returns (uint256 amount); /** @notice Calculates the total amount of underlying tokens the Vault manages. @return The total amount of underlying tokens the Vault manages. */ function totalAssets() public view returns (uint256); /** @notice Returns the value in underlying terms of one vault token. */ function exchangeRate() public view returns (uint256); /** @notice Returns the amount of vault tokens that would be obtained if depositing a given amount of underlying tokens in a `deposit` call. @param amount the input amount of underlying tokens @return shares the corresponding amount of shares out from a deposit call with `amount` in */ function previewDeposit(uint256 amount) public view returns (uint256 shares); /** @notice Returns the amount of underlying tokens that would be deposited if minting a given amount of shares in a `mint` call. @param shares the amount of shares from a mint call. @return amount the amount of underlying tokens corresponding to the mint call */ function previewMint(uint256 shares) public view returns (uint256 amount); /** @notice Returns the amount of vault tokens that would be burned if withdrawing a given amount of underlying tokens in a `withdraw` call. @param amount the input amount of underlying tokens @return shares the corresponding amount of shares out from a withdraw call with `amount` in */ function previewWithdraw(uint256 amount) public view returns (uint256 shares); /** @notice Returns the amount of underlying tokens that would be obtained if redeeming a given amount of shares in a `redeem` call. @param shares the amount of shares from a redeem call. @return amount the amount of underlying tokens corresponding to the redeem call */ function previewRedeem(uint256 shares) public view returns (uint256 amount); /** @notice Returns the max deposit amount for a recipient @param to the deposit recipient @return amount the max input amount for deposit for a user */ function maxDeposit(address to) public view returns (uint256 amount); /** @notice Returns the max mint shares for a recipient @param to the mint recipient @return shares the max shares for mint for a user */ function maxMint(address to) public view returns (uint256 shares); /** @notice Returns the max withdraw amount for a user @param from the withdraw source @return amount the max amount out for withdraw for a user */ function maxWithdraw(address from) public view returns (uint256 amount); /** @notice Returns the max redeem shares for a user @param from the redeem source @return shares the max shares out for redeem for a user */ function maxRedeem(address from) public view returns (uint256 shares); }
{ "metadata": { "useLiteralContent": true }, "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"cashPrior","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"interestAccumulated","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"borrowIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalBorrows","type":"uint256"}],"name":"AccrueInterest","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"borrower","type":"address"},{"indexed":false,"internalType":"uint256","name":"borrowAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"accountBorrows","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalBorrows","type":"uint256"}],"name":"Borrow","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"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":"contract ComptrollerInterface","name":"oldComptroller","type":"address"},{"indexed":false,"internalType":"contract ComptrollerInterface","name":"newComptroller","type":"address"}],"name":"NewComptroller","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"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"},{"constant":true,"inputs":[],"name":"PRECISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes","name":"data","type":"bytes"}],"name":"_becomeImplementation","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"compLikeDelegatee","type":"address"}],"name":"_delegateCompLikeTo","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"_prepare","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"reduceAmount","type":"uint256"}],"name":"_reduceReserves","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"newAdminFeeMantissa","type":"uint256"}],"name":"_setAdminFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"implementation_","type":"address"},{"internalType":"bool","name":"allowResign","type":"bool"},{"internalType":"bytes","name":"becomeImplementationData","type":"bytes"}],"name":"_setImplementationSafe","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"contract InterestRateModel","name":"newInterestRateModel","type":"address"}],"name":"_setInterestRateModel","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"}],"name":"_setNameAndSymbol","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"newReserveFactorMantissa","type":"uint256"}],"name":"_setReserveFactor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"withdrawAmount","type":"uint256"}],"name":"_withdrawAdminFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"withdrawAmount","type":"uint256"}],"name":"_withdrawFuseFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"accrualBlockNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"accrueInterest","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"adminFeeMantissa","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOfUnderlying","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"borrowAmount","type":"uint256"}],"name":"borrow","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"borrowBalanceCurrent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"borrowBalanceStored","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"borrowIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"borrowRatePerBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"comptroller","outputs":[{"internalType":"contract ComptrollerInterface","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"exchangeRateCurrent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"exchangeRateStored","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"fuseFeeMantissa","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"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"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getCash","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"implementation","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"contract ComptrollerInterface","name":"comptroller_","type":"address"},{"internalType":"contract InterestRateModel","name":"interestRateModel_","type":"address"},{"internalType":"uint256","name":"initialExchangeRateMantissa_","type":"uint256"},{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"},{"internalType":"uint8","name":"decimals_","type":"uint8"},{"internalType":"uint256","name":"reserveFactorMantissa_","type":"uint256"},{"internalType":"uint256","name":"adminFeeMantissa_","type":"uint256"}],"name":"initialize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"underlying_","type":"address"},{"internalType":"contract ComptrollerInterface","name":"comptroller_","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":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"interestRateModel","outputs":[{"internalType":"contract InterestRateModel","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isCEther","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isCToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"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"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"mintAmount","type":"uint256"}],"name":"mint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"plugin","outputs":[{"internalType":"contract IERC4626Draft","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"protocolSeizeShareMantissa","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"redeemTokens","type":"uint256"}],"name":"redeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"redeemAmount","type":"uint256"}],"name":"redeemUnderlying","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"repayAmount","type":"uint256"}],"name":"repayBorrow","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"borrower","type":"address"},{"internalType":"uint256","name":"repayAmount","type":"uint256"}],"name":"repayBorrowBehalf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"reserveFactorMantissa","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"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"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"supplyRatePerBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalAdminFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalBorrows","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"totalBorrowsCurrent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalFuseFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalReserves","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"src","type":"address"},{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"underlying","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"}]
Contract Creation Code
6080604052615ffd806100136000396000f3fe60806040526004361061038c5760003560e01c80638d02d9a1116101dc578063b2a02ff111610102578063dd62ed3e116100a0578063f5e3c4621161006f578063f5e3c46214610999578063f8f9da28146109b9578063fca7820b146109ce578063fe9c44ae146109ee5761038c565b8063dd62ed3e1461092f578063ef01df4f1461094f578063f2b3abbd14610964578063f3fdb15a146109845761038c565b8063c5ebeaec116100dc578063c5ebeaec146108c5578063db006a75146108e5578063dbfe7c1914610905578063dc028ab11461091a5761038c565b8063b2a02ff114610860578063bd6d894d14610880578063c37f68e2146108955761038c565b8063a0b0d2891161017a578063aa5af0fd11610149578063aa5af0fd1461080c578063aaf5eb6814610821578063ac784ddc14610836578063ae9d70b01461084b5761038c565b8063a0b0d28914610797578063a6afed95146107b7578063a7b820df146107cc578063a9059cbb146107ec5761038c565b806395d89b41116101b657806395d89b411461072257806395dd919314610737578063a03dce8d14610757578063a0712d68146107775761038c565b80638d02d9a1146106d85780638f840ddd146106ed57806391dd36c6146107025761038c565b80633b1d21a2116102c157806361feacff1161025f57806370a082311161022e57806370a082311461066357806373acee98146106835780637f1e06be14610698578063852a12e3146106b85761038c565b806361feacff1461060f5780636752e702146106245780636c540baf146106395780636f307dc31461064e5761038c565b806356e677281161029b57806356e677281461058b5780635c60da1b146105ab5780635fe3b567146105cd578063601a0bf1146105ef5761038c565b80633b1d21a21461054157806347bd37181461055657806350d85b731461056b5761038c565b8063182df0f51161032e5780632608f818116103085780632608f818146104bf578063313ce567146104df57806334154d4c146105015780633af9e669146105215761038c565b8063182df0f5146104825780631db789441461049757806323b872dd1461049f5761038c565b80630f8855e81161036a5780630f8855e814610416578063173b99041461043857806317bfdfbc1461044d57806318160ddd1461046d5761038c565b806306fdde0314610391578063095ea7b3146103bc5780630e752702146103e9575b600080fd5b34801561039d57600080fd5b506103a6610a03565b6040516103b39190615c18565b60405180910390f35b3480156103c857600080fd5b506103dc6103d7366004615389565b610a8e565b6040516103b39190615c0a565b3480156103f557600080fd5b506104096104043660046155b2565b610afc565b6040516103b39190615dc2565b34801561042257600080fd5b5061043661043136600461545c565b610b12565b005b34801561044457600080fd5b50610409610cae565b34801561045957600080fd5b50610409610468366004615137565b610cb4565b34801561047957600080fd5b50610409610d02565b34801561048e57600080fd5b50610409610d08565b610436610d4c565b3480156104ab57600080fd5b506103dc6104ba3660046151ad565b610eac565b3480156104cb57600080fd5b506104096104da366004615389565b610eda565b3480156104eb57600080fd5b506104f4610ef0565b6040516103b39190615e73565b34801561050d57600080fd5b5061043661051c36600461555a565b610ef9565b34801561052d57600080fd5b5061040961053c366004615137565b610f3d565b34801561054d57600080fd5b50610409610fbe565b34801561056257600080fd5b50610409610fcd565b34801561057757600080fd5b506104366105863660046151fa565b610fd3565b34801561059757600080fd5b506104366105a636600461541a565b61103e565b3480156105b757600080fd5b506105c06112cb565b6040516103b39190615a00565b3480156105d957600080fd5b506105e26112da565b6040516103b39190615c29565b3480156105fb57600080fd5b5061040961060a3660046155b2565b6112e9565b34801561061b57600080fd5b5061040961133a565b34801561063057600080fd5b50610409611340565b34801561064557600080fd5b5061040961134b565b34801561065a57600080fd5b506105c0611351565b34801561066f57600080fd5b5061040961067e366004615137565b611360565b34801561068f57600080fd5b5061040961137b565b3480156106a457600080fd5b506104366106b3366004615137565b6113c0565b3480156106c457600080fd5b506104096106d33660046155b2565b611442565b3480156106e457600080fd5b5061040961144d565b3480156106f957600080fd5b50610409611453565b34801561070e57600080fd5b5061040961071d3660046155b2565b611459565b34801561072e57600080fd5b506103a6611496565b34801561074357600080fd5b50610409610752366004615137565b6114f1565b34801561076357600080fd5b506104096107723660046155b2565b611536565b34801561078357600080fd5b506104096107923660046155b2565b611573565b3480156107a357600080fd5b506104366107b23660046152bd565b61157f565b3480156107c357600080fd5b506104096116b1565b3480156107d857600080fd5b506104096107e73660046155b2565b61180c565b3480156107f857600080fd5b506103dc610807366004615389565b611849565b34801561081857600080fd5b50610409611876565b34801561082d57600080fd5b5061040961187c565b34801561084257600080fd5b506103dc611888565b34801561085757600080fd5b5061040961188d565b34801561086c57600080fd5b5061040961087b3660046151ad565b61193a565b34801561088c57600080fd5b5061040961195e565b3480156108a157600080fd5b506108b56108b0366004615137565b6119a4565b6040516103b39493929190615e65565b3480156108d157600080fd5b506104096108e03660046155b2565b611a39565b3480156108f157600080fd5b506104096109003660046155b2565b611a44565b34801561091157600080fd5b50610409611a4f565b34801561092657600080fd5b50610409611a55565b34801561093b57600080fd5b5061040961094a366004615173565b611a5b565b34801561095b57600080fd5b506105e2611a86565b34801561097057600080fd5b5061040961097f36600461553c565b611a95565b34801561099057600080fd5b506105e2611acf565b3480156109a557600080fd5b506104096109b43660046153b9565b611ade565b3480156109c557600080fd5b50610409611af6565b3480156109da57600080fd5b506104096109e93660046155b2565b611b47565b3480156109fa57600080fd5b506103dc611b84565b6002805460408051602060018416156101000260001901909316849004601f81018490048402820184019092528181529291830182828015610a865780601f10610a5b57610100808354040283529160200191610a86565b820191906000526020600020905b815481529060010190602001808311610a6957829003601f168201915b505050505081565b3360008181526013602090815260408083206001600160a01b03871680855292528083208590555191929182907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610ae8908790615dc2565b60405180910390a360019150505b92915050565b600080610b0883611b89565b509150505b919050565b3373a731585ab05fc9f83555cf9bff8f58ee94e18f8514610b4e5760405162461bcd60e51b8152600401610b4590615cd2565b60405180910390fd5b600b54158015610b5e5750600c54155b610b7a5760405162461bcd60e51b8152600401610b4590615d12565b600786905585610b9c5760405162461bcd60e51b8152600401610b4590615c72565b6000610ba789611bec565b90508015610bc75760405162461bcd60e51b8152600401610b4590615d52565b610bcf611cef565b600b55670de0b6b3a7640000600c55610be788611cf3565b90508015610c075760405162461bcd60e51b8152600401610b4590615d72565b8551610c1a906002906020890190614de9565b508451610c2e906003906020880190614de9565b506004805460ff191660ff8616179055610c4783611f43565b90508015610c675760405162461bcd60e51b8152600401610b4590615cb2565b610c7082611fec565b90508015610c905760405162461bcd60e51b8152600401610b4590615d02565b50506001805460ff60b01b1916600160b01b17905550505050505050565b600a5481565b600080610cc08161210f565b6000610cca6116b1565b14610ce75760405162461bcd60e51b8152600401610b4590615c62565b610cf0836114f1565b91505b610cfc816121b6565b50919050565b60115481565b6000806000610d15612221565b90925090506000826003811115610d2857fe5b14610d455760405162461bcd60e51b8152600401610b4590615d82565b9150505b90565b333014801590610ddd5750600560009054906101000a90046001600160a01b03166001600160a01b031663dd5cd22c6040518163ffffffff1660e01b815260040160206040518083038186803b158015610da557600080fd5b505afa158015610db9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610ddd91908101906153fc565b15610eaa57600080546040516345cc970560e01b8152829160609173a731585ab05fc9f83555cf9bff8f58ee94e18f85916345cc970591610e2a916001600160a01b031690600401615a00565b60006040518083038186803b158015610e4257600080fd5b505afa158015610e56573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610e7e9190810190615262565b60005492955090935091506001600160a01b03808516911614610ea657610ea68383836122e1565b5050505b565b600080610eb88161210f565b6000610ec633878787612470565b149150610ed2816121b6565b509392505050565b600080610ee784846126f8565b50949350505050565b60045460ff1681565b610f0161275d565b610f1d5760405162461bcd60e51b8152600401610b4590615cd2565b610f2960028585614e63565b50610f3660038383614e63565b5050505050565b6000610f47614ed1565b6040518060200160405280610f5a61195e565b90526001600160a01b038416600090815260126020526040812054919250908190610f869084906128fe565b90925090506000826003811115610f9957fe5b14610fb65760405162461bcd60e51b8152600401610b4590615cf2565b949350505050565b6000610fc8612952565b905090565b600d5481565b610fdb61275d565b610ff75760405162461bcd60e51b8152600401610b4590615cd2565b611038848484848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506122e192505050565b50505050565b3330148061104f575061104f61275d565b61105857600080fd5b600061106682840184615137565b90506001600160a01b03811661108e5760405162461bcd60e51b8152600401610b4590615cc2565b6016546001600160a01b03161561119b576016546040516370a0823160e01b81526001600160a01b039091169063ba0876529082906370a08231906110d7903090600401615a00565b60206040518083038186803b1580156110ef57600080fd5b505afa158015611103573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061112791908101906155d0565b30306040518463ffffffff1660e01b815260040161114793929190615e06565b602060405180830381600087803b15801561116157600080fd5b505af1158015611175573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061119991908101906155d0565b505b601680546001600160a01b0319166001600160a01b038381169190911790915560155460405163095ea7b360e01b815291169063095ea7b3906111e690849060001990600401615be1565b602060405180830381600087803b15801561120057600080fd5b505af1158015611214573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061123891908101906153fc565b506015546040516370a0823160e01b81526000916001600160a01b0316906370a082319061126a903090600401615a00565b60206040518083038186803b15801561128257600080fd5b505afa158015611296573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506112ba91908101906155d0565b905080156110385761103881612983565b6000546001600160a01b031681565b6005546001600160a01b031681565b6000806112f58161210f565b60006112ff6116b1565b905080156113255761131d81601181111561131657fe5b603b612a0b565b925050610cf3565b61132e84612a6b565b925050610cfc816121b6565b600f5481565b666379da05b6000081565b600b5481565b6015546001600160a01b031681565b6001600160a01b031660009081526012602052604090205490565b6000806113878161210f565b60006113916116b1565b146113ae5760405162461bcd60e51b8152600401610b4590615c62565b600d5491506113bc816121b6565b5090565b6113c861275d565b6113e45760405162461bcd60e51b8152600401610b4590615cd2565b6015546040516317066a5760e21b81526001600160a01b0390911690635c19a95c90611414908490600401615a00565b600060405180830381600087803b15801561142e57600080fd5b505af1158015610f36573d6000803e3d6000fd5b6000610af682612b23565b60085481565b600e5481565b6000806114658161210f565b600061146f6116b1565b9050801561148d5761131d81601181111561148657fe5b6052612a0b565b61132e84611fec565b6003805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610a865780601f10610a5b57610100808354040283529160200191610a86565b60008060006114ff84612b63565b9092509050600082600381111561151257fe5b1461152f5760405162461bcd60e51b8152600401610b4590615d92565b9392505050565b6000806115428161210f565b600061154c6116b1565b9050801561156a5761131d81601181111561156357fe5b6033612a0b565b61132e84612c17565b600080610b0883612c98565b60006702c68af0bb14000090506000886001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b1580156115c757600080fd5b505afa1580156115db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506115ff919081019061561e565b90506116118888848989868a8a610b12565b601580546001600160a01b0319166001600160a01b038b81169190911791829055604080516318160ddd60e01b8152905192909116916318160ddd91600480820192602092909190829003018186803b15801561166d57600080fd5b505afa158015611681573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506116a591908101906155d0565b50505050505050505050565b6000806116bc611cef565b905080600b5414156116d2576000915050610d49565b60006116dc612952565b90506000600660009054906101000a90046001600160a01b03166001600160a01b03166315f2405383600d54611721600e5461171c600f54601054612cd8565b612cd8565b6040518463ffffffff1660e01b815260040161173f93929190615e57565b60206040518083038186803b15801561175757600080fd5b505afa15801561176b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061178f91908101906155d0565b905065048c273950008111156117b75760405162461bcd60e51b8152600401610b4590615ce2565b6000806117c685600b54612d0e565b909250905060008260038111156117d957fe5b146117f65760405162461bcd60e51b8152600401610b4590615da2565b61180285858584612d31565b9550505050505090565b6000806118188161210f565b60006118226116b1565b905080156118405761131d81601181111561183957fe5b6037612a0b565b61132e84612efb565b6000806118558161210f565b600061186333338787612470565b14915061186f816121b6565b5092915050565b600c5481565b670de0b6b3a764000081565b600081565b6006546000906001600160a01b031663b81688166118a9612952565b600d546118c0600e5461171c600f54601054612cd8565b600854600954600a5401016040518563ffffffff1660e01b81526004016118ea9493929190615e65565b60206040518083038186803b15801561190257600080fd5b505afa158015611916573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610fc891908101906155d0565b600060016119478161210f565b61195333868686612fef565b9150610ed2816121b6565b60008061196a8161210f565b60006119746116b1565b146119915760405162461bcd60e51b8152600401610b4590615c62565b611999610d08565b91506113bc816121b6565b6001600160a01b0381166000908152601260205260408120548190819081908180806119cf89612b63565b9350905060008160038111156119e157fe5b146119ff5760095b975060009650869550859450611a329350505050565b611a07612221565b925090506000816003811115611a1957fe5b14611a255760096119e9565b5060009650919450925090505b9193509193565b6000610af682613394565b6000610af6826133d2565b60095481565b60105481565b6001600160a01b03918216600090815260136020908152604080832093909416825291909152205490565b6016546001600160a01b031681565b600080611aa06116b1565b90508015611ac657611abe816011811115611ab757fe5b604b612a0b565b915050610b0d565b61152f83611cf3565b6006546001600160a01b031681565b600080611aec85858561340b565b5095945050505050565b6006546000906001600160a01b03166315f24053611b12612952565b600d54611b29600e5461171c600f54601054612cd8565b6040518463ffffffff1660e01b81526004016118ea93929190615e57565b600080611b538161210f565b6000611b5d6116b1565b90508015611b7b5761131d816011811115611b7457fe5b6059612a0b565b61132e84611f43565b600181565b6000806000611b978161210f565b6000611ba16116b1565b90508015611bcc57611bbf816011811115611bb857fe5b6041612a0b565b935060009250611bdd9050565b611bd7333387613503565b93509350505b611be6816121b6565b50915091565b600080600560009054906101000a90046001600160a01b03169050826001600160a01b0316627e3dd26040518163ffffffff1660e01b815260040160206040518083038186803b158015611c3f57600080fd5b505afa158015611c53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611c7791908101906153fc565b611c935760405162461bcd60e51b8152600401610b4590615d42565b600580546001600160a01b0319166001600160a01b0385161790556040517f7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d90611ce09083908690615c37565b60405180910390a1600061152f565b4390565b600080611cfe61275d565b611d0e57611abe6001604d612a0b565b611d16611cef565b600b5414611d2a57611abe600a604c612a0b565b600660009054906101000a90046001600160a01b03169050826001600160a01b0316632191f92a6040518163ffffffff1660e01b815260040160206040518083038186803b158015611d7b57600080fd5b505afa158015611d8f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611db391908101906153fc565b611dcf5760405162461bcd60e51b8152600401610b4590615d42565b600680546001600160a01b0319166001600160a01b0385161790556040517fedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f92690611e1c9083908690615c37565b60405180910390a16001600160a01b03811615611eb75760408051600481526024810182526020810180516001600160e01b0316636cc1140b60e11b17905290516001600160a01b03831691611e71916159f4565b6000604051808303816000865af19150503d8060008114611eae576040519150601f19603f3d011682016040523d82523d6000602084013e611eb3565b606091505b5050505b60408051600481526024810182526020810180516001600160e01b031663742a137b60e11b17905290516001600160a01b03851691611ef5916159f4565b6000604051808303816000865af19150503d8060008114611f32576040519150601f19603f3d011682016040523d82523d6000602084013e611f37565b606091505b506000915061152f9050565b6000611f4d61275d565b611f6457611f5d6001605a612a0b565b9050610b0d565b611f6c611cef565b600b5414611f8057611f5d600a605b612a0b565b670de0b6b3a7640000611fa0611f9884600854612cd8565b600954612cd8565b1115611fb257611f5d6002605c612a0b565b600a8054908390556040517faaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f82146090611ce09083908690615e21565b6000611ff6611cef565b600b541461200a57611f5d600a6054612a0b565b60001982141561201a5760085491505b60006120246137f0565b9050670de0b6b3a764000061204461203e600a5486612cd8565b83612cd8565b111561205657611abe60026055612a0b565b82600854146120bb5761206761275d565b61207757611abe60016053612a0b565b60088054908490556040517fcdd0b588250e1398549f79cfdb8217c186688822905d6715b0834ea1c865594a906120b19083908790615e21565b60405180910390a1505b80600954146121085760098054908290556040517f92eef861b6533b7d3417f39c2ad7b460eed4e88a32fa3604f30e718b7602e7dc906120fe9083908590615e21565b60405180910390a1505b600061152f565b600154600160b01b900460ff166121385760405162461bcd60e51b8152600401610b4590615d22565b806121a657600560009054906101000a90046001600160a01b03166001600160a01b031663c90c20b16040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561218d57600080fd5b505af11580156121a1573d6000803e3d6000fd5b505050505b506001805460ff60b01b19169055565b6001805460ff60b01b1916600160b01b1790558061221e57600560009054906101000a90046001600160a01b03166001600160a01b031663632e51426040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561142e57600080fd5b50565b60115460009081908061223c575050600754600091506122dd565b6000612246612952565b90506000612252614ed1565b600061227484600d5461226f600e5461171c600f54601054612cd8565b61383f565b93509050600081600381111561228657fe5b1461229b579550600094506122dd9350505050565b6122a5838661388b565b9250905060008160038111156122b757fe5b146122cc579550600094506122dd9350505050565b50516000955093506122dd92505050565b9091565b6000546040516338e6a07360e11b815273a731585ab05fc9f83555cf9bff8f58ee94e18f85916371cd40e691612327916001600160a01b03169087908790600401615b26565b60206040518083038186803b15801561233f57600080fd5b505afa158015612353573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061237791908101906153fc565b6123935760405162461bcd60e51b8152600401610b4590615c92565b81156123a1576123a161393b565b600080546001600160a01b038581166001600160a01b03198316179092556040519116906124249030906123d9908590602401615c18565b60408051601f19818403018152918152602080830180516001600160e01b0316630adccee560e31b17905281518083019092526007825266216265636f6d6560c81b90820152613940565b506000546040517fd604de94d45953f9138079ec1b82d533cb2160c906d1076d1f7ed54befbca97a916124629184916001600160a01b031690615a6b565b60405180910390a150505050565b6005546040516317b9b84b60e31b815260009182916001600160a01b039091169063bdcdc258906124ab903090899089908990600401615afe565b602060405180830381600087803b1580156124c557600080fd5b505af11580156124d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506124fd91908101906155d0565b9050801561251a576125126003605d836139dd565b915050610fb6565b836001600160a01b0316856001600160a01b03161415612540576125126002605e612a0b565b60006001600160a01b03878116908716141561255f5750600019612587565b506001600160a01b038086166000908152601360209081526040808320938a16835292905220545b6000806000806125978589612d0e565b909450925060008460038111156125aa57fe5b146125c8576125bb6009605e612a0b565b9650505050505050610fb6565b6001600160a01b038a166000908152601260205260409020546125eb9089612d0e565b909450915060008460038111156125fe57fe5b1461260f576125bb6009605f612a0b565b6001600160a01b0389166000908152601260205260409020546126329089613a5f565b9094509050600084600381111561264557fe5b14612656576125bb60096060612a0b565b6001600160a01b03808b16600090815260126020526040808220859055918b1681522081905560001985146126ae576001600160a01b03808b166000908152601360209081526040808320938f168352929052208390555b886001600160a01b03168a6001600160a01b0316600080516020615f9b8339815191528a6040516126df9190615dc2565b60405180910390a35060009a9950505050505050505050565b60008060006127068161210f565b60006127106116b1565b9050801561273b5761272e81601181111561272757fe5b6040612a0b565b93506000925061274c9050565b612746338787613503565b93509350505b612755816121b6565b509250929050565b600554604080516303e1469160e61b815290516000926001600160a01b031691829163f851a44091600480820192602092909190829003018186803b1580156127a557600080fd5b505afa1580156127b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506127dd9190810190615155565b6001600160a01b0316336001600160a01b03161480156128695750806001600160a01b0316630a755ec26040518163ffffffff1660e01b815260040160206040518083038186803b15801561283157600080fd5b505afa158015612845573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061286991908101906153fc565b80610d4557503373a731585ab05fc9f83555cf9bff8f58ee94e18f85148015610d455750806001600160a01b0316632f1069ba6040518163ffffffff1660e01b815260040160206040518083038186803b1580156128c657600080fd5b505afa1580156128da573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610d4591908101906153fc565b600080600061290b614ed1565b6129158686613a85565b9092509050600082600381111561292857fe5b14612939575091506000905061294b565b600061294482613aed565b9350935050505b9250929050565b6016546040516302c62fa160e41b81526000916001600160a01b031690632c62fa10906118ea903090600401615a00565b601654604051636e553f6560e01b81526001600160a01b0390911690636e553f65906129b59084903090600401615dd0565b602060405180830381600087803b1580156129cf57600080fd5b505af11580156129e3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612a0791908101906155d0565b5050565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0836011811115612a3a57fe5b836063811115612a4657fe5b6000604051612a5793929190615e2f565b60405180910390a182601181111561152f57fe5b600080612a7661275d565b612a8657611abe6001603c612a0b565b612a8e611cef565b600b5414612aa257611abe600a603e612a0b565b82612aab612952565b1015612abd57611abe600e603d612a0b565b600e54831115612ad357611abe6002603f612a0b565b612adf600e5484613afc565b600e8190559050612af03384613b36565b7f3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e338483604051611ce093929190615a0e565b600080612b2f8161210f565b6000612b396116b1565b90508015612b575761131d816011811115612b5057fe5b602a612a0b565b61132e33600086613bbc565b6001600160a01b038116600090815260146020526040812080548291829182918291612b9a575060009450849350612c1292505050565b612baa8160000154600c5461403b565b90945092506000846003811115612bbd57fe5b14612bd2575091935060009250612c12915050565b612be083826001015461407a565b90945091506000846003811115612bf357fe5b14612c08575091935060009250612c12915050565b5060009450925050505b915091565b600080612c22611cef565b600b5414612c3657611abe600a6035612a0b565b82612c3f612952565b1015612c5157611abe600e6034612a0b565b601054831115612c6757611abe60026036612a0b565b612c7360105484613afc565b6010819055905061210873a731585ab05fc9f83555cf9bff8f58ee94e18f8584613b36565b6000806000612ca68161210f565b6000612cb06116b1565b90508015612cce57611bbf816011811115612cc757fe5b6020612a0b565b611bd733866140a5565b600061152f8383604051806040016040528060118152602001706164646974696f6e206f766572666c6f7760781b8152506143d8565b600080838311612d2557506000905081830361294b565b5060039050600061294b565b6000612d3b614ed1565b612d53604051806020016040528086815250846143ff565b90506000612d6382600d54614429565b90506000612d7382600d54612cd8565b90506000612d946040518060200160405280600a5481525084600e54614448565b90506000612db5604051806020016040528060095481525085601054614448565b90506000612dd6604051806020016040528060085481525086600f54614448565b90506000612de987600c54600c54614448565b600b8d9055600c819055600d869055600e8590556010849055600f8390556040519091507f4dec04e750ca11537cabcd8a9eab06494de08da3735bc8871cd41250e190bc0490612e40908d90899085908a90615e65565b60405180910390a16006546040516001600160a01b0390911690612e68908c90602401615dc2565b60408051601f198184030181529181526020820180516001600160e01b0316635efd023360e11b17905251612e9d91906159f4565b6000604051808303816000865af19150503d8060008114612eda576040519150601f19603f3d011682016040523d82523d6000602084013e612edf565b606091505b5060009150612eeb9050565b9c9b505050505050505050505050565b600080612f06611cef565b600b5414612f1a57611abe600a6039612a0b565b82612f23612952565b1015612f3557611abe600e6038612a0b565b600f54831115612f4b57611abe6002603a612a0b565b612f57600f5484613afc565b905080600f81905550612108600560009054906101000a90046001600160a01b03166001600160a01b031663f851a4406040518163ffffffff1660e01b815260040160206040518083038186803b158015612fb157600080fd5b505afa158015612fc5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612fe99190810190615155565b84613b36565b60055460405163d02f735160e01b815260009182916001600160a01b039091169063d02f73519061302c9030908a908a908a908a90600401615abc565b602060405180830381600087803b15801561304657600080fd5b505af115801561305a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061307e91908101906155d0565b90508015613093576125126003601d836139dd565b846001600160a01b0316846001600160a01b031614156130b9576125126006601e612a0b565b6130c1614ee4565b6001600160a01b0385166000908152601260205260409020546130e49085612d0e565b60208301819052828260038111156130f857fe5b600381111561310357fe5b905250600090508151600381111561311757fe5b14613141576131386009601c8360000151600381111561313357fe5b6139dd565b92505050610fb6565b613160846040518060200160405280666379da05b60000815250614470565b60808201819052613172908590613afc565b606082015261317f612221565b60c083018190528282600381111561319357fe5b600381111561319e57fe5b90525060009050815160038111156131b257fe5b146131cf5760405162461bcd60e51b8152600401610b4590615d82565b6131ef60405180602001604052808360c001518152508260800151614429565b60a08201819052600e5461320291612cd8565b60e082015260115460808201516132199190613afc565b6101008201526001600160a01b03861660009081526012602052604090205460608201516132479190613a5f565b604083018190528282600381111561325b57fe5b600381111561326657fe5b905250600090508151600381111561327a57fe5b14613296576131386009601b8360000151600381111561313357fe5b60e0810151600e556101008101516011556020808201516001600160a01b038088166000818152601290945260408085209390935582850151918a168085529383902091909155606084015191519091600080516020615f9b833981519152916133009190615dc2565b60405180910390a3306001600160a01b0316856001600160a01b0316600080516020615f9b833981519152836080015160405161333d9190615dc2565b60405180910390a360a081015160e08201516040517fa91e67c5ea634cd43a12c5a482724b03de01e85ca68702a53d0c2f45cb7c1dc59261337f923092615bfc565b60405180910390a16000979650505050505050565b6000806133a08161210f565b60006133aa6116b1565b905080156133c85761131d8160118111156133c157fe5b600a612a0b565b61132e3385614498565b6000806133de8161210f565b60006133e86116b1565b905080156133ff5761131d816011811115612b5057fe5b61132e33856000613bbc565b60008060006134198161210f565b60006134236116b1565b9050801561344e5761344181601181111561343a57fe5b6011612a0b565b9350600092506134f19050565b846001600160a01b031663a6afed956040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561348957600080fd5b505af115801561349d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506134c191908101906155d0565b905080156134df576134418160118111156134d857fe5b6012612a0b565b6134eb338888886147ca565b93509350505b6134fa816121b6565b50935093915050565b600554604051631200453160e11b8152600091829182916001600160a01b0316906324008a629061353e9030908a908a908a90600401615afe565b602060405180830381600087803b15801561355857600080fd5b505af115801561356c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061359091908101906155d0565b905080156135b2576135a560036043836139dd565b9250600091506137e89050565b6135ba611cef565b600b54146135ce576135a5600a6044612a0b565b6135d6614f31565b6001600160a01b038616600090815260146020526040902060010154606082015261360086612b63565b608083018190526020830182600381111561361757fe5b600381111561362257fe5b905250600090508160200151600381111561363957fe5b1461366357613655600960428360200151600381111561313357fe5b9350600092506137e8915050565b60001985141561367c5760808101516040820152613684565b604081018590525b613692878260400151614c11565b60e0820181905260808201516136a791612d0e565b60a08301819052602083018260038111156136be57fe5b60038111156136c957fe5b90525060009050816020015160038111156136e057fe5b146136fd5760405162461bcd60e51b8152600401610b4590615d62565b61370d600d548260e00151612d0e565b60c083018190526020830182600381111561372457fe5b600381111561372f57fe5b905250600090508160200151600381111561374657fe5b146137635760405162461bcd60e51b8152600401610b4590615d62565b60a0810180516001600160a01b03881660009081526014602052604090819020918255600c5460019092019190915560c0830151600d81905560e0840151925191517f1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a1936137d4938c938c93615bac565b60405180910390a160e00151600093509150505b935093915050565b600073a731585ab05fc9f83555cf9bff8f58ee94e18f856001600160a01b031663dd86fea16040518163ffffffff1660e01b815260040160206040518083038186803b15801561190257600080fd5b60008060008061384f8787613a5f565b9092509050600082600381111561386257fe5b1461387357509150600090506137e8565b61387d8186612d0e565b935093505050935093915050565b6000613895614ed1565b6000806138aa86670de0b6b3a764000061403b565b909250905060008260038111156138bd57fe5b146138dc5750604080516020810190915260008152909250905061294b565b6000806138e9838861407a565b909250905060008260038111156138fc57fe5b1461391e5750604080516020810190915260008152909450925061294b915050565b604080516020810190915290815260009890975095505050505050565b610eaa565b606060006060856001600160a01b03168560405161395e91906159f4565b6000604051808303816000865af19150503d806000811461399b576040519150601f19603f3d011682016040523d82523d6000602084013e6139a0565b606091505b5091509150816139d4578051156139ba5780518082602001fd5b8360405162461bcd60e51b8152600401610b459190615c18565b95945050505050565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0846011811115613a0c57fe5b846063811115613a1857fe5b84604051613a2893929190615e57565b60405180910390a16003846011811115613a3e57fe5b14613a5457836011811115613a4f57fe5b610fb6565b506103e80192915050565b600080838301848110613a775760009250905061294b565b50600291506000905061294b565b6000613a8f614ed1565b600080613aa086600001518661403b565b90925090506000826003811115613ab357fe5b14613ad25750604080516020810190915260008152909250905061294b565b60408051602081019091529081526000969095509350505050565b51670de0b6b3a7640000900490565b600061152f8383604051806040016040528060158152602001747375627472616374696f6e20756e646572666c6f7760581b815250614cbd565b601654604051632d182be560e21b81526001600160a01b039091169063b460af9490613b6a90849086903090600401615dde565b602060405180830381600087803b158015613b8457600080fd5b505af1158015613b98573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610ea691908101906155d0565b6000821580613bc9575081155b613be55760405162461bcd60e51b8152600401610b4590615c82565b613bed614f77565b613bf5612221565b6040830181905260208301826003811115613c0c57fe5b6003811115613c1757fe5b9052506000905081602001516003811115613c2e57fe5b14613c5257613c4a6009602e8360200151600381111561313357fe5b91505061152f565b8315613cd3576060810184905260408051602081018252908201518152613c7990856128fe565b6080830181905260208301826003811115613c9057fe5b6003811115613c9b57fe5b9052506000905081602001516003811115613cb257fe5b14613cce57613c4a6009602c8360200151600381111561313357fe5b613d4c565b613cef8360405180602001604052808460400151815250614ce9565b6060830181905260208301826003811115613d0657fe5b6003811115613d1157fe5b9052506000905081602001516003811115613d2857fe5b14613d4457613c4a6009602d8360200151600381111561313357fe5b608081018390525b600554606082015160405163eabe7d9160e01b81526000926001600160a01b03169163eabe7d9191613d859130918b9190600401615a86565b602060405180830381600087803b158015613d9f57600080fd5b505af1158015613db3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250613dd791908101906155d0565b90508015613df557613dec6003602b836139dd565b9250505061152f565b613dfd611cef565b600b5414613e1157613dec600a602f612a0b565b613e216011548360600151612d0e565b60a0840181905260208401826003811115613e3857fe5b6003811115613e4357fe5b9052506000905082602001516003811115613e5a57fe5b14613e7657613dec600960318460200151600381111561313357fe5b6001600160a01b0386166000908152601260205260409020546060830151613e9e9190612d0e565b60c0840181905260208401826003811115613eb557fe5b6003811115613ec057fe5b9052506000905082602001516003811115613ed757fe5b14613ef357613dec600960308460200151600381111561313357fe5b8160800151613f00612952565b1015613f1257613dec600e6032612a0b565b613f20868360800151613b36565b60a082015160115560c08201516001600160a01b0387166000818152601260205260409081902092909255606084015191513092600080516020615f9b83398151915291613f6e9190615dc2565b60405180910390a3608082015160608301516040517fe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a92992613fb0928a92615a0e565b60405180910390a1600554608083015160608401516040516351dff98960e01b81526001600160a01b03909316926351dff98992613ff69230928c929190600401615aa1565b600060405180830381600087803b15801561401057600080fd5b505af1158015614024573d6000803e3d6000fd5b5060009250614031915050565b9695505050505050565b6000808361404e5750600090508061294b565b8383028385828161405b57fe5b041461406f5750600291506000905061294b565b60009250905061294b565b6000808261408e575060019050600061294b565b600083858161409957fe5b04915091509250929050565b600554604051634ef4c3e160e01b8152600091829182916001600160a01b031690634ef4c3e1906140de90309089908990600401615b4e565b602060405180830381600087803b1580156140f857600080fd5b505af115801561410c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061413091908101906155d0565b905080156141525761414560036021836139dd565b92506000915061294b9050565b61415a611cef565b600b541461416e57614145600a6024612a0b565b614176614f77565b61417e612221565b604083018190526020830182600381111561419557fe5b60038111156141a057fe5b90525060009050816020015160038111156141b757fe5b146141e1576141d3600960238360200151600381111561313357fe5b93506000925061294b915050565b6141eb8686614c11565b60c082018190526040805160208101825290830151815261420c9190614ce9565b606083018190526020830182600381111561422357fe5b600381111561422e57fe5b905250600090508160200151600381111561424557fe5b146142625760405162461bcd60e51b8152600401610b4590615db2565b6142726011548260600151612cd8565b60808201526001600160a01b038616600090815260126020526040902054606082015161429f9190612cd8565b60a0820181905260808201516011556001600160a01b038716600090815260126020526040908190209190915560c0820151606083015191517f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f92614308928a92909190615bfc565b60405180910390a1856001600160a01b0316306001600160a01b0316600080516020615f9b83398151915283606001516040516143459190615dc2565b60405180910390a360055460c082015160608301516040516341c728b960e01b81526001600160a01b03909316926341c728b99261438b9230928c929190600401615b91565b600060405180830381600087803b1580156143a557600080fd5b505af11580156143b9573d6000803e3d6000fd5b50600092506143c6915050565b8160c001519350935050509250929050565b60008383018285821015610ee75760405162461bcd60e51b8152600401610b459190615c18565b614407614ed1565b6040518060200160405280614420856000015185614d00565b90529392505050565b6000614433614ed1565b61443d84846143ff565b9050610fb681613aed565b6000614452614ed1565b61445c85856143ff565b90506139d461446a82613aed565b84612cd8565b6000670de0b6b3a7640000614489848460000151614d00565b8161449057fe5b049392505050565b60055460405163368f515360e21b815260009182916001600160a01b039091169063da3d454c906144d190309088908890600401615a86565b602060405180830381600087803b1580156144eb57600080fd5b505af11580156144ff573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061452391908101906155d0565b905080156145405761453860036010836139dd565b915050610af6565b614548611cef565b600b541461455c57614538600a600c612a0b565b6000614566612952565b9050838110156145855761457c600e600b612a0b565b92505050610af6565b61458d614fb5565b61459686612b63565b60208301819052828260038111156145aa57fe5b60038111156145b557fe5b90525060009050815160038111156145c957fe5b146145ee576145e46009808360000151600381111561313357fe5b9350505050610af6565b6145fc816020015186613a5f565b604083018190528282600381111561461057fe5b600381111561461b57fe5b905250600090508151600381111561462f57fe5b1461464b576145e46009600e8360000151600381111561313357fe5b6005546040808301519051631de6c8a560e21b81526001600160a01b039092169163779b22949161468191309190600401615be1565b602060405180830381600087803b15801561469b57600080fd5b505af11580156146af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506146d391908101906155d0565b925082156146e8576145e460036010856139dd565b6146f4600d5486613a5f565b606083018190528282600381111561470857fe5b600381111561471357fe5b905250600090508151600381111561472757fe5b14614743576145e46009600d8360000151600381111561313357fe5b61474d8686613b36565b604080820180516001600160a01b03891660009081526014602052839020908155600c546001909101556060830151600d819055905191517f13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab80926147b6928a928a929190615a36565b60405180910390a160009695505050505050565b600554604051632fe3f38f60e11b8152600091829182916001600160a01b031690635fc7e71e9061480790309088908c908c908c90600401615abc565b602060405180830381600087803b15801561482157600080fd5b505af1158015614835573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061485991908101906155d0565b9050801561487b5761486e60036014836139dd565b925060009150614c089050565b614883611cef565b600b54146148975761486e600a6018612a0b565b61489f611cef565b846001600160a01b0316636c540baf6040518163ffffffff1660e01b815260040160206040518083038186803b1580156148d857600080fd5b505afa1580156148ec573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061491091908101906155d0565b146149215761486e600a6013612a0b565b866001600160a01b0316866001600160a01b031614156149475761486e60066019612a0b565b846149585761486e60076017612a0b565b60001985141561496e5761486e60076016612a0b565b60008061497c898989613503565b909250905081156149ac5761499d82601181111561499657fe5b601a612a0b565b945060009350614c0892505050565b60055460405163c488847b60e01b815260009182916001600160a01b039091169063c488847b906149e59030908c908890600401615b4e565b604080518083038186803b1580156149fc57600080fd5b505afa158015614a10573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250614a3491908101906155ee565b90925090508115614a575760405162461bcd60e51b8152600401610b4590615ca2565b6040516370a0823160e01b815281906001600160a01b038a16906370a0823190614a85908e90600401615a00565b60206040518083038186803b158015614a9d57600080fd5b505afa158015614ab1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250614ad591908101906155d0565b1015614af35760405162461bcd60e51b8152600401610b4590615ca2565b60006001600160a01b038916301415614b1957614b12308d8d85612fef565b9050614b9e565b60405163b2a02ff160e01b81526001600160a01b038a169063b2a02ff190614b49908f908f908790600401615b4e565b602060405180830381600087803b158015614b6357600080fd5b505af1158015614b77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250614b9b91908101906155d0565b90505b8015614bbc5760405162461bcd60e51b8152600401610b4590615c52565b7f298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb528c8c868c86604051614bf3959493929190615b69565b60405180910390a16000975092955050505050505b94509492505050565b6015546040516323b872dd60e01b81526000916001600160a01b0316906323b872dd90614c4690869030908790600401615b4e565b602060405180830381600087803b158015614c6057600080fd5b505af1158015614c74573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250614c9891908101906153fc565b614cb45760405162461bcd60e51b8152600401610b4590615d32565b610cfc82612983565b60008184841115614ce15760405162461bcd60e51b8152600401610b459190615c18565b505050900390565b6000806000614cf6614ed1565b6129158686614d42565b600061152f83836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f77000000000000000000815250614da1565b6000614d4c614ed1565b600080614d61670de0b6b3a76400008761403b565b90925090506000826003811115614d7457fe5b14614d935750604080516020810190915260008152909250905061294b565b61294481866000015161388b565b6000831580614dae575082155b15614dbb5750600061152f565b83830283858281614dc857fe5b04148390610ee75760405162461bcd60e51b8152600401610b459190615c18565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10614e2a57805160ff1916838001178555614e57565b82800160010185558215614e57579182015b82811115614e57578251825591602001919060010190614e3c565b506113bc929150614fde565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10614ea45782800160ff19823516178555614e57565b82800160010185558215614e57579182015b82811115614e57578235825591602001919060010190614eb6565b6040518060200160405280600081525090565b604080516101208101909152806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6040805161010081019091528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6040805160e0810190915280600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b604080516080810190915280600081526020016000815260200160008152602001600081525090565b610d4991905b808211156113bc5760008155600101614fe4565b8035610af681615f62565b8051610af681615f62565b8035610af681615f76565b8051610af681615f76565b60008083601f84011261503657600080fd5b50813567ffffffffffffffff81111561504e57600080fd5b60208301915083600182028301111561294b57600080fd5b600082601f83011261507757600080fd5b815161508a61508582615ea8565b615e81565b915080825260208301602083018583830111156150a657600080fd5b6150b1838284615f2c565b50505092915050565b8035610af681615f7f565b600082601f8301126150d657600080fd5b81356150e461508582615ea8565b9150808252602083016020830185838301111561510057600080fd5b6150b1838284615f20565b8035610af681615f88565b8051610af681615f88565b8035610af681615f91565b8051610af681615f91565b60006020828403121561514957600080fd5b6000610fb68484614ff8565b60006020828403121561516757600080fd5b6000610fb68484615003565b6000806040838503121561518657600080fd5b60006151928585614ff8565b92505060206151a385828601614ff8565b9150509250929050565b6000806000606084860312156151c257600080fd5b60006151ce8686614ff8565b93505060206151df86828701614ff8565b92505060406151f08682870161510b565b9150509250925092565b6000806000806060858703121561521057600080fd5b600061521c8787614ff8565b945050602061522d8782880161500e565b935050604085013567ffffffffffffffff81111561524a57600080fd5b61525687828801615024565b95989497509550505050565b60008060006060848603121561527757600080fd5b60006152838686615003565b935050602061529486828701615019565b925050604084015167ffffffffffffffff8111156152b157600080fd5b6151f086828701615066565b600080600080600080600060e0888a0312156152d857600080fd5b60006152e48a8a614ff8565b97505060206152f58a828b016150ba565b96505060406153068a828b016150ba565b955050606088013567ffffffffffffffff81111561532357600080fd5b61532f8a828b016150c5565b945050608088013567ffffffffffffffff81111561534c57600080fd5b6153588a828b016150c5565b93505060a06153698a828b0161510b565b92505060c061537a8a828b0161510b565b91505092959891949750929550565b6000806040838503121561539c57600080fd5b60006153a88585614ff8565b92505060206151a38582860161510b565b6000806000606084860312156153ce57600080fd5b60006153da8686614ff8565b93505060206153eb8682870161510b565b92505060406151f0868287016150ba565b60006020828403121561540e57600080fd5b6000610fb68484615019565b6000806020838503121561542d57600080fd5b823567ffffffffffffffff81111561544457600080fd5b61545085828601615024565b92509250509250929050565b600080600080600080600080610100898b03121561547957600080fd5b60006154858b8b6150ba565b98505060206154968b828c016150ba565b97505060406154a78b828c0161510b565b965050606089013567ffffffffffffffff8111156154c457600080fd5b6154d08b828c016150c5565b955050608089013567ffffffffffffffff8111156154ed57600080fd5b6154f98b828c016150c5565b94505060a061550a8b828c01615121565b93505060c061551b8b828c0161510b565b92505060e061552c8b828c0161510b565b9150509295985092959890939650565b60006020828403121561554e57600080fd5b6000610fb684846150ba565b6000806000806040858703121561557057600080fd5b843567ffffffffffffffff81111561558757600080fd5b61559387828801615024565b9450945050602085013567ffffffffffffffff81111561524a57600080fd5b6000602082840312156155c457600080fd5b6000610fb6848461510b565b6000602082840312156155e257600080fd5b6000610fb68484615116565b6000806040838503121561560157600080fd5b600061560d8585615116565b92505060206151a385828601615116565b60006020828403121561563057600080fd5b6000610fb6848461512c565b61564581615f0a565b82525050565b61564581615edd565b61564581615ee8565b600061566882615ed0565b6156728185615ed4565b9350615682818560208601615f2c565b61568b81615f58565b9093019392505050565b60006156a082615ed0565b6156aa8185610b0d565b93506156ba818560208601615f2c565b9290920192915050565b61564581615eed565b61564581615f15565b60006156e3600583615ed4565b647365697a6560d81b815260200192915050565b6000615704600383615ed4565b6261636360e81b815260200192915050565b6000615723600983615ed4565b687a65726f207261746560b81b815260200192915050565b6000615748600683615ed4565b6572656465656d60d01b815260200192915050565b600061576a600583615ed4565b64085a5b5c1b60da1b815260200192915050565b600061578b600383615ed4565b624c495160e81b815260200192915050565b60006157aa600e83615ed4565b6d3932b9b2b93b32903330b1ba37b960911b815260200192915050565b60006157d4600683615ed4565b65181030b2323960d11b815260200192915050565b60006157f6600683615ed4565b6510b0b236b4b760d11b815260200192915050565b6000615818600383615ed4565b623137b960e91b815260200192915050565b6000615837600383615ed4565b6218985b60ea1b815260200192915050565b6000615856600383615ed4565b6266656560e81b815260200192915050565b6000615875600483615ed4565b631a5b9a5d60e21b815260200192915050565b6000615895600a83615ed4565b691c994b595b9d195c995960b21b815260200192915050565b60006158bb600983615ed4565b681cd95b990819985a5b60ba1b815260200192915050565b60006158e0600683615ed4565b6536b0b935b2b960d11b815260200192915050565b6000615902600b83615ed4565b6a31b7b6b83a3937b63632b960a91b815260200192915050565b6000615929600583615ed4565b64524550415960d81b815260200192915050565b600061594a600383615ed4565b6269726d60e81b815260200192915050565b6000615969600683615ed4565b6565785261746560d01b815260200192915050565b600061598b600983615ed4565b68189bdc9c9bddd0985b60ba1b815260200192915050565b60006159b0600383615ed4565b6239bab160e91b815260200192915050565b60006159cf600483615ed4565b631352539560e21b815260200192915050565b61564581610d49565b61564581615f04565b600061152f8284615695565b60208101610af6828461564b565b60608101615a1c828661563c565b615a2960208301856159e2565b610fb660408301846159e2565b60808101615a44828761563c565b615a5160208301866159e2565b615a5e60408301856159e2565b6139d460608301846159e2565b60408101615a79828561564b565b61152f602083018461564b565b60608101615a94828661564b565b615a29602083018561563c565b60808101615aaf828761564b565b615a51602083018661563c565b60a08101615aca828861564b565b615ad7602083018761564b565b615ae4604083018661564b565b615af1606083018561564b565b61403160808301846159e2565b60808101615b0c828761564b565b615b19602083018661564b565b615a5e604083018561564b565b60608101615b34828661564b565b615b41602083018561564b565b610fb66040830184615654565b60608101615b5c828661564b565b615a29602083018561564b565b60a08101615b77828861564b565b615b84602083018761564b565b615ae460408301866159e2565b60808101615b9f828761564b565b615a51602083018661564b565b60a08101615bba828861564b565b615bc7602083018761564b565b615bd460408301866159e2565b615af160608301856159e2565b60408101615bef828561564b565b61152f60208301846159e2565b60608101615a1c828661564b565b60208101610af68284615654565b6020808252810161152f818461565d565b60208101610af682846156c4565b60408101615c4582856156c4565b61152f60208301846156c4565b60208082528101610af6816156d6565b60208082528101610af6816156f7565b60208082528101610af681615716565b60208082528101610af68161573b565b60208082528101610af68161575d565b60208082528101610af68161577e565b60208082528101610af68161579d565b60208082528101610af6816157c7565b60208082528101610af6816157e9565b60208082528101610af68161580b565b60208082528101610af68161582a565b60208082528101610af681615849565b60208082528101610af681615868565b60208082528101610af681615888565b60208082528101610af6816158ae565b60208082528101610af6816158d3565b60208082528101610af6816158f5565b60208082528101610af68161591c565b60208082528101610af68161593d565b60208082528101610af68161595c565b60208082528101610af68161597e565b60208082528101610af6816159a3565b60208082528101610af6816159c2565b60208101610af682846159e2565b60408101615a7982856159e2565b60608101615dec82866159e2565b615df9602083018561563c565b610fb6604083018461564b565b60608101615e1482866159e2565b615df9602083018561564b565b60408101615bef82856159e2565b60608101615e3d82866159e2565b615e4a60208301856159e2565b610fb660408301846156cd565b60608101615a1c82866159e2565b60808101615a4482876159e2565b60208101610af682846159eb565b60405181810167ffffffffffffffff81118282101715615ea057600080fd5b604052919050565b600067ffffffffffffffff821115615ebf57600080fd5b506020601f91909101601f19160190565b5190565b90815260200190565b6000610af682615ef8565b151590565b6000610af682615edd565b6001600160a01b031690565b60ff1690565b6000610af682615eed565b6000610af682610d49565b82818337506000910152565b60005b83811015615f47578181015183820152602001615f2f565b838111156110385750506000910152565b601f01601f191690565b615f6b81615edd565b811461221e57600080fd5b615f6b81615ee8565b615f6b81615eed565b615f6b81610d49565b615f6b81615f0456feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa365627a7a72315820bdb98c5a247a2e6739d6a8223c49daa6ba7dfaf29983cdcfcc31ea2814f3e3656c6578706572696d656e74616cf564736f6c63430005110040
Deployed Bytecode
0x60806040526004361061038c5760003560e01c80638d02d9a1116101dc578063b2a02ff111610102578063dd62ed3e116100a0578063f5e3c4621161006f578063f5e3c46214610999578063f8f9da28146109b9578063fca7820b146109ce578063fe9c44ae146109ee5761038c565b8063dd62ed3e1461092f578063ef01df4f1461094f578063f2b3abbd14610964578063f3fdb15a146109845761038c565b8063c5ebeaec116100dc578063c5ebeaec146108c5578063db006a75146108e5578063dbfe7c1914610905578063dc028ab11461091a5761038c565b8063b2a02ff114610860578063bd6d894d14610880578063c37f68e2146108955761038c565b8063a0b0d2891161017a578063aa5af0fd11610149578063aa5af0fd1461080c578063aaf5eb6814610821578063ac784ddc14610836578063ae9d70b01461084b5761038c565b8063a0b0d28914610797578063a6afed95146107b7578063a7b820df146107cc578063a9059cbb146107ec5761038c565b806395d89b41116101b657806395d89b411461072257806395dd919314610737578063a03dce8d14610757578063a0712d68146107775761038c565b80638d02d9a1146106d85780638f840ddd146106ed57806391dd36c6146107025761038c565b80633b1d21a2116102c157806361feacff1161025f57806370a082311161022e57806370a082311461066357806373acee98146106835780637f1e06be14610698578063852a12e3146106b85761038c565b806361feacff1461060f5780636752e702146106245780636c540baf146106395780636f307dc31461064e5761038c565b806356e677281161029b57806356e677281461058b5780635c60da1b146105ab5780635fe3b567146105cd578063601a0bf1146105ef5761038c565b80633b1d21a21461054157806347bd37181461055657806350d85b731461056b5761038c565b8063182df0f51161032e5780632608f818116103085780632608f818146104bf578063313ce567146104df57806334154d4c146105015780633af9e669146105215761038c565b8063182df0f5146104825780631db789441461049757806323b872dd1461049f5761038c565b80630f8855e81161036a5780630f8855e814610416578063173b99041461043857806317bfdfbc1461044d57806318160ddd1461046d5761038c565b806306fdde0314610391578063095ea7b3146103bc5780630e752702146103e9575b600080fd5b34801561039d57600080fd5b506103a6610a03565b6040516103b39190615c18565b60405180910390f35b3480156103c857600080fd5b506103dc6103d7366004615389565b610a8e565b6040516103b39190615c0a565b3480156103f557600080fd5b506104096104043660046155b2565b610afc565b6040516103b39190615dc2565b34801561042257600080fd5b5061043661043136600461545c565b610b12565b005b34801561044457600080fd5b50610409610cae565b34801561045957600080fd5b50610409610468366004615137565b610cb4565b34801561047957600080fd5b50610409610d02565b34801561048e57600080fd5b50610409610d08565b610436610d4c565b3480156104ab57600080fd5b506103dc6104ba3660046151ad565b610eac565b3480156104cb57600080fd5b506104096104da366004615389565b610eda565b3480156104eb57600080fd5b506104f4610ef0565b6040516103b39190615e73565b34801561050d57600080fd5b5061043661051c36600461555a565b610ef9565b34801561052d57600080fd5b5061040961053c366004615137565b610f3d565b34801561054d57600080fd5b50610409610fbe565b34801561056257600080fd5b50610409610fcd565b34801561057757600080fd5b506104366105863660046151fa565b610fd3565b34801561059757600080fd5b506104366105a636600461541a565b61103e565b3480156105b757600080fd5b506105c06112cb565b6040516103b39190615a00565b3480156105d957600080fd5b506105e26112da565b6040516103b39190615c29565b3480156105fb57600080fd5b5061040961060a3660046155b2565b6112e9565b34801561061b57600080fd5b5061040961133a565b34801561063057600080fd5b50610409611340565b34801561064557600080fd5b5061040961134b565b34801561065a57600080fd5b506105c0611351565b34801561066f57600080fd5b5061040961067e366004615137565b611360565b34801561068f57600080fd5b5061040961137b565b3480156106a457600080fd5b506104366106b3366004615137565b6113c0565b3480156106c457600080fd5b506104096106d33660046155b2565b611442565b3480156106e457600080fd5b5061040961144d565b3480156106f957600080fd5b50610409611453565b34801561070e57600080fd5b5061040961071d3660046155b2565b611459565b34801561072e57600080fd5b506103a6611496565b34801561074357600080fd5b50610409610752366004615137565b6114f1565b34801561076357600080fd5b506104096107723660046155b2565b611536565b34801561078357600080fd5b506104096107923660046155b2565b611573565b3480156107a357600080fd5b506104366107b23660046152bd565b61157f565b3480156107c357600080fd5b506104096116b1565b3480156107d857600080fd5b506104096107e73660046155b2565b61180c565b3480156107f857600080fd5b506103dc610807366004615389565b611849565b34801561081857600080fd5b50610409611876565b34801561082d57600080fd5b5061040961187c565b34801561084257600080fd5b506103dc611888565b34801561085757600080fd5b5061040961188d565b34801561086c57600080fd5b5061040961087b3660046151ad565b61193a565b34801561088c57600080fd5b5061040961195e565b3480156108a157600080fd5b506108b56108b0366004615137565b6119a4565b6040516103b39493929190615e65565b3480156108d157600080fd5b506104096108e03660046155b2565b611a39565b3480156108f157600080fd5b506104096109003660046155b2565b611a44565b34801561091157600080fd5b50610409611a4f565b34801561092657600080fd5b50610409611a55565b34801561093b57600080fd5b5061040961094a366004615173565b611a5b565b34801561095b57600080fd5b506105e2611a86565b34801561097057600080fd5b5061040961097f36600461553c565b611a95565b34801561099057600080fd5b506105e2611acf565b3480156109a557600080fd5b506104096109b43660046153b9565b611ade565b3480156109c557600080fd5b50610409611af6565b3480156109da57600080fd5b506104096109e93660046155b2565b611b47565b3480156109fa57600080fd5b506103dc611b84565b6002805460408051602060018416156101000260001901909316849004601f81018490048402820184019092528181529291830182828015610a865780601f10610a5b57610100808354040283529160200191610a86565b820191906000526020600020905b815481529060010190602001808311610a6957829003601f168201915b505050505081565b3360008181526013602090815260408083206001600160a01b03871680855292528083208590555191929182907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610ae8908790615dc2565b60405180910390a360019150505b92915050565b600080610b0883611b89565b509150505b919050565b3373a731585ab05fc9f83555cf9bff8f58ee94e18f8514610b4e5760405162461bcd60e51b8152600401610b4590615cd2565b60405180910390fd5b600b54158015610b5e5750600c54155b610b7a5760405162461bcd60e51b8152600401610b4590615d12565b600786905585610b9c5760405162461bcd60e51b8152600401610b4590615c72565b6000610ba789611bec565b90508015610bc75760405162461bcd60e51b8152600401610b4590615d52565b610bcf611cef565b600b55670de0b6b3a7640000600c55610be788611cf3565b90508015610c075760405162461bcd60e51b8152600401610b4590615d72565b8551610c1a906002906020890190614de9565b508451610c2e906003906020880190614de9565b506004805460ff191660ff8616179055610c4783611f43565b90508015610c675760405162461bcd60e51b8152600401610b4590615cb2565b610c7082611fec565b90508015610c905760405162461bcd60e51b8152600401610b4590615d02565b50506001805460ff60b01b1916600160b01b17905550505050505050565b600a5481565b600080610cc08161210f565b6000610cca6116b1565b14610ce75760405162461bcd60e51b8152600401610b4590615c62565b610cf0836114f1565b91505b610cfc816121b6565b50919050565b60115481565b6000806000610d15612221565b90925090506000826003811115610d2857fe5b14610d455760405162461bcd60e51b8152600401610b4590615d82565b9150505b90565b333014801590610ddd5750600560009054906101000a90046001600160a01b03166001600160a01b031663dd5cd22c6040518163ffffffff1660e01b815260040160206040518083038186803b158015610da557600080fd5b505afa158015610db9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610ddd91908101906153fc565b15610eaa57600080546040516345cc970560e01b8152829160609173a731585ab05fc9f83555cf9bff8f58ee94e18f85916345cc970591610e2a916001600160a01b031690600401615a00565b60006040518083038186803b158015610e4257600080fd5b505afa158015610e56573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610e7e9190810190615262565b60005492955090935091506001600160a01b03808516911614610ea657610ea68383836122e1565b5050505b565b600080610eb88161210f565b6000610ec633878787612470565b149150610ed2816121b6565b509392505050565b600080610ee784846126f8565b50949350505050565b60045460ff1681565b610f0161275d565b610f1d5760405162461bcd60e51b8152600401610b4590615cd2565b610f2960028585614e63565b50610f3660038383614e63565b5050505050565b6000610f47614ed1565b6040518060200160405280610f5a61195e565b90526001600160a01b038416600090815260126020526040812054919250908190610f869084906128fe565b90925090506000826003811115610f9957fe5b14610fb65760405162461bcd60e51b8152600401610b4590615cf2565b949350505050565b6000610fc8612952565b905090565b600d5481565b610fdb61275d565b610ff75760405162461bcd60e51b8152600401610b4590615cd2565b611038848484848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506122e192505050565b50505050565b3330148061104f575061104f61275d565b61105857600080fd5b600061106682840184615137565b90506001600160a01b03811661108e5760405162461bcd60e51b8152600401610b4590615cc2565b6016546001600160a01b03161561119b576016546040516370a0823160e01b81526001600160a01b039091169063ba0876529082906370a08231906110d7903090600401615a00565b60206040518083038186803b1580156110ef57600080fd5b505afa158015611103573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061112791908101906155d0565b30306040518463ffffffff1660e01b815260040161114793929190615e06565b602060405180830381600087803b15801561116157600080fd5b505af1158015611175573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061119991908101906155d0565b505b601680546001600160a01b0319166001600160a01b038381169190911790915560155460405163095ea7b360e01b815291169063095ea7b3906111e690849060001990600401615be1565b602060405180830381600087803b15801561120057600080fd5b505af1158015611214573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061123891908101906153fc565b506015546040516370a0823160e01b81526000916001600160a01b0316906370a082319061126a903090600401615a00565b60206040518083038186803b15801561128257600080fd5b505afa158015611296573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506112ba91908101906155d0565b905080156110385761103881612983565b6000546001600160a01b031681565b6005546001600160a01b031681565b6000806112f58161210f565b60006112ff6116b1565b905080156113255761131d81601181111561131657fe5b603b612a0b565b925050610cf3565b61132e84612a6b565b925050610cfc816121b6565b600f5481565b666379da05b6000081565b600b5481565b6015546001600160a01b031681565b6001600160a01b031660009081526012602052604090205490565b6000806113878161210f565b60006113916116b1565b146113ae5760405162461bcd60e51b8152600401610b4590615c62565b600d5491506113bc816121b6565b5090565b6113c861275d565b6113e45760405162461bcd60e51b8152600401610b4590615cd2565b6015546040516317066a5760e21b81526001600160a01b0390911690635c19a95c90611414908490600401615a00565b600060405180830381600087803b15801561142e57600080fd5b505af1158015610f36573d6000803e3d6000fd5b6000610af682612b23565b60085481565b600e5481565b6000806114658161210f565b600061146f6116b1565b9050801561148d5761131d81601181111561148657fe5b6052612a0b565b61132e84611fec565b6003805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610a865780601f10610a5b57610100808354040283529160200191610a86565b60008060006114ff84612b63565b9092509050600082600381111561151257fe5b1461152f5760405162461bcd60e51b8152600401610b4590615d92565b9392505050565b6000806115428161210f565b600061154c6116b1565b9050801561156a5761131d81601181111561156357fe5b6033612a0b565b61132e84612c17565b600080610b0883612c98565b60006702c68af0bb14000090506000886001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b1580156115c757600080fd5b505afa1580156115db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506115ff919081019061561e565b90506116118888848989868a8a610b12565b601580546001600160a01b0319166001600160a01b038b81169190911791829055604080516318160ddd60e01b8152905192909116916318160ddd91600480820192602092909190829003018186803b15801561166d57600080fd5b505afa158015611681573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506116a591908101906155d0565b50505050505050505050565b6000806116bc611cef565b905080600b5414156116d2576000915050610d49565b60006116dc612952565b90506000600660009054906101000a90046001600160a01b03166001600160a01b03166315f2405383600d54611721600e5461171c600f54601054612cd8565b612cd8565b6040518463ffffffff1660e01b815260040161173f93929190615e57565b60206040518083038186803b15801561175757600080fd5b505afa15801561176b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061178f91908101906155d0565b905065048c273950008111156117b75760405162461bcd60e51b8152600401610b4590615ce2565b6000806117c685600b54612d0e565b909250905060008260038111156117d957fe5b146117f65760405162461bcd60e51b8152600401610b4590615da2565b61180285858584612d31565b9550505050505090565b6000806118188161210f565b60006118226116b1565b905080156118405761131d81601181111561183957fe5b6037612a0b565b61132e84612efb565b6000806118558161210f565b600061186333338787612470565b14915061186f816121b6565b5092915050565b600c5481565b670de0b6b3a764000081565b600081565b6006546000906001600160a01b031663b81688166118a9612952565b600d546118c0600e5461171c600f54601054612cd8565b600854600954600a5401016040518563ffffffff1660e01b81526004016118ea9493929190615e65565b60206040518083038186803b15801561190257600080fd5b505afa158015611916573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610fc891908101906155d0565b600060016119478161210f565b61195333868686612fef565b9150610ed2816121b6565b60008061196a8161210f565b60006119746116b1565b146119915760405162461bcd60e51b8152600401610b4590615c62565b611999610d08565b91506113bc816121b6565b6001600160a01b0381166000908152601260205260408120548190819081908180806119cf89612b63565b9350905060008160038111156119e157fe5b146119ff5760095b975060009650869550859450611a329350505050565b611a07612221565b925090506000816003811115611a1957fe5b14611a255760096119e9565b5060009650919450925090505b9193509193565b6000610af682613394565b6000610af6826133d2565b60095481565b60105481565b6001600160a01b03918216600090815260136020908152604080832093909416825291909152205490565b6016546001600160a01b031681565b600080611aa06116b1565b90508015611ac657611abe816011811115611ab757fe5b604b612a0b565b915050610b0d565b61152f83611cf3565b6006546001600160a01b031681565b600080611aec85858561340b565b5095945050505050565b6006546000906001600160a01b03166315f24053611b12612952565b600d54611b29600e5461171c600f54601054612cd8565b6040518463ffffffff1660e01b81526004016118ea93929190615e57565b600080611b538161210f565b6000611b5d6116b1565b90508015611b7b5761131d816011811115611b7457fe5b6059612a0b565b61132e84611f43565b600181565b6000806000611b978161210f565b6000611ba16116b1565b90508015611bcc57611bbf816011811115611bb857fe5b6041612a0b565b935060009250611bdd9050565b611bd7333387613503565b93509350505b611be6816121b6565b50915091565b600080600560009054906101000a90046001600160a01b03169050826001600160a01b0316627e3dd26040518163ffffffff1660e01b815260040160206040518083038186803b158015611c3f57600080fd5b505afa158015611c53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611c7791908101906153fc565b611c935760405162461bcd60e51b8152600401610b4590615d42565b600580546001600160a01b0319166001600160a01b0385161790556040517f7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d90611ce09083908690615c37565b60405180910390a1600061152f565b4390565b600080611cfe61275d565b611d0e57611abe6001604d612a0b565b611d16611cef565b600b5414611d2a57611abe600a604c612a0b565b600660009054906101000a90046001600160a01b03169050826001600160a01b0316632191f92a6040518163ffffffff1660e01b815260040160206040518083038186803b158015611d7b57600080fd5b505afa158015611d8f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611db391908101906153fc565b611dcf5760405162461bcd60e51b8152600401610b4590615d42565b600680546001600160a01b0319166001600160a01b0385161790556040517fedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f92690611e1c9083908690615c37565b60405180910390a16001600160a01b03811615611eb75760408051600481526024810182526020810180516001600160e01b0316636cc1140b60e11b17905290516001600160a01b03831691611e71916159f4565b6000604051808303816000865af19150503d8060008114611eae576040519150601f19603f3d011682016040523d82523d6000602084013e611eb3565b606091505b5050505b60408051600481526024810182526020810180516001600160e01b031663742a137b60e11b17905290516001600160a01b03851691611ef5916159f4565b6000604051808303816000865af19150503d8060008114611f32576040519150601f19603f3d011682016040523d82523d6000602084013e611f37565b606091505b506000915061152f9050565b6000611f4d61275d565b611f6457611f5d6001605a612a0b565b9050610b0d565b611f6c611cef565b600b5414611f8057611f5d600a605b612a0b565b670de0b6b3a7640000611fa0611f9884600854612cd8565b600954612cd8565b1115611fb257611f5d6002605c612a0b565b600a8054908390556040517faaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f82146090611ce09083908690615e21565b6000611ff6611cef565b600b541461200a57611f5d600a6054612a0b565b60001982141561201a5760085491505b60006120246137f0565b9050670de0b6b3a764000061204461203e600a5486612cd8565b83612cd8565b111561205657611abe60026055612a0b565b82600854146120bb5761206761275d565b61207757611abe60016053612a0b565b60088054908490556040517fcdd0b588250e1398549f79cfdb8217c186688822905d6715b0834ea1c865594a906120b19083908790615e21565b60405180910390a1505b80600954146121085760098054908290556040517f92eef861b6533b7d3417f39c2ad7b460eed4e88a32fa3604f30e718b7602e7dc906120fe9083908590615e21565b60405180910390a1505b600061152f565b600154600160b01b900460ff166121385760405162461bcd60e51b8152600401610b4590615d22565b806121a657600560009054906101000a90046001600160a01b03166001600160a01b031663c90c20b16040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561218d57600080fd5b505af11580156121a1573d6000803e3d6000fd5b505050505b506001805460ff60b01b19169055565b6001805460ff60b01b1916600160b01b1790558061221e57600560009054906101000a90046001600160a01b03166001600160a01b031663632e51426040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561142e57600080fd5b50565b60115460009081908061223c575050600754600091506122dd565b6000612246612952565b90506000612252614ed1565b600061227484600d5461226f600e5461171c600f54601054612cd8565b61383f565b93509050600081600381111561228657fe5b1461229b579550600094506122dd9350505050565b6122a5838661388b565b9250905060008160038111156122b757fe5b146122cc579550600094506122dd9350505050565b50516000955093506122dd92505050565b9091565b6000546040516338e6a07360e11b815273a731585ab05fc9f83555cf9bff8f58ee94e18f85916371cd40e691612327916001600160a01b03169087908790600401615b26565b60206040518083038186803b15801561233f57600080fd5b505afa158015612353573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061237791908101906153fc565b6123935760405162461bcd60e51b8152600401610b4590615c92565b81156123a1576123a161393b565b600080546001600160a01b038581166001600160a01b03198316179092556040519116906124249030906123d9908590602401615c18565b60408051601f19818403018152918152602080830180516001600160e01b0316630adccee560e31b17905281518083019092526007825266216265636f6d6560c81b90820152613940565b506000546040517fd604de94d45953f9138079ec1b82d533cb2160c906d1076d1f7ed54befbca97a916124629184916001600160a01b031690615a6b565b60405180910390a150505050565b6005546040516317b9b84b60e31b815260009182916001600160a01b039091169063bdcdc258906124ab903090899089908990600401615afe565b602060405180830381600087803b1580156124c557600080fd5b505af11580156124d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506124fd91908101906155d0565b9050801561251a576125126003605d836139dd565b915050610fb6565b836001600160a01b0316856001600160a01b03161415612540576125126002605e612a0b565b60006001600160a01b03878116908716141561255f5750600019612587565b506001600160a01b038086166000908152601360209081526040808320938a16835292905220545b6000806000806125978589612d0e565b909450925060008460038111156125aa57fe5b146125c8576125bb6009605e612a0b565b9650505050505050610fb6565b6001600160a01b038a166000908152601260205260409020546125eb9089612d0e565b909450915060008460038111156125fe57fe5b1461260f576125bb6009605f612a0b565b6001600160a01b0389166000908152601260205260409020546126329089613a5f565b9094509050600084600381111561264557fe5b14612656576125bb60096060612a0b565b6001600160a01b03808b16600090815260126020526040808220859055918b1681522081905560001985146126ae576001600160a01b03808b166000908152601360209081526040808320938f168352929052208390555b886001600160a01b03168a6001600160a01b0316600080516020615f9b8339815191528a6040516126df9190615dc2565b60405180910390a35060009a9950505050505050505050565b60008060006127068161210f565b60006127106116b1565b9050801561273b5761272e81601181111561272757fe5b6040612a0b565b93506000925061274c9050565b612746338787613503565b93509350505b612755816121b6565b509250929050565b600554604080516303e1469160e61b815290516000926001600160a01b031691829163f851a44091600480820192602092909190829003018186803b1580156127a557600080fd5b505afa1580156127b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506127dd9190810190615155565b6001600160a01b0316336001600160a01b03161480156128695750806001600160a01b0316630a755ec26040518163ffffffff1660e01b815260040160206040518083038186803b15801561283157600080fd5b505afa158015612845573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061286991908101906153fc565b80610d4557503373a731585ab05fc9f83555cf9bff8f58ee94e18f85148015610d455750806001600160a01b0316632f1069ba6040518163ffffffff1660e01b815260040160206040518083038186803b1580156128c657600080fd5b505afa1580156128da573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610d4591908101906153fc565b600080600061290b614ed1565b6129158686613a85565b9092509050600082600381111561292857fe5b14612939575091506000905061294b565b600061294482613aed565b9350935050505b9250929050565b6016546040516302c62fa160e41b81526000916001600160a01b031690632c62fa10906118ea903090600401615a00565b601654604051636e553f6560e01b81526001600160a01b0390911690636e553f65906129b59084903090600401615dd0565b602060405180830381600087803b1580156129cf57600080fd5b505af11580156129e3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612a0791908101906155d0565b5050565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0836011811115612a3a57fe5b836063811115612a4657fe5b6000604051612a5793929190615e2f565b60405180910390a182601181111561152f57fe5b600080612a7661275d565b612a8657611abe6001603c612a0b565b612a8e611cef565b600b5414612aa257611abe600a603e612a0b565b82612aab612952565b1015612abd57611abe600e603d612a0b565b600e54831115612ad357611abe6002603f612a0b565b612adf600e5484613afc565b600e8190559050612af03384613b36565b7f3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e338483604051611ce093929190615a0e565b600080612b2f8161210f565b6000612b396116b1565b90508015612b575761131d816011811115612b5057fe5b602a612a0b565b61132e33600086613bbc565b6001600160a01b038116600090815260146020526040812080548291829182918291612b9a575060009450849350612c1292505050565b612baa8160000154600c5461403b565b90945092506000846003811115612bbd57fe5b14612bd2575091935060009250612c12915050565b612be083826001015461407a565b90945091506000846003811115612bf357fe5b14612c08575091935060009250612c12915050565b5060009450925050505b915091565b600080612c22611cef565b600b5414612c3657611abe600a6035612a0b565b82612c3f612952565b1015612c5157611abe600e6034612a0b565b601054831115612c6757611abe60026036612a0b565b612c7360105484613afc565b6010819055905061210873a731585ab05fc9f83555cf9bff8f58ee94e18f8584613b36565b6000806000612ca68161210f565b6000612cb06116b1565b90508015612cce57611bbf816011811115612cc757fe5b6020612a0b565b611bd733866140a5565b600061152f8383604051806040016040528060118152602001706164646974696f6e206f766572666c6f7760781b8152506143d8565b600080838311612d2557506000905081830361294b565b5060039050600061294b565b6000612d3b614ed1565b612d53604051806020016040528086815250846143ff565b90506000612d6382600d54614429565b90506000612d7382600d54612cd8565b90506000612d946040518060200160405280600a5481525084600e54614448565b90506000612db5604051806020016040528060095481525085601054614448565b90506000612dd6604051806020016040528060085481525086600f54614448565b90506000612de987600c54600c54614448565b600b8d9055600c819055600d869055600e8590556010849055600f8390556040519091507f4dec04e750ca11537cabcd8a9eab06494de08da3735bc8871cd41250e190bc0490612e40908d90899085908a90615e65565b60405180910390a16006546040516001600160a01b0390911690612e68908c90602401615dc2565b60408051601f198184030181529181526020820180516001600160e01b0316635efd023360e11b17905251612e9d91906159f4565b6000604051808303816000865af19150503d8060008114612eda576040519150601f19603f3d011682016040523d82523d6000602084013e612edf565b606091505b5060009150612eeb9050565b9c9b505050505050505050505050565b600080612f06611cef565b600b5414612f1a57611abe600a6039612a0b565b82612f23612952565b1015612f3557611abe600e6038612a0b565b600f54831115612f4b57611abe6002603a612a0b565b612f57600f5484613afc565b905080600f81905550612108600560009054906101000a90046001600160a01b03166001600160a01b031663f851a4406040518163ffffffff1660e01b815260040160206040518083038186803b158015612fb157600080fd5b505afa158015612fc5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612fe99190810190615155565b84613b36565b60055460405163d02f735160e01b815260009182916001600160a01b039091169063d02f73519061302c9030908a908a908a908a90600401615abc565b602060405180830381600087803b15801561304657600080fd5b505af115801561305a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061307e91908101906155d0565b90508015613093576125126003601d836139dd565b846001600160a01b0316846001600160a01b031614156130b9576125126006601e612a0b565b6130c1614ee4565b6001600160a01b0385166000908152601260205260409020546130e49085612d0e565b60208301819052828260038111156130f857fe5b600381111561310357fe5b905250600090508151600381111561311757fe5b14613141576131386009601c8360000151600381111561313357fe5b6139dd565b92505050610fb6565b613160846040518060200160405280666379da05b60000815250614470565b60808201819052613172908590613afc565b606082015261317f612221565b60c083018190528282600381111561319357fe5b600381111561319e57fe5b90525060009050815160038111156131b257fe5b146131cf5760405162461bcd60e51b8152600401610b4590615d82565b6131ef60405180602001604052808360c001518152508260800151614429565b60a08201819052600e5461320291612cd8565b60e082015260115460808201516132199190613afc565b6101008201526001600160a01b03861660009081526012602052604090205460608201516132479190613a5f565b604083018190528282600381111561325b57fe5b600381111561326657fe5b905250600090508151600381111561327a57fe5b14613296576131386009601b8360000151600381111561313357fe5b60e0810151600e556101008101516011556020808201516001600160a01b038088166000818152601290945260408085209390935582850151918a168085529383902091909155606084015191519091600080516020615f9b833981519152916133009190615dc2565b60405180910390a3306001600160a01b0316856001600160a01b0316600080516020615f9b833981519152836080015160405161333d9190615dc2565b60405180910390a360a081015160e08201516040517fa91e67c5ea634cd43a12c5a482724b03de01e85ca68702a53d0c2f45cb7c1dc59261337f923092615bfc565b60405180910390a16000979650505050505050565b6000806133a08161210f565b60006133aa6116b1565b905080156133c85761131d8160118111156133c157fe5b600a612a0b565b61132e3385614498565b6000806133de8161210f565b60006133e86116b1565b905080156133ff5761131d816011811115612b5057fe5b61132e33856000613bbc565b60008060006134198161210f565b60006134236116b1565b9050801561344e5761344181601181111561343a57fe5b6011612a0b565b9350600092506134f19050565b846001600160a01b031663a6afed956040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561348957600080fd5b505af115801561349d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506134c191908101906155d0565b905080156134df576134418160118111156134d857fe5b6012612a0b565b6134eb338888886147ca565b93509350505b6134fa816121b6565b50935093915050565b600554604051631200453160e11b8152600091829182916001600160a01b0316906324008a629061353e9030908a908a908a90600401615afe565b602060405180830381600087803b15801561355857600080fd5b505af115801561356c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061359091908101906155d0565b905080156135b2576135a560036043836139dd565b9250600091506137e89050565b6135ba611cef565b600b54146135ce576135a5600a6044612a0b565b6135d6614f31565b6001600160a01b038616600090815260146020526040902060010154606082015261360086612b63565b608083018190526020830182600381111561361757fe5b600381111561362257fe5b905250600090508160200151600381111561363957fe5b1461366357613655600960428360200151600381111561313357fe5b9350600092506137e8915050565b60001985141561367c5760808101516040820152613684565b604081018590525b613692878260400151614c11565b60e0820181905260808201516136a791612d0e565b60a08301819052602083018260038111156136be57fe5b60038111156136c957fe5b90525060009050816020015160038111156136e057fe5b146136fd5760405162461bcd60e51b8152600401610b4590615d62565b61370d600d548260e00151612d0e565b60c083018190526020830182600381111561372457fe5b600381111561372f57fe5b905250600090508160200151600381111561374657fe5b146137635760405162461bcd60e51b8152600401610b4590615d62565b60a0810180516001600160a01b03881660009081526014602052604090819020918255600c5460019092019190915560c0830151600d81905560e0840151925191517f1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a1936137d4938c938c93615bac565b60405180910390a160e00151600093509150505b935093915050565b600073a731585ab05fc9f83555cf9bff8f58ee94e18f856001600160a01b031663dd86fea16040518163ffffffff1660e01b815260040160206040518083038186803b15801561190257600080fd5b60008060008061384f8787613a5f565b9092509050600082600381111561386257fe5b1461387357509150600090506137e8565b61387d8186612d0e565b935093505050935093915050565b6000613895614ed1565b6000806138aa86670de0b6b3a764000061403b565b909250905060008260038111156138bd57fe5b146138dc5750604080516020810190915260008152909250905061294b565b6000806138e9838861407a565b909250905060008260038111156138fc57fe5b1461391e5750604080516020810190915260008152909450925061294b915050565b604080516020810190915290815260009890975095505050505050565b610eaa565b606060006060856001600160a01b03168560405161395e91906159f4565b6000604051808303816000865af19150503d806000811461399b576040519150601f19603f3d011682016040523d82523d6000602084013e6139a0565b606091505b5091509150816139d4578051156139ba5780518082602001fd5b8360405162461bcd60e51b8152600401610b459190615c18565b95945050505050565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0846011811115613a0c57fe5b846063811115613a1857fe5b84604051613a2893929190615e57565b60405180910390a16003846011811115613a3e57fe5b14613a5457836011811115613a4f57fe5b610fb6565b506103e80192915050565b600080838301848110613a775760009250905061294b565b50600291506000905061294b565b6000613a8f614ed1565b600080613aa086600001518661403b565b90925090506000826003811115613ab357fe5b14613ad25750604080516020810190915260008152909250905061294b565b60408051602081019091529081526000969095509350505050565b51670de0b6b3a7640000900490565b600061152f8383604051806040016040528060158152602001747375627472616374696f6e20756e646572666c6f7760581b815250614cbd565b601654604051632d182be560e21b81526001600160a01b039091169063b460af9490613b6a90849086903090600401615dde565b602060405180830381600087803b158015613b8457600080fd5b505af1158015613b98573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610ea691908101906155d0565b6000821580613bc9575081155b613be55760405162461bcd60e51b8152600401610b4590615c82565b613bed614f77565b613bf5612221565b6040830181905260208301826003811115613c0c57fe5b6003811115613c1757fe5b9052506000905081602001516003811115613c2e57fe5b14613c5257613c4a6009602e8360200151600381111561313357fe5b91505061152f565b8315613cd3576060810184905260408051602081018252908201518152613c7990856128fe565b6080830181905260208301826003811115613c9057fe5b6003811115613c9b57fe5b9052506000905081602001516003811115613cb257fe5b14613cce57613c4a6009602c8360200151600381111561313357fe5b613d4c565b613cef8360405180602001604052808460400151815250614ce9565b6060830181905260208301826003811115613d0657fe5b6003811115613d1157fe5b9052506000905081602001516003811115613d2857fe5b14613d4457613c4a6009602d8360200151600381111561313357fe5b608081018390525b600554606082015160405163eabe7d9160e01b81526000926001600160a01b03169163eabe7d9191613d859130918b9190600401615a86565b602060405180830381600087803b158015613d9f57600080fd5b505af1158015613db3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250613dd791908101906155d0565b90508015613df557613dec6003602b836139dd565b9250505061152f565b613dfd611cef565b600b5414613e1157613dec600a602f612a0b565b613e216011548360600151612d0e565b60a0840181905260208401826003811115613e3857fe5b6003811115613e4357fe5b9052506000905082602001516003811115613e5a57fe5b14613e7657613dec600960318460200151600381111561313357fe5b6001600160a01b0386166000908152601260205260409020546060830151613e9e9190612d0e565b60c0840181905260208401826003811115613eb557fe5b6003811115613ec057fe5b9052506000905082602001516003811115613ed757fe5b14613ef357613dec600960308460200151600381111561313357fe5b8160800151613f00612952565b1015613f1257613dec600e6032612a0b565b613f20868360800151613b36565b60a082015160115560c08201516001600160a01b0387166000818152601260205260409081902092909255606084015191513092600080516020615f9b83398151915291613f6e9190615dc2565b60405180910390a3608082015160608301516040517fe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a92992613fb0928a92615a0e565b60405180910390a1600554608083015160608401516040516351dff98960e01b81526001600160a01b03909316926351dff98992613ff69230928c929190600401615aa1565b600060405180830381600087803b15801561401057600080fd5b505af1158015614024573d6000803e3d6000fd5b5060009250614031915050565b9695505050505050565b6000808361404e5750600090508061294b565b8383028385828161405b57fe5b041461406f5750600291506000905061294b565b60009250905061294b565b6000808261408e575060019050600061294b565b600083858161409957fe5b04915091509250929050565b600554604051634ef4c3e160e01b8152600091829182916001600160a01b031690634ef4c3e1906140de90309089908990600401615b4e565b602060405180830381600087803b1580156140f857600080fd5b505af115801561410c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061413091908101906155d0565b905080156141525761414560036021836139dd565b92506000915061294b9050565b61415a611cef565b600b541461416e57614145600a6024612a0b565b614176614f77565b61417e612221565b604083018190526020830182600381111561419557fe5b60038111156141a057fe5b90525060009050816020015160038111156141b757fe5b146141e1576141d3600960238360200151600381111561313357fe5b93506000925061294b915050565b6141eb8686614c11565b60c082018190526040805160208101825290830151815261420c9190614ce9565b606083018190526020830182600381111561422357fe5b600381111561422e57fe5b905250600090508160200151600381111561424557fe5b146142625760405162461bcd60e51b8152600401610b4590615db2565b6142726011548260600151612cd8565b60808201526001600160a01b038616600090815260126020526040902054606082015161429f9190612cd8565b60a0820181905260808201516011556001600160a01b038716600090815260126020526040908190209190915560c0820151606083015191517f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f92614308928a92909190615bfc565b60405180910390a1856001600160a01b0316306001600160a01b0316600080516020615f9b83398151915283606001516040516143459190615dc2565b60405180910390a360055460c082015160608301516040516341c728b960e01b81526001600160a01b03909316926341c728b99261438b9230928c929190600401615b91565b600060405180830381600087803b1580156143a557600080fd5b505af11580156143b9573d6000803e3d6000fd5b50600092506143c6915050565b8160c001519350935050509250929050565b60008383018285821015610ee75760405162461bcd60e51b8152600401610b459190615c18565b614407614ed1565b6040518060200160405280614420856000015185614d00565b90529392505050565b6000614433614ed1565b61443d84846143ff565b9050610fb681613aed565b6000614452614ed1565b61445c85856143ff565b90506139d461446a82613aed565b84612cd8565b6000670de0b6b3a7640000614489848460000151614d00565b8161449057fe5b049392505050565b60055460405163368f515360e21b815260009182916001600160a01b039091169063da3d454c906144d190309088908890600401615a86565b602060405180830381600087803b1580156144eb57600080fd5b505af11580156144ff573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061452391908101906155d0565b905080156145405761453860036010836139dd565b915050610af6565b614548611cef565b600b541461455c57614538600a600c612a0b565b6000614566612952565b9050838110156145855761457c600e600b612a0b565b92505050610af6565b61458d614fb5565b61459686612b63565b60208301819052828260038111156145aa57fe5b60038111156145b557fe5b90525060009050815160038111156145c957fe5b146145ee576145e46009808360000151600381111561313357fe5b9350505050610af6565b6145fc816020015186613a5f565b604083018190528282600381111561461057fe5b600381111561461b57fe5b905250600090508151600381111561462f57fe5b1461464b576145e46009600e8360000151600381111561313357fe5b6005546040808301519051631de6c8a560e21b81526001600160a01b039092169163779b22949161468191309190600401615be1565b602060405180830381600087803b15801561469b57600080fd5b505af11580156146af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506146d391908101906155d0565b925082156146e8576145e460036010856139dd565b6146f4600d5486613a5f565b606083018190528282600381111561470857fe5b600381111561471357fe5b905250600090508151600381111561472757fe5b14614743576145e46009600d8360000151600381111561313357fe5b61474d8686613b36565b604080820180516001600160a01b03891660009081526014602052839020908155600c546001909101556060830151600d819055905191517f13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab80926147b6928a928a929190615a36565b60405180910390a160009695505050505050565b600554604051632fe3f38f60e11b8152600091829182916001600160a01b031690635fc7e71e9061480790309088908c908c908c90600401615abc565b602060405180830381600087803b15801561482157600080fd5b505af1158015614835573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061485991908101906155d0565b9050801561487b5761486e60036014836139dd565b925060009150614c089050565b614883611cef565b600b54146148975761486e600a6018612a0b565b61489f611cef565b846001600160a01b0316636c540baf6040518163ffffffff1660e01b815260040160206040518083038186803b1580156148d857600080fd5b505afa1580156148ec573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061491091908101906155d0565b146149215761486e600a6013612a0b565b866001600160a01b0316866001600160a01b031614156149475761486e60066019612a0b565b846149585761486e60076017612a0b565b60001985141561496e5761486e60076016612a0b565b60008061497c898989613503565b909250905081156149ac5761499d82601181111561499657fe5b601a612a0b565b945060009350614c0892505050565b60055460405163c488847b60e01b815260009182916001600160a01b039091169063c488847b906149e59030908c908890600401615b4e565b604080518083038186803b1580156149fc57600080fd5b505afa158015614a10573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250614a3491908101906155ee565b90925090508115614a575760405162461bcd60e51b8152600401610b4590615ca2565b6040516370a0823160e01b815281906001600160a01b038a16906370a0823190614a85908e90600401615a00565b60206040518083038186803b158015614a9d57600080fd5b505afa158015614ab1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250614ad591908101906155d0565b1015614af35760405162461bcd60e51b8152600401610b4590615ca2565b60006001600160a01b038916301415614b1957614b12308d8d85612fef565b9050614b9e565b60405163b2a02ff160e01b81526001600160a01b038a169063b2a02ff190614b49908f908f908790600401615b4e565b602060405180830381600087803b158015614b6357600080fd5b505af1158015614b77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250614b9b91908101906155d0565b90505b8015614bbc5760405162461bcd60e51b8152600401610b4590615c52565b7f298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb528c8c868c86604051614bf3959493929190615b69565b60405180910390a16000975092955050505050505b94509492505050565b6015546040516323b872dd60e01b81526000916001600160a01b0316906323b872dd90614c4690869030908790600401615b4e565b602060405180830381600087803b158015614c6057600080fd5b505af1158015614c74573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250614c9891908101906153fc565b614cb45760405162461bcd60e51b8152600401610b4590615d32565b610cfc82612983565b60008184841115614ce15760405162461bcd60e51b8152600401610b459190615c18565b505050900390565b6000806000614cf6614ed1565b6129158686614d42565b600061152f83836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f77000000000000000000815250614da1565b6000614d4c614ed1565b600080614d61670de0b6b3a76400008761403b565b90925090506000826003811115614d7457fe5b14614d935750604080516020810190915260008152909250905061294b565b61294481866000015161388b565b6000831580614dae575082155b15614dbb5750600061152f565b83830283858281614dc857fe5b04148390610ee75760405162461bcd60e51b8152600401610b459190615c18565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10614e2a57805160ff1916838001178555614e57565b82800160010185558215614e57579182015b82811115614e57578251825591602001919060010190614e3c565b506113bc929150614fde565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10614ea45782800160ff19823516178555614e57565b82800160010185558215614e57579182015b82811115614e57578235825591602001919060010190614eb6565b6040518060200160405280600081525090565b604080516101208101909152806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6040805161010081019091528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6040805160e0810190915280600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b604080516080810190915280600081526020016000815260200160008152602001600081525090565b610d4991905b808211156113bc5760008155600101614fe4565b8035610af681615f62565b8051610af681615f62565b8035610af681615f76565b8051610af681615f76565b60008083601f84011261503657600080fd5b50813567ffffffffffffffff81111561504e57600080fd5b60208301915083600182028301111561294b57600080fd5b600082601f83011261507757600080fd5b815161508a61508582615ea8565b615e81565b915080825260208301602083018583830111156150a657600080fd5b6150b1838284615f2c565b50505092915050565b8035610af681615f7f565b600082601f8301126150d657600080fd5b81356150e461508582615ea8565b9150808252602083016020830185838301111561510057600080fd5b6150b1838284615f20565b8035610af681615f88565b8051610af681615f88565b8035610af681615f91565b8051610af681615f91565b60006020828403121561514957600080fd5b6000610fb68484614ff8565b60006020828403121561516757600080fd5b6000610fb68484615003565b6000806040838503121561518657600080fd5b60006151928585614ff8565b92505060206151a385828601614ff8565b9150509250929050565b6000806000606084860312156151c257600080fd5b60006151ce8686614ff8565b93505060206151df86828701614ff8565b92505060406151f08682870161510b565b9150509250925092565b6000806000806060858703121561521057600080fd5b600061521c8787614ff8565b945050602061522d8782880161500e565b935050604085013567ffffffffffffffff81111561524a57600080fd5b61525687828801615024565b95989497509550505050565b60008060006060848603121561527757600080fd5b60006152838686615003565b935050602061529486828701615019565b925050604084015167ffffffffffffffff8111156152b157600080fd5b6151f086828701615066565b600080600080600080600060e0888a0312156152d857600080fd5b60006152e48a8a614ff8565b97505060206152f58a828b016150ba565b96505060406153068a828b016150ba565b955050606088013567ffffffffffffffff81111561532357600080fd5b61532f8a828b016150c5565b945050608088013567ffffffffffffffff81111561534c57600080fd5b6153588a828b016150c5565b93505060a06153698a828b0161510b565b92505060c061537a8a828b0161510b565b91505092959891949750929550565b6000806040838503121561539c57600080fd5b60006153a88585614ff8565b92505060206151a38582860161510b565b6000806000606084860312156153ce57600080fd5b60006153da8686614ff8565b93505060206153eb8682870161510b565b92505060406151f0868287016150ba565b60006020828403121561540e57600080fd5b6000610fb68484615019565b6000806020838503121561542d57600080fd5b823567ffffffffffffffff81111561544457600080fd5b61545085828601615024565b92509250509250929050565b600080600080600080600080610100898b03121561547957600080fd5b60006154858b8b6150ba565b98505060206154968b828c016150ba565b97505060406154a78b828c0161510b565b965050606089013567ffffffffffffffff8111156154c457600080fd5b6154d08b828c016150c5565b955050608089013567ffffffffffffffff8111156154ed57600080fd5b6154f98b828c016150c5565b94505060a061550a8b828c01615121565b93505060c061551b8b828c0161510b565b92505060e061552c8b828c0161510b565b9150509295985092959890939650565b60006020828403121561554e57600080fd5b6000610fb684846150ba565b6000806000806040858703121561557057600080fd5b843567ffffffffffffffff81111561558757600080fd5b61559387828801615024565b9450945050602085013567ffffffffffffffff81111561524a57600080fd5b6000602082840312156155c457600080fd5b6000610fb6848461510b565b6000602082840312156155e257600080fd5b6000610fb68484615116565b6000806040838503121561560157600080fd5b600061560d8585615116565b92505060206151a385828601615116565b60006020828403121561563057600080fd5b6000610fb6848461512c565b61564581615f0a565b82525050565b61564581615edd565b61564581615ee8565b600061566882615ed0565b6156728185615ed4565b9350615682818560208601615f2c565b61568b81615f58565b9093019392505050565b60006156a082615ed0565b6156aa8185610b0d565b93506156ba818560208601615f2c565b9290920192915050565b61564581615eed565b61564581615f15565b60006156e3600583615ed4565b647365697a6560d81b815260200192915050565b6000615704600383615ed4565b6261636360e81b815260200192915050565b6000615723600983615ed4565b687a65726f207261746560b81b815260200192915050565b6000615748600683615ed4565b6572656465656d60d01b815260200192915050565b600061576a600583615ed4565b64085a5b5c1b60da1b815260200192915050565b600061578b600383615ed4565b624c495160e81b815260200192915050565b60006157aa600e83615ed4565b6d3932b9b2b93b32903330b1ba37b960911b815260200192915050565b60006157d4600683615ed4565b65181030b2323960d11b815260200192915050565b60006157f6600683615ed4565b6510b0b236b4b760d11b815260200192915050565b6000615818600383615ed4565b623137b960e91b815260200192915050565b6000615837600383615ed4565b6218985b60ea1b815260200192915050565b6000615856600383615ed4565b6266656560e81b815260200192915050565b6000615875600483615ed4565b631a5b9a5d60e21b815260200192915050565b6000615895600a83615ed4565b691c994b595b9d195c995960b21b815260200192915050565b60006158bb600983615ed4565b681cd95b990819985a5b60ba1b815260200192915050565b60006158e0600683615ed4565b6536b0b935b2b960d11b815260200192915050565b6000615902600b83615ed4565b6a31b7b6b83a3937b63632b960a91b815260200192915050565b6000615929600583615ed4565b64524550415960d81b815260200192915050565b600061594a600383615ed4565b6269726d60e81b815260200192915050565b6000615969600683615ed4565b6565785261746560d01b815260200192915050565b600061598b600983615ed4565b68189bdc9c9bddd0985b60ba1b815260200192915050565b60006159b0600383615ed4565b6239bab160e91b815260200192915050565b60006159cf600483615ed4565b631352539560e21b815260200192915050565b61564581610d49565b61564581615f04565b600061152f8284615695565b60208101610af6828461564b565b60608101615a1c828661563c565b615a2960208301856159e2565b610fb660408301846159e2565b60808101615a44828761563c565b615a5160208301866159e2565b615a5e60408301856159e2565b6139d460608301846159e2565b60408101615a79828561564b565b61152f602083018461564b565b60608101615a94828661564b565b615a29602083018561563c565b60808101615aaf828761564b565b615a51602083018661563c565b60a08101615aca828861564b565b615ad7602083018761564b565b615ae4604083018661564b565b615af1606083018561564b565b61403160808301846159e2565b60808101615b0c828761564b565b615b19602083018661564b565b615a5e604083018561564b565b60608101615b34828661564b565b615b41602083018561564b565b610fb66040830184615654565b60608101615b5c828661564b565b615a29602083018561564b565b60a08101615b77828861564b565b615b84602083018761564b565b615ae460408301866159e2565b60808101615b9f828761564b565b615a51602083018661564b565b60a08101615bba828861564b565b615bc7602083018761564b565b615bd460408301866159e2565b615af160608301856159e2565b60408101615bef828561564b565b61152f60208301846159e2565b60608101615a1c828661564b565b60208101610af68284615654565b6020808252810161152f818461565d565b60208101610af682846156c4565b60408101615c4582856156c4565b61152f60208301846156c4565b60208082528101610af6816156d6565b60208082528101610af6816156f7565b60208082528101610af681615716565b60208082528101610af68161573b565b60208082528101610af68161575d565b60208082528101610af68161577e565b60208082528101610af68161579d565b60208082528101610af6816157c7565b60208082528101610af6816157e9565b60208082528101610af68161580b565b60208082528101610af68161582a565b60208082528101610af681615849565b60208082528101610af681615868565b60208082528101610af681615888565b60208082528101610af6816158ae565b60208082528101610af6816158d3565b60208082528101610af6816158f5565b60208082528101610af68161591c565b60208082528101610af68161593d565b60208082528101610af68161595c565b60208082528101610af68161597e565b60208082528101610af6816159a3565b60208082528101610af6816159c2565b60208101610af682846159e2565b60408101615a7982856159e2565b60608101615dec82866159e2565b615df9602083018561563c565b610fb6604083018461564b565b60608101615e1482866159e2565b615df9602083018561564b565b60408101615bef82856159e2565b60608101615e3d82866159e2565b615e4a60208301856159e2565b610fb660408301846156cd565b60608101615a1c82866159e2565b60808101615a4482876159e2565b60208101610af682846159eb565b60405181810167ffffffffffffffff81118282101715615ea057600080fd5b604052919050565b600067ffffffffffffffff821115615ebf57600080fd5b506020601f91909101601f19160190565b5190565b90815260200190565b6000610af682615ef8565b151590565b6000610af682615edd565b6001600160a01b031690565b60ff1690565b6000610af682615eed565b6000610af682610d49565b82818337506000910152565b60005b83811015615f47578181015183820152602001615f2f565b838111156110385750506000910152565b601f01601f191690565b615f6b81615edd565b811461221e57600080fd5b615f6b81615ee8565b615f6b81615eed565b615f6b81610d49565b615f6b81615f0456feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa365627a7a72315820bdb98c5a247a2e6739d6a8223c49daa6ba7dfaf29983cdcfcc31ea2814f3e3656c6578706572696d656e74616cf564736f6c63430005110040
Deployed Bytecode Sourcemap
444:2321:2:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;961:18:4;;8:9:-1;5:2;;;30:1;27;20:12;5:2;961:18:4;;;:::i;:::-;;;;;;;;;;;;;;;;7366:232:3;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;7366:232:3;;;;;;;;:::i;:::-;;;;;;;;3662:146:0;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;3662:146:0;;;;;;;;:::i;:::-;;;;;;;;1303:1760:3;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;1303:1760:3;;;;;;;;:::i;:::-;;2391:33:4;;8:9:-1;5:2;;;30:1;27;20:12;5:2;2391:33:4;;;:::i;11595:209:3:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;11595:209:3;;;;;;;;:::i;3267:23:4:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;3267:23:4;;;:::i;14303:210:3:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;14303:210:3;;;:::i;3438:459:1:-;;;:::i;6706:200:3:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;6706:200:3;;;;;;;;:::i;4088:186:0:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;4088:186:0;;;;;;;;:::i;1147:21:4:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;1147:21:4;;;:::i;:::-;;;;;;;;69290:255:3;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;69290:255:3;;;;;;;;:::i;8602:321::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;8602:321:3;;;;;;;;:::i;16168:86::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;16168:86:3;;;:::i;2785:24:4:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;2785:24:4;;;:::i;2929:330:1:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;2929:330:1;;;;;;;;:::i;763:677:2:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;763:677:2;;;;;;;;:::i;9774:29:4:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;9774:29:4;;;:::i;:::-;;;;;;;;1714:39;;8:9:-1;5:2;;;30:1;27;20:12;5:2;1714:39:4;;;:::i;:::-;;;;;;;;58444:570:3;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;58444:570:3;;;;;;;;:::i;3038:26:4:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;3038:26:4;;;:::i;4210:56::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;4210:56:4;;;:::i;2509:30::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;2509:30:4;;;:::i;8835:25::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;8835:25:4;;;:::i;8244:110:3:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;8244:110:3;;;;;;;;:::i;11134:177::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;11134:177:3;;;:::i;8474:175:0:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;8474:175:0;;;;;;;;:::i;2958:131::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;2958:131:0;;;;;;;;:::i;2151:28:4:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;2151:28:4;;;:::i;2910:25::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;2910:25:4;;;:::i;53472:571:3:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;53472:571:3;;;;;;;;:::i;1052:20:4:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;1052:20:4;;;:::i;12006:237:3:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;12006:237:3;;;;;;;;:::i;61153:587::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;61153:587:3;;;;;;;;:::i;2026:130:0:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;2026:130:0;;;;;;;;:::i;804:842::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;804:842:0;;;;;;;;:::i;16495:1018:3:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;16495:1018:3;;;:::i;63675:592::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;63675:592:3;;;;;;;;:::i;6218:190::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;6218:190:3;;;;;;;;:::i;2655:23:4:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;2655:23:4;;;:::i;579:40:2:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;579:40:2;;;:::i;4557:37:4:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;4557:37:4;;;:::i;10732:262:3:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;10732:262:3;;;:::i;48190:198::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;48190:198:3;;;;;;;;:::i;13877:183::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;13877:183:3;;;:::i;9261:685::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;9261:685:3;;;;;;;;:::i;:::-;;;;;;;;;;;3350:111:0;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;3350:111:0;;;;;;;;:::i;2499:::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;2499:111:0;;;;;;;;:::i;2272:27:4:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;2272:27:4;;;:::i;3166:25::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;3166:25:4;;;:::i;7920:141:3:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;7920:141:3;;;;;;;;:::i;545:27:2:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;545:27:2;;;:::i;66388:625:3:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;66388:625:3;;;;;;;;:::i;1850:42:4:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;1850:42:4;;;:::i;4746:234:0:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;4746:234:0;;;;;;;;:::i;10360:202:3:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;10360:202:3;;;:::i;56327:606::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;56327:606:3;;;;;;;;:::i;4415:36:4:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;4415:36:4;;;:::i;961:18::-;;;;;;;;;;;;;;-1:-1:-1;;961:18:4;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;7366:232:3:-;7464:10;7434:4;7484:23;;;:18;:23;;;;;;;;-1:-1:-1;;;;;7484:32:3;;;;;;;;;;:41;;;7540:30;7434:4;;7464:10;;;7540:30;;;;7519:6;;7540:30;;;;;;;;;;7587:4;7580:11;;;7366:232;;;;;:::o;3662:146:0:-;3719:4;3736:8;3749:32;3769:11;3749:19;:32::i;:::-;-1:-1:-1;3735:46:0;-1:-1:-1;;3662:146:0;;;;:::o;1303:1760:3:-;1744:10;327:42:4;1744:32:3;1736:51;;;;-1:-1:-1;;;1736:51:3;;;;;;;;;;;;;;;;;1805:18;;:23;:43;;;;-1:-1:-1;1832:11:3;;:16;1805:43;1797:60;;;;-1:-1:-1;;;1797:60:3;;;;;;;;;1905:27;:58;;;1981:31;1973:53;;;;-1:-1:-1;;;1973:53:3;;;;;;;;;2068:8;2079:29;2095:12;2079:15;:29::i;:::-;2068:40;-1:-1:-1;2126:27:3;;2118:51;;;;-1:-1:-1;;;2118:51:3;;;;;;;;;2306:16;:14;:16::i;:::-;2285:18;:37;410:4:12;2332:11:3;:25;2454:46;2481:18;2454:26;:46::i;:::-;2448:52;-1:-1:-1;2518:27:3;;2510:43;;;;-1:-1:-1;;;2510:43:3;;;;;;;;;2564:12;;;;:4;;:12;;;;;:::i;:::-;-1:-1:-1;2586:16:3;;;;:6;;:16;;;;;:::i;:::-;-1:-1:-1;2612:8:3;:20;;-1:-1:-1;;2612:20:3;;;;;;;2679:46;2702:22;2679;:46::i;:::-;2673:52;-1:-1:-1;2743:27:3;;2735:54;;;;-1:-1:-1;;;2735:54:3;;;;;;;;;2831:36;2849:17;2831;:36::i;:::-;2825:42;-1:-1:-1;2885:27:3;;2877:43;;;;-1:-1:-1;;;2877:43:3;;;;;;;;;-1:-1:-1;;3052:4:3;3038:18;;-1:-1:-1;;;;3038:18:3;-1:-1:-1;;;3038:18:3;;;-1:-1:-1;;;;;;;1303:1760:3:o;2391:33:4:-;;;;:::o;11595:209:3:-;11680:4;11664:5;70787:30;70807:9;70787:19;:30::i;:::-;11729:14;11704:16;:14;:16::i;:::-;:40;11696:56;;;;-1:-1:-1;;;11696:56:3;;;;;;;;;11769:28;11789:7;11769:19;:28::i;:::-;11762:35;;70827:1;70838:29;70857:9;70838:18;:29::i;:::-;11595:209;;;;:::o;3267:23:4:-;;;;:::o;14303:210:3:-;14354:4;14371:13;14386:11;14401:28;:26;:28::i;:::-;14370:59;;-1:-1:-1;14370:59:3;-1:-1:-1;14454:18:3;14447:3;:25;;;;;;;;;14439:44;;;;-1:-1:-1;;;14439:44:3;;;;;;;;;14500:6;-1:-1:-1;;14303:210:3;;:::o;3438:459:1:-;3489:10;3511:4;3489:27;;;;:94;;;3549:11;;;;;;;;;-1:-1:-1;;;;;3549:11:1;-1:-1:-1;;;;;3520:61:1;;:63;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;3520:63:1;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;3520:63:1;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;3520:63:1;;;;;;;;;3485:406;;;3600:28;3720:14;;3689:46;;-1:-1:-1;;;3689:46:1;;3600:28;;3648:37;;327:42:4;;3689:30:1;;:46;;-1:-1:-1;;;;;3720:14:1;;3689:46;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;3689:46:1;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;3689:46:1;;;;;;39:16:-1;36:1;17:17;2:54;101:4;3689:46:1;80:15:-1;;;-1:-1;;76:31;65:43;;120:4;113:20;3689:46:1;;;;;;;;;3753:14;;3599:136;;-1:-1:-1;3599:136:1;;-1:-1:-1;3599:136:1;-1:-1:-1;;;;;;3753:38:1;;;:14;;:38;3749:131;;3793:87;3820:20;3842:11;3855:24;3793:26;:87::i;:::-;3485:406;;;;3438:459::o;6706:200:3:-;6808:4;6792:5;70787:30;70807:9;70787:19;:30::i;:::-;6884:14;6831:44;6846:10;6858:3;6863;6868:6;6831:14;:44::i;:::-;:68;6824:75;;70838:29;70857:9;70838:18;:29::i;:::-;6706:200;;;;;;:::o;4088:186:0:-;4169:4;4186:8;4199:48;4225:8;4235:11;4199:25;:48::i;:::-;-1:-1:-1;4185:62:0;4088:186;-1:-1:-1;;;;4088:186:0:o;1147:21:4:-;;;;;;:::o;69290:255:3:-;69425:16;:14;:16::i;:::-;69417:35;;;;-1:-1:-1;;;69417:35:3;;;;;;;;;69500:12;:4;69507:5;;69500:12;:::i;:::-;-1:-1:-1;69522:16:3;:6;69531:7;;69522:16;:::i;:::-;;69290:255;;;;:::o;8602:321::-;8664:4;8680:23;;:::i;:::-;8706:38;;;;;;;;8721:21;:19;:21::i;:::-;8706:38;;-1:-1:-1;;;;;8819:20:3;;8755:14;8819:20;;;:13;:20;;;;;;8680:64;;-1:-1:-1;8755:14:3;;;8787:53;;8680:64;;8787:17;:53::i;:::-;8754:86;;-1:-1:-1;8754:86:3;-1:-1:-1;8866:18:3;8858:4;:26;;;;;;;;;8850:42;;;;-1:-1:-1;;;8850:42:3;;;;;;;;;8909:7;8602:321;-1:-1:-1;;;;8602:321:3:o;16168:86::-;16210:4;16233:14;:12;:14::i;:::-;16226:21;;16168:86;:::o;2785:24:4:-;;;;:::o;2929:330:1:-;3102:16;:14;:16::i;:::-;3094:35;;;;-1:-1:-1;;;3094:35:1;;;;;;;;;3170:82;3197:15;3214:11;3227:24;;3170:82;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;3170:26:1;;-1:-1:-1;;;3170:82:1:i;:::-;2929:330;;;;:::o;763:677:2:-;842:10;864:4;842:27;;:47;;;873:16;:14;:16::i;:::-;834:56;;;;;;902:15;921:61;;;;945:4;921:61;;;901:81;-1:-1:-1;;;;;;1001:21:2;;993:40;;;;-1:-1:-1;;;993:40:2;;;;;;;;;1056:6;;-1:-1:-1;;;;;1056:6:2;1048:29;1044:136;;1093:6;;1107:31;;-1:-1:-1;;;1107:31:2;;-1:-1:-1;;;;;1093:6:2;;;;:13;;:6;;1107:16;;:31;;1132:4;;1107:31;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;1107:31:2;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;1107:31:2;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;1107:31:2;;;;;;;;;1148:4;1163;1093:76;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;1093:76:2;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;1093:76:2;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;1093:76:2;;;;;;;;;;1044:136;1190:6;:31;;-1:-1:-1;;;;;;1190:31:2;-1:-1:-1;;;;;1190:31:2;;;;;;;;;;1247:10;;1232:56;;-1:-1:-1;;;1232:56:2;;1247:10;;;1232:34;;:56;;1190:31;;-1:-1:-1;;1284:2:2;1232:56;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;1232:56:2;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;1232:56:2;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;1232:56:2;;;;;;;;;-1:-1:-1;1331:10:2;;1316:51;;-1:-1:-1;;;1316:51:2;;1299:14;;-1:-1:-1;;;;;1331:10:2;;1316:36;;:51;;1361:4;;1316:51;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;1316:51:2;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;1316:51:2;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;1316:51:2;;;;;;;;;1299:68;-1:-1:-1;1381:11:2;;1377:57;;1408:15;1416:6;1408:7;:15::i;9774:29:4:-;;;-1:-1:-1;;;;;9774:29:4;;:::o;1714:39::-;;;-1:-1:-1;;;;;1714:39:4;;:::o;58444:570:3:-;58526:4;58510:5;70787:30;70807:9;70787:19;:30::i;:::-;58542:10;58555:16;:14;:16::i;:::-;58542:29;-1:-1:-1;58585:29:3;;58581:274;;58774:70;58785:5;58779:12;;;;;;;;58793:50;58774:4;:70::i;:::-;58767:77;;;;;58581:274;58973:34;58994:12;58973:20;:34::i;:::-;58966:41;;;70838:29;70857:9;70838:18;:29::i;3038:26:4:-;;;;:::o;4210:56::-;4260:6;4210:56;:::o;2509:30::-;;;;:::o;8835:25::-;;;-1:-1:-1;;;;;8835:25:4;;:::o;8244:110:3:-;-1:-1:-1;;;;;8327:20:3;8301:7;8327:20;;;:13;:20;;;;;;;8244:110::o;11134:177::-;11203:4;11187:5;70787:30;70807:9;70787:19;:30::i;:::-;11252:14;11227:16;:14;:16::i;:::-;:40;11219:56;;;;-1:-1:-1;;;11219:56:3;;;;;;;;;11292:12;;11285:19;;70838:29;70857:9;70838:18;:29::i;:::-;11134:177;;:::o;8474:175:0:-;8557:16;:14;:16::i;:::-;8549:35;;;;-1:-1:-1;;;8549:35:0;;;;;;;;;8603:10;;8594:48;;-1:-1:-1;;;8594:48:0;;-1:-1:-1;;;;;8603:10:0;;;;8594:29;;:48;;8624:17;;8594:48;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;8594:48:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;2958:131:0;3021:4;3044:38;3069:12;3044:24;:38::i;2151:28:4:-;;;;:::o;2910:25::-;;;;:::o;53472:571:3:-;53558:4;53542:5;70787:30;70807:9;70787:19;:30::i;:::-;53574:10;53587:16;:14;:16::i;:::-;53574:29;-1:-1:-1;53617:29:3;;53613:273;;53807:68;53818:5;53812:12;;;;;;;;53826:48;53807:4;:68::i;53613:273::-;53998:38;54016:19;53998:17;:38::i;1052:20:4:-;;;;;;;;;;;;;;;-1:-1:-1;;1052:20:4;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12006:237:3;12073:4;12090:13;12105:11;12120:36;12148:7;12120:27;:36::i;:::-;12089:67;;-1:-1:-1;12089:67:3;-1:-1:-1;12181:18:3;12174:3;:25;;;;;;;;;12166:47;;;;-1:-1:-1;;;12166:47:3;;;;;;;;;12230:6;12006:237;-1:-1:-1;;;12006:237:3:o;61153:587::-;61239:4;61223:5;70787:30;70807:9;70787:19;:30::i;:::-;61255:10;61268:16;:14;:16::i;:::-;61255:29;-1:-1:-1;61298:29:3;;61294:281;;61491:73;61502:5;61496:12;;;;;;;;61510:53;61491:4;:73::i;61294:281::-;61695:38;61718:14;61695:22;:38::i;2026:130:0:-;2075:4;2092:8;2105:24;2118:10;2105:12;:24::i;804:842::-;1237:36;1276:6;1237:45;;1292:15;1325:11;-1:-1:-1;;;;;1310:36:0;;:38;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;1310:38:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;1310:38:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;1310:38:0;;;;;;;;;1292:56;;1358:150;1375:12;1389:18;1409:28;1439:5;1446:7;1455:9;1466:22;1490:17;1358:16;:150::i;:::-;1565:10;:24;;-1:-1:-1;;;;;;1565:24:0;-1:-1:-1;;;;;1565:24:0;;;;;;;;;;;1599:40;;;-1:-1:-1;;;1599:40:0;;;;1614:10;;;;;1599:38;;:40;;;;;;;;;;;;;;;1614:10;1599:40;;;5:2:-1;;;;30:1;27;20:12;5:2;1599:40:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;1599:40:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;1599:40:0;;;;;;;;;;804:842;;;;;;;;;:::o;16495:1018:3:-;16537:4;16601:23;16627:16;:14;:16::i;:::-;16601:42;;16732:18;16710;;:40;16706:98;;;16778:14;16766:27;;;;;16706:98;16868:14;16885;:12;:14::i;:::-;16868:31;;16967:23;16993:17;;;;;;;;;-1:-1:-1;;;;;16993:17:3;-1:-1:-1;;;;;16993:31:3;;17025:9;17036:12;;17050:56;17055:13;;17070:35;17075:14;;17091:13;;17070:4;:35::i;:::-;17050:4;:56::i;:::-;16993:114;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;16993:114:3;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;16993:114:3;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;16993:114:3;;;;;;;;;16967:140;;1315:9:4;17125:18:3;:43;;17117:59;;;;-1:-1:-1;;;17117:59:3;;;;;;;;;17264:17;17283:15;17302:47;17310:18;17330;;17302:7;:47::i;:::-;17263:86;;-1:-1:-1;17263:86:3;-1:-1:-1;17378:18:3;17367:7;:29;;;;;;;;;17359:45;;;;-1:-1:-1;;;17359:45:3;;;;;;;;;17422:84;17444:18;17464:9;17475:18;17495:10;17422:21;:84::i;:::-;17415:91;;;;;;;16495:1018;:::o;63675:592::-;63762:4;63746:5;70787:30;70807:9;70787:19;:30::i;:::-;63778:10;63791:16;:14;:16::i;:::-;63778:29;-1:-1:-1;63821:29:3;;63817:283;;64015:74;64026:5;64020:12;;;;;;;;64034:54;64015:4;:74::i;63817:283::-;64221:39;64245:14;64221:23;:39::i;6218:190::-;6303:4;6287:5;70787:30;70807:9;70787:19;:30::i;:::-;6386:14;6326:51;6341:10;6353;6365:3;6370:6;6326:14;:51::i;:::-;:75;6319:82;;70838:29;70857:9;70838:18;:29::i;:::-;6218:190;;;;;:::o;2655:23:4:-;;;;:::o;579:40:2:-;615:4;579:40;:::o;4557:37:4:-;4589:5;4557:37;:::o;10732:262:3:-;10808:17;;10785:4;;-1:-1:-1;;;;;10808:17:3;:31;10840:14;:12;:14::i;:::-;10856:12;;10870:56;10875:13;;10890:35;10895:14;;10911:13;;10890:4;:35::i;10870:56::-;10970:16;;10952:15;;10928:21;;:39;:58;10808:179;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;10808:179:3;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;10808:179:3;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;10808:179:3;;;;;;;;48190:198;48298:4;48283;70787:30;70807:9;70787:19;:30::i;:::-;48321:60;48335:10;48347;48359:8;48369:11;48321:13;:60::i;:::-;48314:67;;70838:29;70857:9;70838:18;:29::i;13877:183::-;13944:4;13928:5;70787:30;70807:9;70787:19;:30::i;:::-;13993:14;13968:16;:14;:16::i;:::-;:40;13960:56;;;;-1:-1:-1;;;13960:56:3;;;;;;;;;14033:20;:18;:20::i;:::-;14026:27;;70838:29;70857:9;70838:18;:29::i;9261:685::-;-1:-1:-1;;;;;9384:22:3;;9329:4;9384:22;;;:13;:22;;;;;;9329:4;;;;;;;;;9529:36;9398:7;9529:27;:36::i;:::-;9505:60;-1:-1:-1;9505:60:3;-1:-1:-1;9587:18:3;9579:4;:26;;;;;;;;;9575:97;;9634:16;9629:22;9621:40;-1:-1:-1;9653:1:3;;-1:-1:-1;9653:1:3;;-1:-1:-1;9653:1:3;;-1:-1:-1;9621:40:3;;-1:-1:-1;;;;9621:40:3;9575:97;9713:28;:26;:28::i;:::-;9682:59;-1:-1:-1;9682:59:3;-1:-1:-1;9763:18:3;9755:4;:26;;;;;;;;;9751:97;;9810:16;9805:22;;9751:97;-1:-1:-1;9871:14:3;;-1:-1:-1;9888:13:3;;-1:-1:-1;9903:13:3;-1:-1:-1;9903:13:3;-1:-1:-1;9261:685:3;;;;;;:::o;3350:111:0:-;3403:4;3426:28;3441:12;3426:14;:28::i;2499:111::-;2552:4;2575:28;2590:12;2575:14;:28::i;2272:27:4:-;;;;:::o;3166:25::-;;;;:::o;7920:141:3:-;-1:-1:-1;;;;;8020:25:3;;;7994:7;8020:25;;;:18;:25;;;;;;;;:34;;;;;;;;;;;;;7920:141::o;545:27:2:-;;;-1:-1:-1;;;;;545:27:2;;:::o;66388:625:3:-;66475:4;66491:10;66504:16;:14;:16::i;:::-;66491:29;-1:-1:-1;66534:29:3;;66530:295;;66736:78;66747:5;66741:12;;;;;;;;66755:58;66736:4;:78::i;:::-;66729:85;;;;;66530:295;66958:48;66985:20;66958:26;:48::i;1850:42:4:-;;;-1:-1:-1;;;;;1850:42:4;;:::o;4746:234:0:-;4859:4;4876:8;4889:64;4913:8;4923:11;4936:16;4889:23;:64::i;:::-;-1:-1:-1;4875:78:0;4746:234;-1:-1:-1;;;;;4746:234:0:o;10360:202:3:-;10436:17;;10413:4;;-1:-1:-1;;;;;10436:17:3;:31;10468:14;:12;:14::i;:::-;10484:12;;10498:56;10503:13;;10518:35;10523:14;;10539:13;;10518:4;:35::i;10498:56::-;10436:119;;;;;;;;;;;;;;;;;;56327:606;56423:4;56407:5;70787:30;70807:9;70787:19;:30::i;:::-;56439:10;56452:16;:14;:16::i;:::-;56439:29;-1:-1:-1;56482:29:3;;56478:283;;56677:73;56688:5;56682:12;;;;;;;;56696:53;56677:4;:73::i;56478:283::-;56878:48;56901:24;56878:22;:48::i;4415:36:4:-;4447:4;4415:36;:::o;36626:571:3:-;36711:4;36717;36695:5;70787:30;70807:9;70787:19;:30::i;:::-;36733:10;36746:16;:14;:16::i;:::-;36733:29;-1:-1:-1;36776:29:3;;36772:257;;36947:67;36958:5;36952:12;;;;;;;;36966:47;36947:4;:67::i;:::-;36939:79;-1:-1:-1;37016:1:3;;-1:-1:-1;36939:79:3;;-1:-1:-1;36939:79:3;36772:257;37137:53;37154:10;37166;37178:11;37137:16;:53::i;:::-;37130:60;;;;;70827:1;70838:29;70857:9;70838:18;:29::i;:::-;36626:571;;;;:::o;52658:533::-;52738:4;52754:35;52792:11;;;;;;;;;-1:-1:-1;;;;;52792:11:3;52754:49;;52887:14;-1:-1:-1;;;;;52887:28:3;;:30;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;52887:30:3;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;52887:30:3;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;52887:30:3;;;;;;;;;52879:49;;;;-1:-1:-1;;;52879:49:3;;;;;;;;;52993:11;:28;;-1:-1:-1;;;;;;52993:28:3;-1:-1:-1;;;;;52993:28:3;;;;;53100:46;;;;;;53115:14;;52993:28;;53100:46;;;;;;;;;;53169:14;53164:20;;10099:91;10171:12;10099:91;:::o;67335:1612::-;67429:4;67528:38;67615:16;:14;:16::i;:::-;67610:128;;67654:73;67659:18;67679:47;67654:4;:73::i;67610:128::-;67861:16;:14;:16::i;:::-;67839:18;;:38;67835:153;;67900:77;67905:22;67929:47;67900:4;:77::i;67835:153::-;68079:17;;;;;;;;;-1:-1:-1;;;;;68079:17:3;68056:40;;68196:20;-1:-1:-1;;;;;68196:40:3;;:42;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;68196:42:3;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;68196:42:3;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;68196:42:3;;;;;;;;;68188:61;;;;-1:-1:-1;;;68188:61:3;;;;;;;;;68323:17;:40;;-1:-1:-1;;;;;;68323:40:3;-1:-1:-1;;;;;68323:40:3;;;;;68466:70;;;;;;68493:20;;68323:40;;68466:70;;;;;;;;;;-1:-1:-1;;;;;68611:43:3;;;68607:138;;68691:53;;;22:32:-1;6:49;;68691:53:3;;;;;49:4:-1;25:18;;61:17;;-1:-1;;;;;182:15;-1:-1;;;179:29;160:49;;68656:89:3;;-1:-1:-1;;;;;68656:34:3;;;:89;;;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;;68656:89:3;;68607:138;68854:47;;;22:32:-1;6:49;;68854:47:3;;;;;49:4:-1;25:18;;61:17;;-1:-1;;;;;182:15;-1:-1;;;179:29;160:49;;68819:83:3;;-1:-1:-1;;;;;68819:34:3;;;:83;;;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;-1:-1;68925:14:3;;-1:-1:-1;68920:20:3;;-1:-1:-1;68920:20:3;57194:1004;57275:4;57329:16;:14;:16::i;:::-;57324:123;;57368:68;57373:18;57393:42;57368:4;:68::i;:::-;57361:75;;;;57324:123;57551:16;:14;:16::i;:::-;57529:18;;:38;57525:148;;57590:72;57595:22;57619:42;57590:4;:72::i;57525:148::-;1491:4:4;57742:71:3;57747:48;57752:24;57778:16;;57747:4;:48::i;:::-;57797:15;;57742:4;:71::i;:::-;:106;57738:210;;;57871:66;57876:15;57893:43;57871:4;:66::i;57738:210::-;57990:21;;;58021:48;;;;58085:68;;;;;;57990:21;;58045:24;;58085:68;;54294:1737;54365:4;54475:16;:14;:16::i;:::-;54453:18;;:38;54449:143;;54514:67;54519:22;54543:37;54514:4;:67::i;54449:143::-;-1:-1:-1;;54646:19:3;:31;54642:75;;;54701:16;;54679:38;;54642:75;54759:23;54785:28;:26;:28::i;:::-;54759:54;;1491:4:4;54947:74:3;54952:48;54957:21;;54980:19;54952:4;:48::i;:::-;55002:18;54947:4;:74::i;:::-;:109;54943:208;;;55079:61;55084:15;55101:38;55079:4;:61::i;54943:208::-;55217:19;55197:16;;:39;55193:470;;55294:16;:14;:16::i;:::-;55289:126;;55337:63;55342:18;55362:37;55337:4;:63::i;55289:126::-;55485:16;;;55515:38;;;;55599:53;;;;;;55485:16;;55534:19;;55599:53;;;;;;;;;;55193:470;;55727:18;55708:15;;:37;55704:283;;55815:15;;;55844:36;;;;55926:50;;;;;;55815:15;;55862:18;;55926:50;;;;;;;;;;55704:283;;56009:14;56004:20;;71187:192;71258:11;;-1:-1:-1;;;71258:11:3;;;;71250:34;;;;-1:-1:-1;;;71250:34:3;;;;;;;;;71299:9;71294:49;;71310:11;;;;;;;;;-1:-1:-1;;;;;71310:11:3;-1:-1:-1;;;;;71310:31:3;;:33;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;71310:33:3;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;71310:33:3;;;;71294:49;-1:-1:-1;71353:11:3;:19;;-1:-1:-1;;;;71353:19:3;;;71187:192::o;71691:179::-;71767:4;71753:18;;-1:-1:-1;;;;71753:18:3;-1:-1:-1;;;71753:18:3;;;71820:9;71815:48;;71831:11;;;;;;;;;-1:-1:-1;;;;;71831:11:3;-1:-1:-1;;;;;71831:30:3;;:32;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;71815:48:3;71691:179;:::o;14770:1234::-;14878:11;;14831:9;;;;14903:17;14899:1099;;-1:-1:-1;;15092:27:3;;15072:18;;-1:-1:-1;15064:56:3;;14899:1099;15331:14;15348;:12;:14::i;:::-;15331:31;;15376:33;15423:23;;:::i;:::-;15460:17;15534:97;15549:9;15560:12;;15574:56;15579:13;;15594:35;15599:14;;15615:13;;15594:4;:35::i;15574:56::-;15534:14;:97::i;:::-;15492:139;-1:-1:-1;15492:139:3;-1:-1:-1;15660:18:3;15649:7;:29;;;;;;;;;15645:87;;15706:7;-1:-1:-1;15715:1:3;;-1:-1:-1;15698:19:3;;-1:-1:-1;;;;15698:19:3;15645:87;15772:50;15779:28;15809:12;15772:6;:50::i;:::-;15746:76;-1:-1:-1;15746:76:3;-1:-1:-1;15851:18:3;15840:7;:29;;;;;;;;;15836:87;;15897:7;-1:-1:-1;15906:1:3;;-1:-1:-1;15889:19:3;;-1:-1:-1;;;;15889:19:3;15836:87;-1:-1:-1;15965:21:3;15945:18;;-1:-1:-1;15965:21:3;-1:-1:-1;15937:50:3;;-1:-1:-1;;;15937:50:3;14770:1234;;;:::o;1671:865:1:-;1877:14;;1843:79;;-1:-1:-1;;;1843:79:1;;327:42:4;;1843:33:1;;:79;;-1:-1:-1;;;;;1877:14:1;;1893:15;;1910:11;;1843:79;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;1843:79:1;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;1843:79:1;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;1843:79:1;;;;;;;;;1835:97;;;;-1:-1:-1;;;1835:97:1;;;;;;;;;2019:11;2015:40;;;2032:23;:21;:23::i;:::-;2100:25;2128:14;;-1:-1:-1;;;;;2189:32:1;;;-1:-1:-1;;;;;;2189:32:1;;;;;;2346:81;;2128:14;;;2317:122;;2339:4;;2346:81;;2402:24;;2346:81;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;2346:81:1;;;49:4:-1;25:18;;;61:17;;-1:-1;;;;;182:15;-1:-1;;;179:29;160:49;;2317:122:1;;;;;;;;;;;-1:-1:-1;;;2317:122:1;;;;:13;:122::i;:::-;-1:-1:-1;2514:14:1;;2477:52;;;;;;2495:17;;-1:-1:-1;;;;;2514:14:1;;2477:52;;;;;;;;;;1671:865;;;;:::o;3739:2226:3:-;3911:11;;:60;;-1:-1:-1;;;3911:60:3;;3837:4;;;;-1:-1:-1;;;;;3911:11:3;;;;:27;;:60;;3947:4;;3954:3;;3959;;3964:6;;3911:60;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;3911:60:3;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;3911:60:3;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;3911:60:3;;;;;;;;;3896:75;-1:-1:-1;3985:12:3;;3981:142;;4020:92;4031:27;4060:42;4104:7;4020:10;:92::i;:::-;4013:99;;;;;3981:142;4186:3;-1:-1:-1;;;;;4179:10:3;:3;-1:-1:-1;;;;;4179:10:3;;4175:103;;;4212:55;4217:15;4234:32;4212:4;:55::i;4175:103::-;4352:22;-1:-1:-1;;;;;4392:14:3;;;;;;;4388:156;;;-1:-1:-1;;;4388:156:3;;;-1:-1:-1;;;;;;4501:23:3;;;;;;;:18;:23;;;;;;;;:32;;;;;;;;;;4388:156;4619:17;4646;4673;4700;4754:34;4762:17;4781:6;4754:7;:34::i;:::-;4728:60;;-1:-1:-1;4728:60:3;-1:-1:-1;4813:18:3;4802:7;:29;;;;;;;;;4798:123;;4854:56;4859:16;4877:32;4854:4;:56::i;:::-;4847:63;;;;;;;;;;4798:123;-1:-1:-1;;;;;4965:18:3;;;;;;:13;:18;;;;;;4957:35;;4985:6;4957:7;:35::i;:::-;4931:61;;-1:-1:-1;4931:61:3;-1:-1:-1;5017:18:3;5006:7;:29;;;;;;;;;5002:122;;5058:55;5063:16;5081:31;5058:4;:55::i;5002:122::-;-1:-1:-1;;;;;5168:18:3;;;;;;:13;:18;;;;;;5160:35;;5188:6;5160:7;:35::i;:::-;5134:61;;-1:-1:-1;5134:61:3;-1:-1:-1;5220:18:3;5209:7;:29;;;;;;;;;5205:120;;5261:53;5266:16;5284:29;5261:4;:53::i;5205:120::-;-1:-1:-1;;;;;5452:18:3;;;;;;;:13;:18;;;;;;:33;;;5495:18;;;;;;:33;;;-1:-1:-1;;5598:29:3;;5594:107;;-1:-1:-1;;;;;5643:23:3;;;;;;;:18;:23;;;;;;;;:32;;;;;;;;;:47;;;5594:107;5769:3;-1:-1:-1;;;;;5755:26:3;5764:3;-1:-1:-1;;;;;5755:26:3;-1:-1:-1;;;;;;;;;;;5774:6:3;5755:26;;;;;;;;;;;;;;;-1:-1:-1;5943:14:3;;3739:2226;-1:-1:-1;;;;;;;;;;3739:2226:3:o;37522:593::-;37631:4;37637;37615:5;70787:30;70807:9;70787:19;:30::i;:::-;37653:10;37666:16;:14;:16::i;:::-;37653:29;-1:-1:-1;37696:29:3;;37692:257;;37867:67;37878:5;37872:12;;;;;;;;37886:47;37867:4;:67::i;:::-;37859:79;-1:-1:-1;37936:1:3;;-1:-1:-1;37859:79:3;;-1:-1:-1;37859:79:3;37692:257;38057:51;38074:10;38086:8;38096:11;38057:16;:51::i;:::-;38050:58;;;;;70827:1;70838:29;70857:9;70838:18;:29::i;:::-;37522:593;;;;;;:::o;529:335::-;665:11;;710:26;;;-1:-1:-1;;;710:26:3;;;;578:4;;-1:-1:-1;;;;;665:11:3;;;;710:24;;:26;;;;;;;;;;;;;;;665:11;710:26;;;5:2:-1;;;;30:1;27;20:12;5:2;710:26:3;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;710:26:3;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;710:26:3;;;;;;;;;-1:-1:-1;;;;;696:40:3;:10;-1:-1:-1;;;;;696:40:3;;:79;;;;;740:18;-1:-1:-1;;;;;740:33:3;;:35;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;740:35:3;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;740:35:3;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;740:35:3;;;;;;;;;695:162;;;-1:-1:-1;781:10:3;327:42:4;781:32:3;:75;;;;;817:18;-1:-1:-1;;;;;817:37:3;;:39;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;817:39:3;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;817:39:3;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;817:39:3;;;;;;;;2432:306:11;2509:9;2520:4;2537:13;2552:18;;:::i;:::-;2574:20;2584:1;2587:6;2574:9;:20::i;:::-;2536:58;;-1:-1:-1;2536:58:11;-1:-1:-1;2615:18:11;2608:3;:25;;;;;;;;;2604:71;;-1:-1:-1;2657:3:11;-1:-1:-1;2662:1:11;;-1:-1:-1;2649:15:11;;2604:71;2693:18;2713:17;2722:7;2713:8;:17::i;:::-;2685:46;;;;;;2432:306;;;;;;:::o;1661:110:2:-;1734:6;;:30;;-1:-1:-1;;;1734:30:2;;1708:7;;-1:-1:-1;;;;;1734:6:2;;:15;;:30;;1758:4;;1734:30;;;;2330:96;2382:6;;:37;;-1:-1:-1;;;2382:37:2;;-1:-1:-1;;;;;2382:6:2;;;;:14;;:37;;2397:6;;2413:4;;2382:37;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;2382:37:2;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;2382:37:2;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;2382:37:2;;;;;;;;;;2330:96;:::o;8569:149:10:-;8630:4;8651:33;8664:3;8659:9;;;;;;;;8675:4;8670:10;;;;;;;;8682:1;8651:33;;;;;;;;;;;;;;;;;8707:3;8702:9;;;;;;;59283:1627:3;59350:4;59406:21;59476:16;:14;:16::i;:::-;59471:120;;59515:65;59520:18;59540:39;59515:4;:65::i;59471:120::-;59714:16;:14;:16::i;:::-;59692:18;;:38;59688:145;;59753:69;59758:22;59782:39;59753:4;:69::i;59688:145::-;59936:12;59919:14;:12;:14::i;:::-;:29;59915:150;;;59971:83;59976:29;60007:46;59971:4;:83::i;59915:150::-;60156:13;;60141:12;:28;60137:127;;;60192:61;60197:15;60214:38;60192:4;:61::i;60137:127::-;60498:33;60503:13;;60518:12;60498:4;:33::i;:::-;60602:13;:32;;;60479:52;-1:-1:-1;60751:39:3;60765:10;60777:12;60751:13;:39::i;:::-;60806:59;60822:10;60834:12;60848:16;60806:59;;;;;;;;;25986:536;26077:4;26061:5;70787:30;70807:9;70787:19;:30::i;:::-;26093:10;26106:16;:14;:16::i;:::-;26093:29;-1:-1:-1;26136:29:3;;26132:246;;26306:61;26317:5;26311:12;;;;;;;;26325:41;26306:4;:61::i;26132:246::-;26475:40;26487:10;26499:1;26502:12;26475:11;:40::i;12490:1238::-;-1:-1:-1;;;;;12832:23:3;;12567:9;12832:23;;;:14;:23;;;;;13056:24;;12567:9;;;;;;;;13052:90;;-1:-1:-1;13109:18:3;;-1:-1:-1;13109:18:3;;-1:-1:-1;13101:30:3;;-1:-1:-1;;;13101:30:3;13052:90;13364:46;13372:14;:24;;;13398:11;;13364:7;:46::i;:::-;13331:79;;-1:-1:-1;13331:79:3;-1:-1:-1;13435:18:3;13424:7;:29;;;;;;;;;13420:79;;-1:-1:-1;13477:7:3;;-1:-1:-1;13486:1:3;;-1:-1:-1;13469:19:3;;-1:-1:-1;;13469:19:3;13420:79;13529:58;13537:19;13558:14;:28;;;13529:7;:58::i;:::-;13509:78;;-1:-1:-1;13509:78:3;-1:-1:-1;13612:18:3;13601:7;:29;;;;;;;;;13597:79;;-1:-1:-1;13654:7:3;;-1:-1:-1;13663:1:3;;-1:-1:-1;13646:19:3;;-1:-1:-1;;13646:19:3;13597:79;-1:-1:-1;13694:18:3;;-1:-1:-1;13714:6:3;-1:-1:-1;;;12490:1238:3;;;;:::o;62006:1424::-;62077:4;62133:21;62278:16;:14;:16::i;:::-;62256:18;;:38;62252:148;;62317:72;62322:22;62346:42;62317:4;:72::i;62252:148::-;62503:14;62486;:12;:14::i;:::-;:31;62482:155;;;62540:86;62545:29;62576:49;62540:4;:86::i;62482:155::-;62732:13;;62715:14;:30;62711:132;;;62768:64;62773:15;62790:41;62768:4;:64::i;62711:132::-;63079:35;63084:13;;63099:14;63079:4;:35::i;:::-;63187:13;:32;;;63060:54;-1:-1:-1;63336:49:3;327:42:4;63370:14:3;63336:13;:49::i;20320:546::-;20397:4;20403;20381:5;70787:30;70807:9;70787:19;:30::i;:::-;20419:10;20432:16;:14;:16::i;:::-;20419:29;-1:-1:-1;20462:29:3;;20458:249;;20633:59;20644:5;20638:12;;;;;;;;20652:39;20633:4;:59::i;20458:249::-;20826:33;20836:10;20848;20826:9;:33::i;3096:114:12:-;3149:4;3172:31;3177:1;3180;3172:31;;;;;;;;;;;;;-1:-1:-1;;;3172:31:12;;;:4;:31::i;1303:230:5:-;1359:9;1370:4;1395:1;1390;:6;1386:141;;-1:-1:-1;1420:18:5;;-1:-1:-1;1440:5:5;;;1412:34;;1386:141;-1:-1:-1;1485:27:5;;-1:-1:-1;1514:1:5;1477:39;;17613:2317:3;17744:4;18387:31;;:::i;:::-;18421:53;18426:35;;;;;;;;18441:18;18426:35;;;18463:10;18421:4;:53::i;:::-;18387:87;;18484:24;18511:54;18530:20;18552:12;;18511:18;:54::i;:::-;18484:81;;18575:20;18598:39;18603:19;18624:12;;18598:4;:39::i;:::-;18575:62;;18647:21;18671:101;18697:38;;;;;;;;18712:21;;18697:38;;;18737:19;18758:13;;18671:25;:101::i;:::-;18647:125;;18782:21;18806:95;18832:32;;;;;;;;18847:15;;18832:32;;;18866:19;18887:13;;18806:25;:95::i;:::-;18782:119;;18911:22;18936:97;18962:33;;;;;;;;18977:16;;18962:33;;;18997:19;19018:14;;18936:25;:97::i;:::-;18911:122;;19043:19;19065:73;19091:20;19113:11;;19126;;19065:25;:73::i;:::-;19335:18;:39;;;19384:11;:28;;;19422:12;:30;;;19462:13;:32;;;19504:13;:32;;;19546:14;:34;;;19642:79;;19043:95;;-1:-1:-1;19642:79:3;;;;19657:9;;19668:19;;19043:95;;19437:15;;19642:79;;;;;;;;;;19786:17;;19810:74;;-1:-1:-1;;;;;19786:17:3;;;;19810:74;;19865:18;;19810:74;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;19810:74:3;;;49:4:-1;25:18;;61:17;;-1:-1;;;;;182:15;-1:-1;;;179:29;160:49;;19778:107:3;;;19810:74;19778:107;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;-1:-1;19908:14:3;;-1:-1:-1;19903:20:3;;-1:-1:-1;19903:20:3;;19896:27;17613:2317;-1:-1:-1;;;;;;;;;;;;17613:2317:3:o;64535:1492::-;64607:4;64664:22;64810:16;:14;:16::i;:::-;64788:18;;:38;64784:149;;64849:73;64854:22;64878:43;64849:4;:73::i;64784:149::-;65036:14;65019;:12;:14::i;:::-;:31;65015:156;;;65073:87;65078:29;65109:50;65073:4;:87::i;65015:156::-;65268:14;;65251;:31;65247:134;;;65305:65;65310:15;65327:42;65305:4;:65::i;65247:134::-;65619:36;65624:14;;65640;65619:4;:36::i;:::-;65599:56;;65747:17;65730:14;:34;;;;65881:101;65942:11;;;;;;;;;-1:-1:-1;;;;;65942:11:3;-1:-1:-1;;;;;65911:50:3;;:52;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;65911:52:3;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;65911:52:3;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;65911:52:3;;;;;;;;;65967:14;65881:13;:101::i;49386:3019::-;49575:11;;:87;;-1:-1:-1;;;49575:87:3;;49504:4;;;;-1:-1:-1;;;;;49575:11:3;;;;:24;;:87;;49608:4;;49615:11;;49628:10;;49640:8;;49650:11;;49575:87;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;49575:87:3;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;49575:87:3;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;49575:87:3;;;;;;;;;49560:102;-1:-1:-1;49676:12:3;;49672:149;;49711:99;49722:27;49751:49;49802:7;49711:10;:99::i;49672:149::-;49891:10;-1:-1:-1;;;;;49879:22:3;:8;-1:-1:-1;;;;;49879:22:3;;49875:144;;;49924:84;49929:26;49957:50;49924:4;:84::i;49875:144::-;50029:34;;:::i;:::-;-1:-1:-1;;;;;50393:23:3;;;;;;:13;:23;;;;;;50385:45;;50418:11;50385:7;:45::i;:::-;50359:22;;;50344:86;;;50345:4;50344:86;;;;;;;;;;;;;;;;;;;-1:-1:-1;50460:18:3;;-1:-1:-1;50444:12:3;;:34;;;;;;;;;50440:174;;50501:102;50512:16;50530:52;50589:4;:12;;;50584:18;;;;;;;;50501:10;:102::i;:::-;50494:109;;;;;;50440:174;50651:62;50656:11;50669:43;;;;;;;;4260:6:4;50669:43:3;;;50651:4;:62::i;:::-;50624:24;;;:89;;;50752:43;;50757:11;;50752:4;:43::i;:::-;50723:26;;;:72;50850:28;:26;:28::i;:::-;50821:25;;;50806:72;;;50807:4;50806:72;;;;;;;;;;;;;;;;;;;-1:-1:-1;50912:18:3;;-1:-1:-1;50896:12:3;;:34;;;;;;;;;50888:53;;;;-1:-1:-1;;;50888:53:3;;;;;;;;;50979:88;50998:42;;;;;;;;51013:4;:25;;;50998:42;;;51042:4;:24;;;50979:18;:88::i;:::-;50952:24;;;:115;;;51107:13;;51102:45;;:4;:45::i;:::-;51078:21;;;:69;51184:11;;51197:24;;;;51179:43;;51184:11;51179:4;:43::i;:::-;51157:19;;;:65;-1:-1:-1;;;;;51284:25:3;;;;;;:13;:25;;;;;;51311:26;;;;51276:62;;51284:25;51276:7;:62::i;:::-;51248:24;;;51233:105;;;51234:4;51233:105;;;;;;;;;;;;;;;;;;;-1:-1:-1;51368:18:3;;-1:-1:-1;51352:12:3;;:34;;;;;;;;;51348:174;;51409:102;51420:16;51438:52;51497:4;:12;;;51492:18;;;;;;;51348:174;51734:21;;;;51718:13;:37;51779:19;;;;51765:11;:33;51834:22;;;;;-1:-1:-1;;;;;51808:23:3;;;-1:-1:-1;51808:23:3;;;:13;:23;;;;;;;:48;;;;51894:24;;;;51866:25;;;;;;;;;;:52;;;;52001:26;;;;51970:58;;51808:23;;-1:-1:-1;;;;;;;;;;;51970:58:3;;;52001:26;51970:58;;;;;;;;;;52070:4;-1:-1:-1;;;;;52043:59:3;52052:8;-1:-1:-1;;;;;52043:59:3;-1:-1:-1;;;;;;;;;;;52077:4:3;:24;;;52043:59;;;;;;;;;;;;;;;52146:24;;;;52172:21;;;;52117:77;;;;;;52139:4;;52117:77;;;;;;;;;;52383:14;52371:27;49386:3019;-1:-1:-1;;;;;;;49386:3019:3:o;32110:523::-;32191:4;32175:5;70787:30;70807:9;70787:19;:30::i;:::-;32207:10;32220:16;:14;:16::i;:::-;32207:29;-1:-1:-1;32250:29:3;;32246:246;;32420:61;32431:5;32425:12;;;;;;;;32439:41;32420:4;:61::i;32246:246::-;32589:37;32601:10;32613:12;32589:11;:37::i;25088:526::-;25169:4;25153:5;70787:30;70807:9;70787:19;:30::i;:::-;25185:10;25198:16;:14;:16::i;:::-;25185:29;-1:-1:-1;25228:29:3;;25224:246;;25398:61;25409:5;25403:12;;;;;;;25224:246;25567:40;25579:10;25591:12;25605:1;25567:11;:40::i;42593:986::-;42734:4;42740;42718:5;70787:30;70807:9;70787:19;:30::i;:::-;42756:10;42769:16;:14;:16::i;:::-;42756:29;-1:-1:-1;42799:29:3;;42795:266;;42975:71;42986:5;42980:12;;;;;;;;42994:51;42975:4;:71::i;:::-;42967:83;-1:-1:-1;43048:1:3;;-1:-1:-1;42967:83:3;;-1:-1:-1;42967:83:3;42795:266;43079:16;-1:-1:-1;;;;;43079:31:3;;:33;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;43079:33:3;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;43079:33:3;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;43079:33:3;;;;;;;;;43071:41;-1:-1:-1;43126:29:3;;43122:270;;43302:75;43313:5;43307:12;;;;;;;;43321:55;43302:4;:75::i;43122:270::-;43499:73;43520:10;43532:8;43542:11;43555:16;43499:20;:73::i;:::-;43492:80;;;;;70827:1;70838:29;70857:9;70838:18;:29::i;:::-;42593:986;;;;;;;:::o;38800:3276::-;38978:11;;:75;;-1:-1:-1;;;38978:75:3;;38895:4;;;;;;-1:-1:-1;;;;;38978:11:3;;:30;;:75;;39017:4;;39024:5;;39031:8;;39041:11;;38978:75;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;38978:75:3;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;38978:75:3;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;38978:75:3;;;;;;;;;38963:90;-1:-1:-1;39067:12:3;;39063:151;;39103:96;39114:27;39143:46;39191:7;39103:10;:96::i;:::-;39095:108;-1:-1:-1;39201:1:3;;-1:-1:-1;39095:108:3;;-1:-1:-1;39095:108:3;39063:151;39321:16;:14;:16::i;:::-;39299:18;;:38;39295:151;;39361:70;39366:22;39390:40;39361:4;:70::i;39295:151::-;39456:32;;:::i;:::-;-1:-1:-1;;;;;39599:24:3;;;;;;:14;:24;;;;;:38;;;39578:18;;;:59;39765:37;39614:8;39765:27;:37::i;:::-;39742:19;;;39727:75;;;39728:12;;;39727:75;;;;;;;;;;;;;;;;;;;-1:-1:-1;39832:18:3;;-1:-1:-1;39816:4:3;:12;;;:34;;;;;;;;;39812:190;;39874:113;39885:16;39903:63;39973:4;:12;;;39968:18;;;;;;;39874:113;39866:125;-1:-1:-1;39989:1:3;;-1:-1:-1;39866:125:3;;-1:-1:-1;;39866:125:3;39812:190;-1:-1:-1;;40081:11:3;:23;40077:153;;;40139:19;;;;40120:16;;;:38;40077:153;;;40189:16;;;:30;;;40077:153;40815:37;40828:5;40835:4;:16;;;40815:12;:37::i;:::-;40790:22;;;:62;;;41155:19;;;;41147:52;;:7;:52::i;:::-;41121:22;;;41106:93;;;41107:12;;;41106:93;;;;;;;;;;;;;;;;;;;-1:-1:-1;41233:18:3;;-1:-1:-1;41217:4:3;:12;;;:34;;;;;;;;;41209:52;;;;-1:-1:-1;;;41209:52:3;;;;;;;;;41311:45;41319:12;;41333:4;:22;;;41311:7;:45::i;:::-;41287:20;;;41272:84;;;41273:12;;;41272:84;;;;;;;;;;;;;;;;;;;-1:-1:-1;41390:18:3;;-1:-1:-1;41374:4:3;:12;;;:34;;;;;;;;;41366:52;;;;-1:-1:-1;;;41366:52:3;;;;;;;;;41535:22;;;;;-1:-1:-1;;;;;41498:24:3;;;;;;:14;:24;;;;;;;:59;;;41608:11;;41567:38;;;;:52;;;;41644:20;;;;41629:12;:35;;;41751:22;;;;41775;;41722:98;;;;;;41734:5;;41513:8;;41722:98;;;;;;;;;;42046:22;;;42029:14;;-1:-1:-1;42046:22:3;-1:-1:-1;;38800:3276:3;;;;;;;:::o;3169:118::-;3230:4;327:42:4;-1:-1:-1;;;;;3253:25:3;;:27;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;1927:263:5;1998:9;2009:4;2026:14;2042:8;2054:13;2062:1;2065;2054:7;:13::i;:::-;2025:42;;-1:-1:-1;2025:42:5;-1:-1:-1;2090:18:5;2082:4;:26;;;;;;;;;2078:73;;-1:-1:-1;2132:4:5;-1:-1:-1;2138:1:5;;-1:-1:-1;2124:16:5;;2078:73;2168:15;2176:3;2181:1;2168:7;:15::i;:::-;2161:22;;;;;;1927:263;;;;;;:::o;772:503:11:-;833:9;844:10;;:::i;:::-;867:14;883:20;907:22;915:3;410:4:12;907:7:11;:22::i;:::-;866:63;;-1:-1:-1;866:63:11;-1:-1:-1;951:18:11;943:4;:26;;;;;;;;;939:90;;-1:-1:-1;999:18:11;;;;;;;;;-1:-1:-1;999:18:11;;993:4;;-1:-1:-1;999:18:11;-1:-1:-1;985:33:11;;939:90;1040:14;1056:13;1073:31;1081:15;1098:5;1073:7;:31::i;:::-;1039:65;;-1:-1:-1;1039:65:11;-1:-1:-1;1126:18:11;1118:4;:26;;;;;;;;;1114:90;;-1:-1:-1;1174:18:11;;;;;;;;;-1:-1:-1;1174:18:11;;1168:4;;-1:-1:-1;1174:18:11;-1:-1:-1;1160:33:11;;-1:-1:-1;;1160:33:11;1114:90;1242:25;;;;;;;;;;;;-1:-1:-1;;1242:25:11;;-1:-1:-1;772:503:11;-1:-1:-1;;;;;;772:503:11:o;1097:186:1:-;1214:63;;72583:765:3;72687:12;72712;72726:23;72753:6;-1:-1:-1;;;;;72753:11:3;72765:4;72753:17;;;;;;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;;72711:59:3;;;;72786:7;72781:533;;72879:17;;:21;72875:429;;73137:10;73131:17;73197:15;73184:10;73180:2;73176:19;73169:44;73086:145;73276:12;73269:20;;-1:-1:-1;;;73269:20:3;;;;;;;;;72875:429;73331:10;72583:765;-1:-1:-1;;;;;72583:765:3:o;8836:241:10:-;8921:4;8942:43;8955:3;8950:9;;;;;;;;8966:4;8961:10;;;;;;;;8973:11;8942:43;;;;;;;;;;;;;;;;;9010:27;9003:3;:34;;;;;;;;;:67;;9066:3;9061:9;;;;;;;;9003:67;;;-1:-1:-1;9040:4:10;:18;;8996:74;-1:-1:-1;;8836:241:10:o;1613:250:5:-;1669:9;;1705:5;;;1725:6;;;1721:136;;1755:18;;-1:-1:-1;1775:1:5;-1:-1:-1;1747:30:5;;1721:136;-1:-1:-1;1816:26:5;;-1:-1:-1;1844:1:5;;-1:-1:-1;1808:38:5;;1978:346:11;2047:9;2058:10;;:::i;:::-;2081:14;2097:19;2120:27;2128:1;:10;;;2140:6;2120:7;:27::i;:::-;2080:67;;-1:-1:-1;2080:67:11;-1:-1:-1;2169:18:11;2161:4;:26;;;;;;;;;2157:90;;-1:-1:-1;2217:18:11;;;;;;;;;-1:-1:-1;2217:18:11;;2211:4;;-1:-1:-1;2217:18:11;-1:-1:-1;2203:33:11;;2157:90;2285:31;;;;;;;;;;;;-1:-1:-1;;2285:31:11;;-1:-1:-1;1978:346:11;-1:-1:-1;;;;1978:346:11:o;789:210:12:-;969:12;410:4;969:23;;;789:210::o;3713:118::-;3766:4;3789:35;3794:1;3797;3789:35;;;;;;;;;;;;;-1:-1:-1;;;3789:35:12;;;:4;:35::i;2614:149:2:-;2714:6;;:42;;-1:-1:-1;;;2714:42:2;;-1:-1:-1;;;;;2714:6:2;;;;:15;;:42;;2730:6;;2738:2;;2750:4;;2714:42;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;2714:42:2;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;2714:42:2;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;2714:42:2;;;;;;;;27391:4458:3;27498:4;27522:19;;;:42;;-1:-1:-1;27545:19:3;;27522:42;27514:61;;;;-1:-1:-1;;;27514:61:3;;;;;;;;;27586:27;;:::i;:::-;27727:28;:26;:28::i;:::-;27698:25;;;27683:72;;;27684:12;;;27683:72;;;;;;;;;;;;;;;;;;;-1:-1:-1;27785:18:3;;-1:-1:-1;27769:4:3;:12;;;:34;;;;;;;;;27765:166;;27826:94;27837:16;27855:44;27906:4;:12;;;27901:18;;;;;;;27826:94;27819:101;;;;;27765:166;27982:18;;27978:1265;;28252:17;;;:34;;;28355:42;;;;;;;;28370:25;;;;28355:42;;28337:77;;28272:14;28337:17;:77::i;:::-;28316:17;;;28301:113;;;28302:12;;;28301:113;;;;;;;;;;;;;;;;;;;-1:-1:-1;28448:18:3;;-1:-1:-1;28432:4:3;:12;;;:34;;;;;;;;;28428:183;;28493:103;28504:16;28522:53;28582:4;:12;;;28577:18;;;;;;;28428:183;27978:1265;;;28905:82;28928:14;28944:42;;;;;;;;28959:4;:25;;;28944:42;;;28905:22;:82::i;:::-;28884:17;;;28869:118;;;28870:12;;;28869:118;;;;;;;;;;;;;;;;;;;-1:-1:-1;29021:18:3;;-1:-1:-1;29005:4:3;:12;;;:34;;;;;;;;;29001:183;;29066:103;29077:16;29095:53;29155:4;:12;;;29150:18;;;;;;;29001:183;29198:17;;;:34;;;27978:1265;29309:11;;29360:17;;;;29309:69;;-1:-1:-1;;;29309:69:3;;29294:12;;-1:-1:-1;;;;;29309:11:3;;:25;;:69;;29343:4;;29350:8;;29360:17;29309:69;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;29309:69:3;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;29309:69:3;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;29309:69:3;;;;;;;;;29294:84;-1:-1:-1;29392:12:3;;29388:140;;29427:90;29438:27;29467:40;29509:7;29427:10;:90::i;:::-;29420:97;;;;;;29388:140;29635:16;:14;:16::i;:::-;29613:18;;:38;29609:140;;29674:64;29679:22;29703:34;29674:4;:64::i;29609:140::-;30037:39;30045:11;;30058:4;:17;;;30037:7;:39::i;:::-;30014:19;;;29999:77;;;30000:12;;;29999:77;;;;;;;;;;;;;;;;;;;-1:-1:-1;30106:18:3;;-1:-1:-1;30090:4:3;:12;;;:34;;;;;;;;;30086:176;;30147:104;30158:16;30176:54;30237:4;:12;;;30232:18;;;;;;;30086:176;-1:-1:-1;;;;;30320:23:3;;;;;;:13;:23;;;;;;30345:17;;;;30312:51;;30320:23;30312:7;:51::i;:::-;30287:21;;;30272:91;;;30273:12;;;30272:91;;;;;;;;;;;;;;;;;;;-1:-1:-1;30393:18:3;;-1:-1:-1;30377:4:3;:12;;;:34;;;;;;;;;30373:179;;30434:107;30445:16;30463:57;30527:4;:12;;;30522:18;;;;;;;30373:179;30647:4;:17;;;30630:14;:12;:14::i;:::-;:34;30626:153;;;30687:81;30692:29;30723:44;30687:4;:81::i;30626:153::-;31263:42;31277:8;31287:4;:17;;;31263:13;:42::i;:::-;31395:19;;;;31381:11;:33;31450:21;;;;-1:-1:-1;;;;;31424:23:3;;;;;;:13;:23;;;;;;;:47;;;;31580:17;;;;31546:52;;31573:4;;-1:-1:-1;;;;;;;;;;;31546:52:3;;;31580:17;31546:52;;;;;;;;;;31630:17;;;;31649;;;;31613:54;;;;;;31620:8;;31613:54;;;;;;;;;;31717:11;;31767:17;;;;31786;;;;31717:87;;-1:-1:-1;;;31717:87:3;;-1:-1:-1;;;;;31717:11:3;;;;:24;;:87;;31750:4;;31757:8;;31767:17;31786;31717:87;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;31717:87:3;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;31827:14:3;;-1:-1:-1;31822:20:3;;-1:-1:-1;;31822:20:3;;31815:27;27391:4458;-1:-1:-1;;;;;;27391:4458:3:o;543:331:5:-;599:9;;630:6;626:67;;-1:-1:-1;660:18:5;;-1:-1:-1;660:18:5;652:30;;626:67;712:5;;;716:1;712;:5;:1;732:5;;;;;:10;728:140;;-1:-1:-1;766:26:5;;-1:-1:-1;794:1:5;;-1:-1:-1;758:38:5;;728:140;835:18;;-1:-1:-1;855:1:5;-1:-1:-1;827:30:5;;964:209;1020:9;;1051:6;1047:75;;-1:-1:-1;1081:26:5;;-1:-1:-1;1109:1:5;1073:38;;1047:75;1140:18;1164:1;1160;:5;;;;;;1132:34;;;;964:209;;;;;:::o;21557:3188:3:-;21703:11;;:58;;-1:-1:-1;;;21703:58:3;;21627:4;;;;;;-1:-1:-1;;;;;21703:11:3;;:23;;:58;;21735:4;;21742:6;;21750:10;;21703:58;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;21703:58:3;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;21703:58:3;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;21703:58:3;;;;;;;;;21688:73;-1:-1:-1;21775:12:3;;21771:143;;21811:88;21822:27;21851:38;21891:7;21811:10;:88::i;:::-;21803:100;-1:-1:-1;21901:1:3;;-1:-1:-1;21803:100:3;;-1:-1:-1;21803:100:3;21771:143;22021:16;:14;:16::i;:::-;21999:18;;:38;21995:143;;22061:62;22066:22;22090:32;22061:4;:62::i;21995:143::-;22148:25;;:::i;:::-;22228:28;:26;:28::i;:::-;22199:25;;;22184:72;;;22185:12;;;22184:72;;;;;;;;;;;;;;;;;;;-1:-1:-1;22286:18:3;;-1:-1:-1;22270:4:3;:12;;;:34;;;;;;;;;22266:169;;22328:92;22339:16;22357:42;22406:4;:12;;;22401:18;;;;;;;22328:92;22320:104;-1:-1:-1;22422:1:3;;-1:-1:-1;22320:104:3;;-1:-1:-1;;22320:104:3;22266:169;23392:32;23405:6;23413:10;23392:12;:32::i;:::-;23368:21;;;:56;;;23690:42;;;;;;;;23705:25;;;;23690:42;;23644:89;;23368:56;23644:22;:89::i;:::-;23625:15;;;23610:123;;;23611:12;;;23610:123;;;;;;;;;;;;;;;;;;;-1:-1:-1;23767:18:3;;-1:-1:-1;23751:4:3;:12;;;:34;;;;;;;;;23743:51;;;;-1:-1:-1;;;23743:51:3;;;;;;;;;24075:34;24080:11;;24093:4;:15;;;24075:4;:34::i;:::-;24053:19;;;:56;-1:-1:-1;;;;;24149:21:3;;;;;;:13;:21;;;;;;24172:15;;;;24144:44;;24149:21;24144:4;:44::i;:::-;24120:21;;;:68;;;24278:19;;;;24264:11;:33;-1:-1:-1;;;;;24307:21:3;;;;;;:13;:21;;;;;;;:45;;;;24438:21;;;;24461:15;;;;24425:52;;;;;;24321:6;;24438:21;;24461:15;24425:52;;;;;;;;;;24516:6;-1:-1:-1;;;;;24492:48:3;24509:4;-1:-1:-1;;;;;24492:48:3;-1:-1:-1;;;;;;;;;;;24524:4:3;:15;;;24492:48;;;;;;;;;;;;;;;24590:11;;24636:21;;;;24659:15;;;;24590:85;;-1:-1:-1;;;24590:85:3;;-1:-1:-1;;;;;24590:11:3;;;;:22;;:85;;24621:4;;24628:6;;24636:21;24659:15;24590:85;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;24590:85:3;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;24699:14:3;;-1:-1:-1;24694:20:3;;-1:-1:-1;;24694:20:3;;24716:4;:21;;;24686:52;;;;;;21557:3188;;;;;:::o;3216:175:12:-;3297:4;3322:5;;;3353:12;3345:6;;;;3337:29;;;;-1:-1:-1;;;3337:29:12;;;;;;;;;4161:131;4220:10;;:::i;:::-;4249:36;;;;;;;;4264:19;4269:1;:10;;;4281:1;4264:4;:19::i;:::-;4249:36;;4242:43;4161:131;-1:-1:-1;;;4161:131:12:o;1107:171::-;1185:4;1201:18;;:::i;:::-;1222:15;1227:1;1230:6;1222:4;:15::i;:::-;1201:36;;1254:17;1263:7;1254:8;:17::i;1418:205::-;1516:4;1532:18;;:::i;:::-;1553:15;1558:1;1561:6;1553:4;:15::i;:::-;1532:36;;1585:31;1590:17;1599:7;1590:8;:17::i;:::-;1609:6;1585:4;:31::i;4298:119::-;4357:4;410;4380:19;4385:1;4388;:10;;;4380:4;:19::i;:::-;:30;;;;;;;4298:119;-1:-1:-1;;;4298:119:12:o;33046:3334:3:-;33202:11;;:64;;-1:-1:-1;;;33202:64:3;;33130:4;;;;-1:-1:-1;;;;;33202:11:3;;;;:25;;:64;;33236:4;;33243:8;;33253:12;;33202:64;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;33202:64:3;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;33202:64:3;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;33202:64:3;;;;;;;;;33187:79;-1:-1:-1;33280:12:3;;33276:140;;33315:90;33326:27;33355:40;33397:7;33315:10;:90::i;:::-;33308:97;;;;;33276:140;33523:16;:14;:16::i;:::-;33501:18;;:38;33497:140;;33562:64;33567:22;33591:34;33562:4;:64::i;33497:140::-;33722:14;33739;:12;:14::i;:::-;33722:31;;33780:12;33768:9;:24;33764:136;;;33815:74;33820:29;33851:37;33815:4;:74::i;:::-;33808:81;;;;;;33764:136;33910:27;;:::i;:::-;34218:37;34246:8;34218:27;:37::i;:::-;34195:19;;;34180:75;;;34181:4;34180:75;;;;;;;;;;;;;;;;;;;-1:-1:-1;34285:18:3;;-1:-1:-1;34269:12:3;;:34;;;;;;;;;34265:179;;34326:107;34337:16;34355:57;34419:4;:12;;;34414:18;;;;;;;34326:107;34319:114;;;;;;;34265:179;34495:42;34503:4;:19;;;34524:12;34495:7;:42::i;:::-;34469:22;;;34454:83;;;34455:4;34454:83;;;;;;;;;;;;;;;;;;;-1:-1:-1;34567:18:3;;-1:-1:-1;34551:12:3;;:34;;;;;;;;;34547:186;;34608:114;34619:16;34637:64;34708:4;:12;;;34703:18;;;;;;;34547:186;34810:11;;34856:22;;;;;34810:69;;-1:-1:-1;;;34810:69:3;;-1:-1:-1;;;;;34810:11:3;;;;:30;;:69;;34849:4;;34856:22;34810:69;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;34810:69:3;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;34810:69:3;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;34810:69:3;;;;;;;;;34800:79;-1:-1:-1;34893:12:3;;34889:140;;34928:90;34939:27;34968:40;35010:7;34928:10;:90::i;34889:140::-;35078:35;35086:12;;35100;35078:7;:35::i;:::-;35054:20;;;35039:74;;;35040:4;35039:74;;;;;;;;;;;;;;;;;;;-1:-1:-1;35143:18:3;;-1:-1:-1;35127:12:3;;:34;;;;;;;;;35123:177;;35184:105;35195:16;35213:55;35275:4;:12;;;35270:18;;;;;;;35123:177;35780:37;35794:8;35804:12;35780:13;:37::i;:::-;35934:22;;;;;;-1:-1:-1;;;;;35897:24:3;;;;;;:14;:24;;;;;:59;;;36007:11;;35966:38;;;;:52;36043:20;;;;36028:12;:35;;;36147:22;;36116:76;;;;;;35912:8;;36133:12;;36147:22;36043:20;36116:76;;;;;;;;;;36358:14;36346:27;33046:3334;-1:-1:-1;;;;;;33046:3334:3:o;44180:3460::-;44399:11;;:111;;-1:-1:-1;;;44399:111:3;;44318:4;;;;;;-1:-1:-1;;;;;44399:11:3;;:34;;:111;;44442:4;;44457:16;;44476:10;;44488:8;;44498:11;;44399:111;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;44399:111:3;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;44399:111:3;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;44399:111:3;;;;;;;;;44384:126;-1:-1:-1;44524:12:3;;44520:148;;44560:93;44571:27;44600:43;44645:7;44560:10;:93::i;:::-;44552:105;-1:-1:-1;44655:1:3;;-1:-1:-1;44552:105:3;;-1:-1:-1;44552:105:3;44520:148;44775:16;:14;:16::i;:::-;44753:18;;:38;44749:148;;44815:67;44820:22;44844:37;44815:4;:67::i;44749:148::-;45040:16;:14;:16::i;:::-;44999;-1:-1:-1;;;;;44999:35:3;;:37;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;44999:37:3;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;44999:37:3;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;44999:37:3;;;;;;;;;:57;44995:178;;45080:78;45085:22;45109:48;45080:4;:78::i;44995:178::-;45243:10;-1:-1:-1;;;;;45231:22:3;:8;-1:-1:-1;;;;;45231:22:3;;45227:143;;;45277:78;45282:26;45310:44;45277:4;:78::i;45227:143::-;45422:16;45418:145;;45462:86;45467:36;45505:42;45462:4;:86::i;45418:145::-;-1:-1:-1;;45616:11:3;:23;45612:156;;;45663:90;45668:36;45706:46;45663:4;:90::i;45612:156::-;45820:21;45843:22;45869:51;45886:10;45898:8;45908:11;45869:16;:51::i;:::-;45819:101;;-1:-1:-1;45819:101:3;-1:-1:-1;45934:40:3;;45930:161;;45998:78;46009:16;46003:23;;;;;;;;46028:47;45998:4;:78::i;:::-;45990:90;-1:-1:-1;46078:1:3;;-1:-1:-1;45990:90:3;;-1:-1:-1;;;45990:90:3;45930:161;46341:11;;:102;;-1:-1:-1;;;46341:102:3;;46298:21;;;;-1:-1:-1;;;;;46341:11:3;;;;:41;;:102;;46391:4;;46406:16;;46425:17;;46341:102;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;46341:102:3;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;46341:102:3;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;46341:102:3;;;;;;;;;46297:146;;-1:-1:-1;46297:146:3;-1:-1:-1;46461:40:3;;46453:56;;;;-1:-1:-1;;;46453:56:3;;;;;;;;;46600:36;;-1:-1:-1;;;46600:36:3;;46640:11;;-1:-1:-1;;;;;46600:26:3;;;;;:36;;46627:8;;46600:36;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;46600:36:3;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;46600:36:3;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;46600:36:3;;;;;;;;;:51;;46592:67;;;;-1:-1:-1;;;46592:67:3;;;;;;;;;46785:15;-1:-1:-1;;;;;46814:42:3;;46851:4;46814:42;46810:250;;;46885:63;46907:4;46914:10;46926:8;46936:11;46885:13;:63::i;:::-;46872:76;;46810:250;;;46992:57;;-1:-1:-1;;;46992:57:3;;-1:-1:-1;;;;;46992:22:3;;;;;:57;;47015:10;;47027:8;;47037:11;;46992:57;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;46992:57:3;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;46992:57:3;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;46992:57:3;;;;;;;;;46979:70;;46810:250;47163:34;;47155:52;;;;-1:-1:-1;;;47155:52:3;;;;;;;;;47269:96;47285:10;47297:8;47307:17;47334:16;47353:11;47269:96;;;;;;;;;;;;;;;;;;;47598:14;47585:48;-1:-1:-1;47615:17:3;;-1:-1:-1;;;;;;44180:3460:3;;;;;;;;:::o;2025:299:2:-;2201:10;;2186:68;;-1:-1:-1;;;2186:68:2;;2117:7;;-1:-1:-1;;;;;2201:10:2;;2186:39;;:68;;2226:4;;2240;;2247:6;;2186:68;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;2186:68:2;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;2186:68:2;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;2186:68:2;;;;;;;;;2178:90;;;;-1:-1:-1;;;2178:90:2;;;;;;;;;2279:15;2287:6;2279:7;:15::i;3837:155:12:-;3918:4;3950:12;3942:6;;;;3934:29;;;;-1:-1:-1;;;3934:29:12;;;;;;;;;;-1:-1:-1;;;3980:5:12;;;3837:155::o;4424:330:11:-;4512:9;4523:4;4540:13;4555:19;;:::i;:::-;4578:31;4593:6;4601:7;4578:14;:31::i;4878:120:12:-;4931:4;4954:37;4959:1;4962;4954:37;;;;;;;;;;;;;;;;;:4;:37::i;3713:605:11:-;3793:9;3804:10;;:::i;:::-;4101:14;4117;4135:25;410:4:12;4153:6:11;4135:7;:25::i;:::-;4100:60;;-1:-1:-1;4100:60:11;-1:-1:-1;4182:18:11;4174:4;:26;;;;;;;;;4170:90;;-1:-1:-1;4230:18:11;;;;;;;;;-1:-1:-1;4230:18:11;;4224:4;;-1:-1:-1;4230:18:11;-1:-1:-1;4216:33:11;;4170:90;4276:35;4283:9;4294:7;:16;;;4276:6;:35::i;5004:243:12:-;5085:4;5105:6;;;:16;;-1:-1:-1;5115:6:12;;5105:16;5101:55;;;-1:-1:-1;5144:1:12;5137:8;;5101:55;5174:5;;;5178:1;5174;:5;:1;5197:5;;;;;:10;5209:12;5189:33;;;;;-1:-1:-1;;;5189:33:12;;;;;;;;;444:2321:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;444:2321:2;;;-1:-1:-1;444:2321:2;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;444:2321:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;-1:-1:-1;444:2321:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;-1:-1:-1;444:2321:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;-1:-1:-1;444:2321:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;-1:-1:-1;444:2321:2;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;5:130:-1;72:20;;97:33;72:20;97:33;;142:134;220:13;;238:33;220:13;238:33;;436:124;500:20;;525:30;500:20;525:30;;567:128;642:13;;660:30;642:13;660:30;;716:336;;;830:3;823:4;815:6;811:17;807:27;797:2;;848:1;845;838:12;797:2;-1:-1;868:20;;908:18;897:30;;894:2;;;940:1;937;930:12;894:2;974:4;966:6;962:17;950:29;;1025:3;1017:4;1009:6;1005:17;995:8;991:32;988:41;985:2;;;1042:1;1039;1032:12;1061:442;;1173:3;1166:4;1158:6;1154:17;1150:27;1140:2;;1191:1;1188;1181:12;1140:2;1221:6;1215:13;1243:64;1258:48;1299:6;1258:48;;;1243:64;;;1234:73;;1327:6;1320:5;1313:21;1363:4;1355:6;1351:17;1396:4;1389:5;1385:16;1431:3;1422:6;1417:3;1413:16;1410:25;1407:2;;;1448:1;1445;1438:12;1407:2;1458:39;1490:6;1485:3;1480;1458:39;;;1133:370;;;;;;;;1511:178;1602:20;;1627:57;1602:20;1627:57;;2441:442;;2543:3;2536:4;2528:6;2524:17;2520:27;2510:2;;2561:1;2558;2551:12;2510:2;2598:6;2585:20;2620:65;2635:49;2677:6;2635:49;;2620:65;2611:74;;2705:6;2698:5;2691:21;2741:4;2733:6;2729:17;2774:4;2767:5;2763:16;2809:3;2800:6;2795:3;2791:16;2788:25;2785:2;;;2826:1;2823;2816:12;2785:2;2836:41;2870:6;2865:3;2860;2836:41;;2891:130;2958:20;;2983:33;2958:20;2983:33;;3028:134;3106:13;;3124:33;3106:13;3124:33;;3169:126;3234:20;;3259:31;3234:20;3259:31;;3302:130;3378:13;;3396:31;3378:13;3396:31;;3439:241;;3543:2;3531:9;3522:7;3518:23;3514:32;3511:2;;;3559:1;3556;3549:12;3511:2;3594:1;3611:53;3656:7;3636:9;3611:53;;3687:263;;3802:2;3790:9;3781:7;3777:23;3773:32;3770:2;;;3818:1;3815;3808:12;3770:2;3853:1;3870:64;3926:7;3906:9;3870:64;;4221:366;;;4342:2;4330:9;4321:7;4317:23;4313:32;4310:2;;;4358:1;4355;4348:12;4310:2;4393:1;4410:53;4455:7;4435:9;4410:53;;;4400:63;;4372:97;4500:2;4518:53;4563:7;4554:6;4543:9;4539:22;4518:53;;;4508:63;;4479:98;4304:283;;;;;;4594:491;;;;4732:2;4720:9;4711:7;4707:23;4703:32;4700:2;;;4748:1;4745;4738:12;4700:2;4783:1;4800:53;4845:7;4825:9;4800:53;;;4790:63;;4762:97;4890:2;4908:53;4953:7;4944:6;4933:9;4929:22;4908:53;;;4898:63;;4869:98;4998:2;5016:53;5061:7;5052:6;5041:9;5037:22;5016:53;;;5006:63;;4977:98;4694:391;;;;;;5092:609;;;;;5246:2;5234:9;5225:7;5221:23;5217:32;5214:2;;;5262:1;5259;5252:12;5214:2;5297:1;5314:53;5359:7;5339:9;5314:53;;;5304:63;;5276:97;5404:2;5422:50;5464:7;5455:6;5444:9;5440:22;5422:50;;;5412:60;;5383:95;5537:2;5526:9;5522:18;5509:32;5561:18;5553:6;5550:30;5547:2;;;5593:1;5590;5583:12;5547:2;5621:64;5677:7;5668:6;5657:9;5653:22;5621:64;;;5208:493;;;;-1:-1;5611:74;-1:-1;;;;5208:493;5708:626;;;;5863:2;5851:9;5842:7;5838:23;5834:32;5831:2;;;5879:1;5876;5869:12;5831:2;5914:1;5931:64;5987:7;5967:9;5931:64;;;5921:74;;5893:108;6032:2;6050:61;6103:7;6094:6;6083:9;6079:22;6050:61;;;6040:71;;6011:106;6169:2;6158:9;6154:18;6148:25;6193:18;6185:6;6182:30;6179:2;;;6225:1;6222;6215:12;6179:2;6245:73;6310:7;6301:6;6290:9;6286:22;6245:73;;6341:1317;;;;;;;;6622:3;6610:9;6601:7;6597:23;6593:33;6590:2;;;6639:1;6636;6629:12;6590:2;6674:1;6691:53;6736:7;6716:9;6691:53;;;6681:63;;6653:97;6781:2;6799:82;6873:7;6864:6;6853:9;6849:22;6799:82;;;6789:92;;6760:127;6918:2;6936:79;7007:7;6998:6;6987:9;6983:22;6936:79;;;6926:89;;6897:124;7080:2;7069:9;7065:18;7052:32;7104:18;7096:6;7093:30;7090:2;;;7136:1;7133;7126:12;7090:2;7156:63;7211:7;7202:6;7191:9;7187:22;7156:63;;;7146:73;;7031:194;7284:3;7273:9;7269:19;7256:33;7309:18;7301:6;7298:30;7295:2;;;7341:1;7338;7331:12;7295:2;7361:63;7416:7;7407:6;7396:9;7392:22;7361:63;;;7351:73;;7235:195;7461:3;7480:53;7525:7;7516:6;7505:9;7501:22;7480:53;;;7470:63;;7440:99;7570:3;7589:53;7634:7;7625:6;7614:9;7610:22;7589:53;;;7579:63;;7549:99;6584:1074;;;;;;;;;;;7665:366;;;7786:2;7774:9;7765:7;7761:23;7757:32;7754:2;;;7802:1;7799;7792:12;7754:2;7837:1;7854:53;7899:7;7879:9;7854:53;;;7844:63;;7816:97;7944:2;7962:53;8007:7;7998:6;7987:9;7983:22;7962:53;;8038:539;;;;8200:2;8188:9;8179:7;8175:23;8171:32;8168:2;;;8216:1;8213;8206:12;8168:2;8251:1;8268:53;8313:7;8293:9;8268:53;;;8258:63;;8230:97;8358:2;8376:53;8421:7;8412:6;8401:9;8397:22;8376:53;;;8366:63;;8337:98;8466:2;8484:77;8553:7;8544:6;8533:9;8529:22;8484:77;;8584:257;;8696:2;8684:9;8675:7;8671:23;8667:32;8664:2;;;8712:1;8709;8702:12;8664:2;8747:1;8764:61;8817:7;8797:9;8764:61;;8848:365;;;8971:2;8959:9;8950:7;8946:23;8942:32;8939:2;;;8987:1;8984;8977:12;8939:2;9022:31;;9073:18;9062:30;;9059:2;;;9105:1;9102;9095:12;9059:2;9133:64;9189:7;9180:6;9169:9;9165:22;9133:64;;;9123:74;;;;9001:202;8933:280;;;;;;9220:1439;;;;;;;;;9516:3;9504:9;9495:7;9491:23;9487:33;9484:2;;;9533:1;9530;9523:12;9484:2;9568:1;9585:82;9659:7;9639:9;9585:82;;;9575:92;;9547:126;9704:2;9722:79;9793:7;9784:6;9773:9;9769:22;9722:79;;;9712:89;;9683:124;9838:2;9856:53;9901:7;9892:6;9881:9;9877:22;9856:53;;;9846:63;;9817:98;9974:2;9963:9;9959:18;9946:32;9998:18;9990:6;9987:30;9984:2;;;10030:1;10027;10020:12;9984:2;10050:63;10105:7;10096:6;10085:9;10081:22;10050:63;;;10040:73;;9925:194;10178:3;10167:9;10163:19;10150:33;10203:18;10195:6;10192:30;10189:2;;;10235:1;10232;10225:12;10189:2;10255:63;10310:7;10301:6;10290:9;10286:22;10255:63;;;10245:73;;10129:195;10355:3;10374:51;10417:7;10408:6;10397:9;10393:22;10374:51;;;10364:61;;10334:97;10462:3;10481:53;10526:7;10517:6;10506:9;10502:22;10481:53;;;10471:63;;10441:99;10571:3;10590:53;10635:7;10626:6;10615:9;10611:22;10590:53;;;10580:63;;10550:99;9478:1181;;;;;;;;;;;;10666:293;;10796:2;10784:9;10775:7;10771:23;10767:32;10764:2;;;10812:1;10809;10802:12;10764:2;10847:1;10864:79;10935:7;10915:9;10864:79;;10966:618;;;;;11127:2;11115:9;11106:7;11102:23;11098:32;11095:2;;;11143:1;11140;11133:12;11095:2;11178:31;;11229:18;11218:30;;11215:2;;;11261:1;11258;11251:12;11215:2;11289:65;11346:7;11337:6;11326:9;11322:22;11289:65;;;11279:75;;;;11157:203;11419:2;11408:9;11404:18;11391:32;11443:18;11435:6;11432:30;11429:2;;;11475:1;11472;11465:12;11591:241;;11695:2;11683:9;11674:7;11670:23;11666:32;11663:2;;;11711:1;11708;11701:12;11663:2;11746:1;11763:53;11808:7;11788:9;11763:53;;11839:263;;11954:2;11942:9;11933:7;11929:23;11925:32;11922:2;;;11970:1;11967;11960:12;11922:2;12005:1;12022:64;12078:7;12058:9;12022:64;;12109:399;;;12241:2;12229:9;12220:7;12216:23;12212:32;12209:2;;;12257:1;12254;12247:12;12209:2;12292:1;12309:64;12365:7;12345:9;12309:64;;;12299:74;;12271:108;12410:2;12428:64;12484:7;12475:6;12464:9;12460:22;12428:64;;12515:259;;12628:2;12616:9;12607:7;12603:23;12599:32;12596:2;;;12644:1;12641;12634:12;12596:2;12679:1;12696:62;12750:7;12730:9;12696:62;;12781:142;12872:45;12911:5;12872:45;;;12867:3;12860:58;12854:69;;;12930:113;13013:24;13031:5;13013:24;;13050:104;13127:21;13142:5;13127:21;;13161:343;;13271:38;13303:5;13271:38;;;13321:70;13384:6;13379:3;13321:70;;;13314:77;;13396:52;13441:6;13436:3;13429:4;13422:5;13418:16;13396:52;;;13469:29;13491:6;13469:29;;;13460:39;;;;13251:253;-1:-1;;;13251:253;13511:356;;13639:38;13671:5;13639:38;;;13689:88;13770:6;13765:3;13689:88;;;13682:95;;13782:52;13827:6;13822:3;13815:4;13808:5;13804:16;13782:52;;;13846:16;;;;;13619:248;-1:-1;;13619:248;13874:184;13986:66;14046:5;13986:66;;14427:142;14518:45;14557:5;14518:45;;15277:304;;15437:66;15501:1;15496:3;15437:66;;;-1:-1;;;15516:28;;15572:2;15563:12;;15423:158;-1:-1;;15423:158;15590:302;;15750:66;15814:1;15809:3;15750:66;;;-1:-1;;;15829:26;;15883:2;15874:12;;15736:156;-1:-1;;15736:156;15901:308;;16061:66;16125:1;16120:3;16061:66;;;-1:-1;;;16140:32;;16200:2;16191:12;;16047:162;-1:-1;;16047:162;16218:305;;16378:66;16442:1;16437:3;16378:66;;;-1:-1;;;16457:29;;16514:2;16505:12;;16364:159;-1:-1;;16364:159;16532:304;;16692:66;16756:1;16751:3;16692:66;;;-1:-1;;;16771:28;;16827:2;16818:12;;16678:158;-1:-1;;16678:158;16845:302;;17005:66;17069:1;17064:3;17005:66;;;-1:-1;;;17084:26;;17138:2;17129:12;;16991:156;-1:-1;;16991:156;17156:314;;17316:67;17380:2;17375:3;17316:67;;;-1:-1;;;17396:37;;17461:2;17452:12;;17302:168;-1:-1;;17302:168;17479:305;;17639:66;17703:1;17698:3;17639:66;;;-1:-1;;;17718:29;;17775:2;17766:12;;17625:159;-1:-1;;17625:159;17793:305;;17953:66;18017:1;18012:3;17953:66;;;-1:-1;;;18032:29;;18089:2;18080:12;;17939:159;-1:-1;;17939:159;18107:302;;18267:66;18331:1;18326:3;18267:66;;;-1:-1;;;18346:26;;18400:2;18391:12;;18253:156;-1:-1;;18253:156;18418:302;;18578:66;18642:1;18637:3;18578:66;;;-1:-1;;;18657:26;;18711:2;18702:12;;18564:156;-1:-1;;18564:156;18729:302;;18889:66;18953:1;18948:3;18889:66;;;-1:-1;;;18968:26;;19022:2;19013:12;;18875:156;-1:-1;;18875:156;19040:303;;19200:66;19264:1;19259:3;19200:66;;;-1:-1;;;19279:27;;19334:2;19325:12;;19186:157;-1:-1;;19186:157;19352:310;;19512:67;19576:2;19571:3;19512:67;;;-1:-1;;;19592:33;;19653:2;19644:12;;19498:164;-1:-1;;19498:164;19671:308;;19831:66;19895:1;19890:3;19831:66;;;-1:-1;;;19910:32;;19970:2;19961:12;;19817:162;-1:-1;;19817:162;19988:305;;20148:66;20212:1;20207:3;20148:66;;;-1:-1;;;20227:29;;20284:2;20275:12;;20134:159;-1:-1;;20134:159;20302:311;;20462:67;20526:2;20521:3;20462:67;;;-1:-1;;;20542:34;;20604:2;20595:12;;20448:165;-1:-1;;20448:165;20622:304;;20782:66;20846:1;20841:3;20782:66;;;-1:-1;;;20861:28;;20917:2;20908:12;;20768:158;-1:-1;;20768:158;20935:302;;21095:66;21159:1;21154:3;21095:66;;;-1:-1;;;21174:26;;21228:2;21219:12;;21081:156;-1:-1;;21081:156;21246:305;;21406:66;21470:1;21465:3;21406:66;;;-1:-1;;;21485:29;;21542:2;21533:12;;21392:159;-1:-1;;21392:159;21560:308;;21720:66;21784:1;21779:3;21720:66;;;-1:-1;;;21799:32;;21859:2;21850:12;;21706:162;-1:-1;;21706:162;21877:302;;22037:66;22101:1;22096:3;22037:66;;;-1:-1;;;22116:26;;22170:2;22161:12;;22023:156;-1:-1;;22023:156;22188:303;;22348:66;22412:1;22407:3;22348:66;;;-1:-1;;;22427:27;;22482:2;22473:12;;22334:157;-1:-1;;22334:157;22499:113;22582:24;22600:5;22582:24;;22619:107;22698:22;22714:5;22698:22;;22733:262;;22877:93;22966:3;22957:6;22877:93;;23002:213;23120:2;23105:18;;23134:71;23109:9;23178:6;23134:71;;23222:451;23404:2;23389:18;;23418:79;23393:9;23470:6;23418:79;;;23508:72;23576:2;23565:9;23561:18;23552:6;23508:72;;;23591;23659:2;23648:9;23644:18;23635:6;23591:72;;23680:563;23890:3;23875:19;;23905:79;23879:9;23957:6;23905:79;;;23995:72;24063:2;24052:9;24048:18;24039:6;23995:72;;;24078;24146:2;24135:9;24131:18;24122:6;24078:72;;;24161;24229:2;24218:9;24214:18;24205:6;24161:72;;24250:324;24396:2;24381:18;;24410:71;24385:9;24454:6;24410:71;;;24492:72;24560:2;24549:9;24545:18;24536:6;24492:72;;24581:451;24763:2;24748:18;;24777:71;24752:9;24821:6;24777:71;;;24859:80;24935:2;24924:9;24920:18;24911:6;24859:80;;25039:563;25249:3;25234:19;;25264:71;25238:9;25308:6;25264:71;;;25346:80;25422:2;25411:9;25407:18;25398:6;25346:80;;25609:659;25839:3;25824:19;;25854:71;25828:9;25898:6;25854:71;;;25936:72;26004:2;25993:9;25989:18;25980:6;25936:72;;;26019;26087:2;26076:9;26072:18;26063:6;26019:72;;;26102;26170:2;26159:9;26155:18;26146:6;26102:72;;;26185:73;26253:3;26242:9;26238:19;26229:6;26185:73;;26275:547;26477:3;26462:19;;26492:71;26466:9;26536:6;26492:71;;;26574:72;26642:2;26631:9;26627:18;26618:6;26574:72;;;26657;26725:2;26714:9;26710:18;26701:6;26657:72;;26829:423;26997:2;26982:18;;27011:71;26986:9;27055:6;27011:71;;;27093:72;27161:2;27150:9;27146:18;27137:6;27093:72;;;27176:66;27238:2;27227:9;27223:18;27214:6;27176:66;;27259:435;27433:2;27418:18;;27447:71;27422:9;27491:6;27447:71;;;27529:72;27597:2;27586:9;27582:18;27573:6;27529:72;;27701:659;27931:3;27916:19;;27946:71;27920:9;27990:6;27946:71;;;28028:72;28096:2;28085:9;28081:18;28072:6;28028:72;;;28111;28179:2;28168:9;28164:18;28155:6;28111:72;;28367:547;28569:3;28554:19;;28584:71;28558:9;28628:6;28584:71;;;28666:72;28734:2;28723:9;28719:18;28710:6;28666:72;;28921:659;29151:3;29136:19;;29166:71;29140:9;29210:6;29166:71;;;29248:72;29316:2;29305:9;29301:18;29292:6;29248:72;;;29331;29399:2;29388:9;29384:18;29375:6;29331:72;;;29414;29482:2;29471:9;29467:18;29458:6;29414:72;;29587:324;29733:2;29718:18;;29747:71;29722:9;29791:6;29747:71;;;29829:72;29897:2;29886:9;29882:18;29873:6;29829:72;;29918:435;30092:2;30077:18;;30106:71;30081:9;30150:6;30106:71;;30360:201;30472:2;30457:18;;30486:65;30461:9;30524:6;30486:65;;30568:297;30704:2;30718:47;;;30689:18;;30779:76;30689:18;30841:6;30779:76;;30872:271;31019:2;31004:18;;31033:100;31008:9;31106:6;31033:100;;31150:440;31354:2;31339:18;;31368:100;31343:9;31441:6;31368:100;;;31479:101;31576:2;31565:9;31561:18;31552:6;31479:101;;33176:407;33367:2;33381:47;;;33352:18;;33442:131;33352:18;33442:131;;33590:407;33781:2;33795:47;;;33766:18;;33856:131;33766:18;33856:131;;34004:407;34195:2;34209:47;;;34180:18;;34270:131;34180:18;34270:131;;34418:407;34609:2;34623:47;;;34594:18;;34684:131;34594:18;34684:131;;34832:407;35023:2;35037:47;;;35008:18;;35098:131;35008:18;35098:131;;35246:407;35437:2;35451:47;;;35422:18;;35512:131;35422:18;35512:131;;35660:407;35851:2;35865:47;;;35836:18;;35926:131;35836:18;35926:131;;36074:407;36265:2;36279:47;;;36250:18;;36340:131;36250:18;36340:131;;36488:407;36679:2;36693:47;;;36664:18;;36754:131;36664:18;36754:131;;36902:407;37093:2;37107:47;;;37078:18;;37168:131;37078:18;37168:131;;37316:407;37507:2;37521:47;;;37492:18;;37582:131;37492:18;37582:131;;37730:407;37921:2;37935:47;;;37906:18;;37996:131;37906:18;37996:131;;38144:407;38335:2;38349:47;;;38320:18;;38410:131;38320:18;38410:131;;38558:407;38749:2;38763:47;;;38734:18;;38824:131;38734:18;38824:131;;38972:407;39163:2;39177:47;;;39148:18;;39238:131;39148:18;39238:131;;39386:407;39577:2;39591:47;;;39562:18;;39652:131;39562:18;39652:131;;39800:407;39991:2;40005:47;;;39976:18;;40066:131;39976:18;40066:131;;40214:407;40405:2;40419:47;;;40390:18;;40480:131;40390:18;40480:131;;40628:407;40819:2;40833:47;;;40804:18;;40894:131;40804:18;40894:131;;41042:407;41233:2;41247:47;;;41218:18;;41308:131;41218:18;41308:131;;41456:407;41647:2;41661:47;;;41632:18;;41722:131;41632:18;41722:131;;41870:407;42061:2;42075:47;;;42046:18;;42136:131;42046:18;42136:131;;42284:407;42475:2;42489:47;;;42460:18;;42550:131;42460:18;42550:131;;42698:213;42816:2;42801:18;;42830:71;42805:9;42874:6;42830:71;;42918:324;43064:2;43049:18;;43078:71;43053:9;43122:6;43078:71;;43249:451;43431:2;43416:18;;43445:71;43420:9;43489:6;43445:71;;;43527:80;43603:2;43592:9;43588:18;43579:6;43527:80;;;43618:72;43686:2;43675:9;43671:18;43662:6;43618:72;;43707:435;43881:2;43866:18;;43895:71;43870:9;43939:6;43895:71;;;43977:72;44045:2;44034:9;44030:18;44021:6;43977:72;;44149:324;44295:2;44280:18;;44309:71;44284:9;44353:6;44309:71;;44480:451;44662:2;44647:18;;44676:71;44651:9;44720:6;44676:71;;;44758:72;44826:2;44815:9;44811:18;44802:6;44758:72;;;44841:80;44917:2;44906:9;44902:18;44893:6;44841:80;;44938:435;45112:2;45097:18;;45126:71;45101:9;45170:6;45126:71;;45380:547;45582:3;45567:19;;45597:71;45571:9;45641:6;45597:71;;45934:205;46048:2;46033:18;;46062:67;46037:9;46102:6;46062:67;;46146:256;46208:2;46202:9;46234:17;;;46309:18;46294:34;;46330:22;;;46291:62;46288:2;;;46366:1;46363;46356:12;46288:2;46382;46375:22;46186:216;;-1:-1;46186:216;46409:321;;46552:18;46544:6;46541:30;46538:2;;;46584:1;46581;46574:12;46538:2;-1:-1;46715:4;46651;46628:17;;;;-1:-1;;46624:33;46705:15;;46475:255;47066:121;47153:12;;47124:63;47449:162;47551:19;;;47600:4;47591:14;;47544:67;47944:91;;48006:24;48024:5;48006:24;;48148:85;48214:13;48207:21;;48190:43;48240:115;;48326:24;48344:5;48326:24;;48613:121;-1:-1;;;;;48675:54;;48658:76;48820:81;48891:4;48880:16;;48863:38;48908:129;;48995:37;49026:5;48995:37;;50004:116;;50091:24;50109:5;50091:24;;50371:145;50452:6;50447:3;50442;50429:30;-1:-1;50508:1;50490:16;;50483:27;50422:94;50525:268;50590:1;50597:101;50611:6;50608:1;50605:13;50597:101;;;50678:11;;;50672:18;50659:11;;;50652:39;50633:2;50626:10;50597:101;;;50713:6;50710:1;50707:13;50704:2;;;-1:-1;;50778:1;50760:16;;50753:27;50574:219;50801:97;50889:2;50869:14;-1:-1;;50865:28;;50849:49;50906:117;50975:24;50993:5;50975:24;;;50968:5;50965:35;50955:2;;51014:1;51011;51004:12;51170:111;51236:21;51251:5;51236:21;;51288:165;51381:48;51423:5;51381:48;;51818:117;51887:24;51905:5;51887:24;;51942:113;52009:22;52025:5;52009:22;
Swarm Source
bzzr://bdb98c5a247a2e6739d6a8223c49daa6ba7dfaf29983cdcfcc31ea2814f3e365
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.