Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
ChickenBondManager
Compiler Version
v0.8.11+commit.d7f03943
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2022-10-04 */ // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.10; // OpenZeppelin Contracts (last updated v4.5.0) (utils/math/Math.sol) /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a >= b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a / b + (a % b == 0 ? 0 : 1); } } // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol) /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); } contract BaseMath { uint constant public DECIMAL_PRECISION = 1e18; } // taken from: https://github.com/liquity/dev/blob/8371355b2f11bee9fa599f9223f4c2f6f429351f/packages/contracts/contracts/Dependencies/LiquityMath.sol contract ChickenMath is BaseMath { /* * Multiply two decimal numbers and use normal rounding rules: * -round product up if 19'th mantissa digit >= 5 * -round product down if 19'th mantissa digit < 5 * * Used only inside the exponentiation, decPow(). */ function decMul(uint256 x, uint256 y) internal pure returns (uint256) { return (x * y + DECIMAL_PRECISION / 2) / DECIMAL_PRECISION; } /* * decPow: Exponentiation function for 18-digit decimal base, and integer exponent n. * * Uses the efficient "exponentiation by squaring" algorithm. O(log(n)) complexity. * * Called by ChickenBondManager.calcRedemptionFeePercentage, that represents time in units of minutes: * * The exponent is capped to avoid reverting due to overflow. The cap 525600000 equals * "minutes in 1000 years": 60 * 24 * 365 * 1000 * * If a period of > 1000 years is ever used as an exponent in either of the above functions, the result will be * negligibly different from just passing the cap, since: * the decayed base rate will be 0 for 1000 years or > 1000 years */ function decPow(uint256 _base, uint256 _exponent) internal pure returns (uint) { if (_exponent > 525600000) {_exponent = 525600000;} // cap to avoid overflow if (_exponent == 0) {return DECIMAL_PRECISION;} uint256 y = DECIMAL_PRECISION; uint256 x = _base; uint256 n = _exponent; // Exponentiation-by-squaring while (n > 1) { if (n % 2 != 0) { y = decMul(x, y); } x = decMul(x, x); n = n / 2; } return decMul(x, y); } } // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol) // OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol) // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); } /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external; } /** * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Enumerable is IERC721 { /** * @dev Returns the total amount of tokens stored by the contract. */ function totalSupply() external view returns (uint256); /** * @dev Returns a token ID owned by `owner` at a given `index` of its token list. * Use along with {balanceOf} to enumerate all of ``owner``'s tokens. */ function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256); /** * @dev Returns a token ID at a given `index` of all the tokens stored by the contract. * Use along with {totalSupply} to enumerate all tokens. */ function tokenByIndex(uint256 index) external view returns (uint256); } interface ILUSDToken is IERC20 { // --- Events --- event TroveManagerAddressChanged(address _troveManagerAddress); event StabilityPoolAddressChanged(address _newStabilityPoolAddress); event BorrowerOperationsAddressChanged(address _newBorrowerOperationsAddress); event LUSDTokenBalanceUpdated(address _user, uint _amount); // --- Functions --- function mint(address _account, uint256 _amount) external; function burn(address _account, uint256 _amount) external; function sendToPool(address _sender, address poolAddress, uint256 _amount) external; function returnFromPool(address poolAddress, address user, uint256 _amount ) external; function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; } interface IBLUSDToken is IERC20 { function mint(address _to, uint256 _bLUSDAmount) external; function burn(address _from, uint256 _bLUSDAmount) external; } interface ICurvePool is IERC20 { function add_liquidity(uint256[2] memory _amounts, uint256 _min_mint_amount) external returns (uint256 mint_amount); function remove_liquidity(uint256 burn_amount, uint256[2] memory _min_amounts) external; function remove_liquidity_one_coin(uint256 _burn_amount, int128 i, uint256 _min_received) external; function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy, address _receiver) external returns (uint256); function exchange_underlying(int128 i, int128 j, uint256 dx, uint256 min_dy, address _receiver) external returns (uint256); function calc_withdraw_one_coin(uint256 _burn_amount, int128 i) external view returns (uint256); function calc_token_amount(uint256[2] memory _amounts, bool _is_deposit) external view returns (uint256); function balances(uint256 arg0) external view returns (uint256); function token() external view returns (address); function totalSupply() external view returns (uint256); function get_dy(int128 i,int128 j, uint256 dx) external view returns (uint256); function get_dy_underlying(int128 i,int128 j, uint256 dx) external view returns (uint256); function get_virtual_price() external view returns (uint256); function fee() external view returns (uint256); function D() external returns (uint256); function future_A_gamma_time() external returns (uint256); } interface IYearnVault is IERC20 { function deposit(uint256 _tokenAmount) external returns (uint256); function withdraw(uint256 _tokenAmount) external returns (uint256); function lastReport() external view returns (uint256); function totalDebt() external view returns (uint256); function calcTokenToYToken(uint256 _tokenAmount) external pure returns (uint256); function token() external view returns (address); function availableDepositLimit() external view returns (uint256); function pricePerShare() external view returns (uint256); function name() external view returns (string memory); function setDepositLimit(uint256 limit) external; function withdrawalQueue(uint256) external returns (address); } interface IBAMM { function deposit(uint256 lusdAmount) external; function withdraw(uint256 lusdAmount, address to) external; function swap(uint lusdAmount, uint minEthReturn, address payable dest) external returns(uint); function getSwapEthAmount(uint lusdQty) external view returns(uint ethAmount, uint feeLusdAmount); function getLUSDValue() external view returns (uint256, uint256, uint256); function setChicken(address _chicken) external; } interface IChickenBondManager { // Valid values for `status` returned by `getBondData()` enum BondStatus { nonExistent, active, chickenedOut, chickenedIn } function lusdToken() external view returns (ILUSDToken); function bLUSDToken() external view returns (IBLUSDToken); function curvePool() external view returns (ICurvePool); function bammSPVault() external view returns (IBAMM); function yearnCurveVault() external view returns (IYearnVault); // constants function INDEX_OF_LUSD_TOKEN_IN_CURVE_POOL() external pure returns (int128); function createBond(uint256 _lusdAmount) external returns (uint256); function createBondWithPermit( address owner, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external returns (uint256); function chickenOut(uint256 _bondID, uint256 _minLUSD) external; function chickenIn(uint256 _bondID) external; function redeem(uint256 _bLUSDToRedeem, uint256 _minLUSDFromBAMMSPVault) external returns (uint256, uint256); // getters function calcRedemptionFeePercentage(uint256 _fractionOfBLUSDToRedeem) external view returns (uint256); function getBondData(uint256 _bondID) external view returns (uint256 lusdAmount, uint64 claimedBLUSD, uint64 startTime, uint64 endTime, uint8 status); function getLUSDToAcquire(uint256 _bondID) external view returns (uint256); function calcAccruedBLUSD(uint256 _bondID) external view returns (uint256); function calcBondBLUSDCap(uint256 _bondID) external view returns (uint256); function getLUSDInBAMMSPVault() external view returns (uint256); function calcTotalYearnCurveVaultShareValue() external view returns (uint256); function calcTotalLUSDValue() external view returns (uint256); function getPendingLUSD() external view returns (uint256); function getAcquiredLUSDInSP() external view returns (uint256); function getAcquiredLUSDInCurve() external view returns (uint256); function getTotalAcquiredLUSD() external view returns (uint256); function getPermanentLUSD() external view returns (uint256); function getOwnedLUSDInSP() external view returns (uint256); function getOwnedLUSDInCurve() external view returns (uint256); function calcSystemBackingRatio() external view returns (uint256); function calcUpdatedAccrualParameter() external view returns (uint256); function getBAMMLUSDDebt() external view returns (uint256); } interface IBondNFT is IERC721Enumerable { struct BondExtraData { uint80 initialHalfDna; uint80 finalHalfDna; uint32 troveSize; // Debt in LUSD uint32 lqtyAmount; // Holding LQTY, staking or deposited into Pickle uint32 curveGaugeSlopes; // For 3CRV and Frax pools combined } function mint(address _bonder, uint256 _permanentSeed) external returns (uint256, uint80); function setFinalExtraData(address _bonder, uint256 _tokenID, uint256 _permanentSeed) external returns (uint80); function chickenBondManager() external view returns (IChickenBondManager); function getBondAmount(uint256 _tokenID) external view returns (uint256 amount); function getBondStartTime(uint256 _tokenID) external view returns (uint256 startTime); function getBondEndTime(uint256 _tokenID) external view returns (uint256 endTime); function getBondInitialHalfDna(uint256 _tokenID) external view returns (uint80 initialHalfDna); function getBondInitialDna(uint256 _tokenID) external view returns (uint256 initialDna); function getBondFinalHalfDna(uint256 _tokenID) external view returns (uint80 finalHalfDna); function getBondFinalDna(uint256 _tokenID) external view returns (uint256 finalDna); function getBondStatus(uint256 _tokenID) external view returns (uint8 status); function getBondExtraData(uint256 _tokenID) external view returns (uint80 initialHalfDna, uint80 finalHalfDna, uint32 troveSize, uint32 lqtyAmount, uint32 curveGaugeSlopes); } interface IYearnRegistry { function latestVault(address _tokenAddress) external returns (address); } interface ICurveLiquidityGaugeV5 is IERC20 { // Public state getters function reward_data(address _reward_token) external returns ( address token, address distributor, uint256 period_finish, uint256 rate, uint256 last_update, uint256 integral ); // User-facing functions function deposit(uint256 _value) external; function deposit(uint256 _value, address _addr) external; function deposit(uint256 _value, address _addr, bool _claim_rewards) external; function withdraw(uint256 _value) external; function withdraw(uint256 _value, bool _claim_rewards) external; function claim_rewards() external; function claim_rewards(address _addr) external; function claim_rewards(address _addr, address _receiver) external; function user_checkpoint(address addr) external returns (bool); function set_rewards_receiver(address _receiver) external; function kick(address addr) external; // Admin functions function deposit_reward_token(address _reward_token, uint256 _amount) external; function add_reward(address _reward_token, address _distributor) external; function set_reward_distributor(address _reward_token, address _distributor) external; function set_killed(bool _is_killed) external; // View methods function claimed_reward(address _addr, address _token) external view returns (uint256); function claimable_reward(address _user, address _reward_token) external view returns (uint256); function claimable_tokens(address addr) external view returns (uint256); function integrate_checkpoint() external view returns (uint256); function future_epoch_time() external view returns (uint256); function inflation_rate() external view returns (uint256); function version() external view returns (string memory); } // import "forge-std/console.sol"; contract ChickenBondManager is ChickenMath, IChickenBondManager { // ChickenBonds contracts and addresses IBondNFT immutable public bondNFT; IBLUSDToken immutable public bLUSDToken; ILUSDToken immutable public lusdToken; // External contracts and addresses ICurvePool immutable public curvePool; // LUSD meta-pool (i.e. coin 0 is LUSD, coin 1 is LP token from a base pool) ICurvePool immutable public curveBasePool; // base pool of curvePool IBAMM immutable public bammSPVault; // B.Protocol Stability Pool vault IYearnVault immutable public yearnCurveVault; IYearnRegistry immutable public yearnRegistry; ICurveLiquidityGaugeV5 immutable public curveLiquidityGauge; address immutable public yearnGovernanceAddress; uint256 immutable public CHICKEN_IN_AMM_FEE; uint256 private pendingLUSD; // Total pending LUSD. It will always be in SP (B.Protocol) uint256 private permanentLUSD; // Total permanent LUSD uint256 private bammLUSDDebt; // Amount “owed” by B.Protocol to ChickenBonds, equals deposits - withdrawals + rewards uint256 public yTokensHeldByCBM; // Computed balance of Y-tokens of LUSD-3CRV vault owned by this contract // (to prevent certain attacks where attacker increases the balance and thus the backing ratio) // --- Data structures --- struct ExternalAdresses { address bondNFTAddress; address lusdTokenAddress; address curvePoolAddress; address curveBasePoolAddress; address bammSPVaultAddress; address yearnCurveVaultAddress; address yearnRegistryAddress; address yearnGovernanceAddress; address bLUSDTokenAddress; address curveLiquidityGaugeAddress; } struct Params { uint256 targetAverageAgeSeconds; // Average outstanding bond age above which the controller will adjust `accrualParameter` in order to speed up accrual uint256 initialAccrualParameter; // Initial value for `accrualParameter` uint256 minimumAccrualParameter; // Stop adjusting `accrualParameter` when this value is reached uint256 accrualAdjustmentRate; // `accrualParameter` is multiplied `1 - accrualAdjustmentRate` every time there's an adjustment uint256 accrualAdjustmentPeriodSeconds; // The duration of an adjustment period in seconds uint256 chickenInAMMFee; // Fraction of bonded amount that is sent to Curve Liquidity Gauge to incentivize LUSD-bLUSD liquidity uint256 curveDepositDydxThreshold; // Threshold of SP => Curve shifting uint256 curveWithdrawalDxdyThreshold; // Threshold of Curve => SP shifting uint256 bootstrapPeriodChickenIn; // Min duration of first chicken-in uint256 bootstrapPeriodRedeem; // Redemption lock period after first chicken in uint256 bootstrapPeriodShift; // Period after launch during which shifter functions are disabled uint256 shifterDelay; // Duration of shifter countdown uint256 shifterWindow; // Interval in which shifting is possible after countdown finishes uint256 minBLUSDSupply; // Minimum amount of bLUSD supply that must remain after a redemption uint256 minBondAmount; // Minimum amount of LUSD that needs to be bonded uint256 nftRandomnessDivisor; // Divisor for permanent LUSD amount in NFT pseudo-randomness computation (see comment below) uint256 redemptionFeeBeta; // Parameter by which to divide the redeemed fraction, in order to calculate the new base rate from a redemption uint256 redemptionFeeMinuteDecayFactor; // Factor by which redemption fee decays (exponentially) every minute } struct BondData { uint256 lusdAmount; uint64 claimedBLUSD; // In BLUSD units without decimals uint64 startTime; uint64 endTime; // Timestamp of chicken in/out event BondStatus status; } uint256 public firstChickenInTime; // Timestamp of the first chicken in after bLUSD supply is zero uint256 public totalWeightedStartTimes; // Sum of `lusdAmount * startTime` for all outstanding bonds (used to tell weighted average bond age) uint256 public lastRedemptionTime; // The timestamp of the latest redemption uint256 public baseRedemptionRate; // The latest base redemption rate mapping (uint256 => BondData) private idToBondData; /* migration: flag which determines whether the system is in migration mode. When migration mode has been triggered: - No funds are held in the permanent bucket. Liquidity is either pending, or acquired - Bond creation and public shifter functions are disabled - Users with an existing bond may still chicken in or out - Chicken-ins will no longer send the LUSD surplus to the permanent bucket. Instead, they refund the surplus to the bonder - bLUSD holders may still redeem - Redemption fees are zero */ bool public migration; uint256 public countChickenIn; uint256 public countChickenOut; // --- Constants --- uint256 constant MAX_UINT256 = type(uint256).max; int128 public constant INDEX_OF_LUSD_TOKEN_IN_CURVE_POOL = 0; int128 constant INDEX_OF_3CRV_TOKEN_IN_CURVE_POOL = 1; uint256 constant public SECONDS_IN_ONE_MINUTE = 60; uint256 public immutable BOOTSTRAP_PERIOD_CHICKEN_IN; // Min duration of first chicken-in uint256 public immutable BOOTSTRAP_PERIOD_REDEEM; // Redemption lock period after first chicken in uint256 public immutable BOOTSTRAP_PERIOD_SHIFT; // Period after launch during which shifter functions are disabled uint256 public immutable SHIFTER_DELAY; // Duration of shifter countdown uint256 public immutable SHIFTER_WINDOW; // Interval in which shifting is possible after countdown finishes uint256 public immutable MIN_BLUSD_SUPPLY; // Minimum amount of bLUSD supply that must remain after a redemption uint256 public immutable MIN_BOND_AMOUNT; // Minimum amount of LUSD that needs to be bonded // This is the minimum amount the permanent bucket needs to be increased by an attacker (through previous chicken in or redemption fee), // in order to manipulate the obtained NFT. If the attacker finds the desired outcome at attempt N, // the permanent increase should be N * NFT_RANDOMNESS_DIVISOR. // It also means that as long as Permanent doesn’t change in that order of magnitude, attacker can try to manipulate // only changing the event date. uint256 public immutable NFT_RANDOMNESS_DIVISOR; /* * BETA: 18 digit decimal. Parameter by which to divide the redeemed fraction, in order to calc the new base rate from a redemption. * Corresponds to (1 / ALPHA) in the Liquity white paper. */ uint256 public immutable BETA; uint256 public immutable MINUTE_DECAY_FACTOR; uint256 constant CURVE_FEE_DENOMINATOR = 1e10; // Thresholds of SP <=> Curve shifting uint256 public immutable curveDepositLUSD3CRVExchangeRateThreshold; uint256 public immutable curveWithdrawal3CRVLUSDExchangeRateThreshold; // Timestamp at which the last shifter countdown started uint256 public lastShifterCountdownStartTime; // --- Accrual control variables --- // `block.timestamp` of the block in which this contract was deployed. uint256 public immutable deploymentTimestamp; // Average outstanding bond age above which the controller will adjust `accrualParameter` in order to speed up accrual. uint256 public immutable targetAverageAgeSeconds; // Stop adjusting `accrualParameter` when this value is reached. uint256 public immutable minimumAccrualParameter; // Number between 0 and 1. `accrualParameter` is multiplied by this every time there's an adjustment. uint256 public immutable accrualAdjustmentMultiplier; // The duration of an adjustment period in seconds. The controller performs at most one adjustment per every period. uint256 public immutable accrualAdjustmentPeriodSeconds; // The number of seconds it takes to accrue 50% of the cap, represented as an 18 digit fixed-point number. uint256 public accrualParameter; // Counts the number of adjustment periods since deployment. // Updated by operations that change the average outstanding bond age (createBond, chickenIn, chickenOut). // Used by `_calcUpdatedAccrualParameter` to tell whether it's time to perform adjustments, and if so, how many times // (in case the time elapsed since the last adjustment is more than one adjustment period). uint256 public accrualAdjustmentPeriodCount; // --- Events --- event BaseRedemptionRateUpdated(uint256 _baseRedemptionRate); event LastRedemptionTimeUpdated(uint256 _lastRedemptionFeeOpTime); event BondCreated(address indexed bonder, uint256 bondId, uint256 amount, uint80 bondInitialHalfDna); event BondClaimed( address indexed bonder, uint256 bondId, uint256 lusdAmount, uint256 bLusdAmount, uint256 lusdSurplus, uint256 chickenInFeeAmount, bool migration, uint80 bondFinalHalfDna ); event BondCancelled(address indexed bonder, uint256 bondId, uint256 principalLusdAmount, uint256 minLusdAmount, uint256 withdrawnLusdAmount, uint80 bondFinalHalfDna); event BLUSDRedeemed(address indexed redeemer, uint256 bLusdAmount, uint256 minLusdAmount, uint256 lusdAmount, uint256 yTokens, uint256 redemptionFee); event MigrationTriggered(uint256 previousPermanentLUSD); event AccrualParameterUpdated(uint256 accrualParameter); // --- Constructor --- constructor ( ExternalAdresses memory _externalContractAddresses, // to avoid stack too deep issues Params memory _params ) { bondNFT = IBondNFT(_externalContractAddresses.bondNFTAddress); lusdToken = ILUSDToken(_externalContractAddresses.lusdTokenAddress); bLUSDToken = IBLUSDToken(_externalContractAddresses.bLUSDTokenAddress); curvePool = ICurvePool(_externalContractAddresses.curvePoolAddress); curveBasePool = ICurvePool(_externalContractAddresses.curveBasePoolAddress); bammSPVault = IBAMM(_externalContractAddresses.bammSPVaultAddress); yearnCurveVault = IYearnVault(_externalContractAddresses.yearnCurveVaultAddress); yearnRegistry = IYearnRegistry(_externalContractAddresses.yearnRegistryAddress); yearnGovernanceAddress = _externalContractAddresses.yearnGovernanceAddress; deploymentTimestamp = block.timestamp; targetAverageAgeSeconds = _params.targetAverageAgeSeconds; accrualParameter = _params.initialAccrualParameter; minimumAccrualParameter = _params.minimumAccrualParameter; require(minimumAccrualParameter > 0, "CBM: Min accrual parameter cannot be zero"); accrualAdjustmentMultiplier = 1e18 - _params.accrualAdjustmentRate; accrualAdjustmentPeriodSeconds = _params.accrualAdjustmentPeriodSeconds; curveLiquidityGauge = ICurveLiquidityGaugeV5(_externalContractAddresses.curveLiquidityGaugeAddress); CHICKEN_IN_AMM_FEE = _params.chickenInAMMFee; uint256 fee = curvePool.fee(); // This is practically immutable (can only be set once, in `initialize()`) // By exchange rate, we mean the rate at which Curve exchanges LUSD <=> $ value of 3CRV (at the virtual price), // which is reduced by the fee. // For convenience, we want to parameterize our thresholds in terms of the spot prices -dy/dx & -dx/dy, // which are not exposed by Curve directly. Instead, we turn our thresholds into thresholds on the exchange rate // by taking into account the fee. curveDepositLUSD3CRVExchangeRateThreshold = _params.curveDepositDydxThreshold * (CURVE_FEE_DENOMINATOR - fee) / CURVE_FEE_DENOMINATOR; curveWithdrawal3CRVLUSDExchangeRateThreshold = _params.curveWithdrawalDxdyThreshold * (CURVE_FEE_DENOMINATOR - fee) / CURVE_FEE_DENOMINATOR; BOOTSTRAP_PERIOD_CHICKEN_IN = _params.bootstrapPeriodChickenIn; BOOTSTRAP_PERIOD_REDEEM = _params.bootstrapPeriodRedeem; BOOTSTRAP_PERIOD_SHIFT = _params.bootstrapPeriodShift; SHIFTER_DELAY = _params.shifterDelay; SHIFTER_WINDOW = _params.shifterWindow; MIN_BLUSD_SUPPLY = _params.minBLUSDSupply; require(_params.minBondAmount > 0, "CBM: MIN BOND AMOUNT parameter cannot be zero"); // We can still use 1e-18 MIN_BOND_AMOUNT = _params.minBondAmount; NFT_RANDOMNESS_DIVISOR = _params.nftRandomnessDivisor; BETA = _params.redemptionFeeBeta; MINUTE_DECAY_FACTOR = _params.redemptionFeeMinuteDecayFactor; // TODO: Decide between one-time infinite LUSD approval to Yearn and Curve (lower gas cost per user tx, less secure // or limited approval at each bonder action (higher gas cost per user tx, more secure) lusdToken.approve(address(bammSPVault), MAX_UINT256); lusdToken.approve(address(curvePool), MAX_UINT256); curvePool.approve(address(yearnCurveVault), MAX_UINT256); lusdToken.approve(address(curveLiquidityGauge), MAX_UINT256); // Check that the system is hooked up to the correct latest Yearn vault assert(address(yearnCurveVault) == yearnRegistry.latestVault(address(curvePool))); } // --- User-facing functions --- function createBond(uint256 _lusdAmount) public returns (uint256) { _requireMinBond(_lusdAmount); _requireMigrationNotActive(); _updateAccrualParameter(); // Mint the bond NFT to the caller and get the bond ID (uint256 bondID, uint80 initialHalfDna) = bondNFT.mint(msg.sender, permanentLUSD / NFT_RANDOMNESS_DIVISOR); //Record the user’s bond data: bond_amount and start_time BondData memory bondData; bondData.lusdAmount = _lusdAmount; bondData.startTime = uint64(block.timestamp); bondData.status = BondStatus.active; idToBondData[bondID] = bondData; pendingLUSD += _lusdAmount; totalWeightedStartTimes += _lusdAmount * block.timestamp; lusdToken.transferFrom(msg.sender, address(this), _lusdAmount); // Deposit the LUSD to the B.Protocol LUSD vault _depositToBAMM(_lusdAmount); emit BondCreated(msg.sender, bondID, _lusdAmount, initialHalfDna); return bondID; } function createBondWithPermit( address owner, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external returns (uint256) { // LCB-10: don't call permit if the user already has the required amount permitted if (lusdToken.allowance(owner, address(this)) < amount) { lusdToken.permit(owner, address(this), amount, deadline, v, r, s); } return createBond(amount); } function chickenOut(uint256 _bondID, uint256 _minLUSD) external { BondData memory bond = idToBondData[_bondID]; _requireCallerOwnsBond(_bondID); _requireActiveStatus(bond.status); _updateAccrualParameter(); idToBondData[_bondID].status = BondStatus.chickenedOut; idToBondData[_bondID].endTime = uint64(block.timestamp); uint80 newDna = bondNFT.setFinalExtraData(msg.sender, _bondID, permanentLUSD / NFT_RANDOMNESS_DIVISOR); countChickenOut += 1; pendingLUSD -= bond.lusdAmount; totalWeightedStartTimes -= bond.lusdAmount * bond.startTime; /* In practice, there could be edge cases where the pendingLUSD is not fully backed: * - Heavy liquidations, and before yield has been converted * - Heavy loss-making liquidations, i.e. at <100% CR * - SP or B.Protocol vault hack that drains LUSD * * The user can decide how to handle chickenOuts if/when the recorded pendingLUSD is not fully backed by actual * LUSD in B.Protocol / the SP, by adjusting _minLUSD */ uint256 lusdToWithdraw = _requireEnoughLUSDInBAMM(bond.lusdAmount, _minLUSD); // Withdraw from B.Protocol LUSD vault _withdrawFromBAMM(lusdToWithdraw, msg.sender); emit BondCancelled(msg.sender, _bondID, bond.lusdAmount, _minLUSD, lusdToWithdraw, newDna); } // transfer _lusdToTransfer to the LUSD/bLUSD AMM LP Rewards staking contract function _transferToRewardsStakingContract(uint256 _lusdToTransfer) internal { uint256 lusdBalanceBefore = lusdToken.balanceOf(address(this)); curveLiquidityGauge.deposit_reward_token(address(lusdToken), _lusdToTransfer); assert(lusdBalanceBefore - lusdToken.balanceOf(address(this)) == _lusdToTransfer); } function _withdrawFromSPVaultAndTransferToRewardsStakingContract(uint256 _lusdAmount) internal { // Pull the LUSD amount from B.Protocol LUSD vault _withdrawFromBAMM(_lusdAmount, address(this)); // Deposit in rewards contract _transferToRewardsStakingContract(_lusdAmount); } /* Divert acquired yield to LUSD/bLUSD AMM LP rewards staking contract * It happens on the very first chicken in event of the system, or any time that redemptions deplete bLUSD total supply to zero * Assumption: When there have been no chicken ins since the bLUSD supply was set to 0 (either due to system deployment, or full bLUSD redemption), * all acquired LUSD must necessarily be pure yield. */ function _firstChickenIn(uint256 _bondStartTime, uint256 _bammLUSDValue, uint256 _lusdInBAMMSPVault) internal returns (uint256) { //assert(!migration); // we leave it as a comment so we can uncomment it for automated testing tools require(block.timestamp >= _bondStartTime + BOOTSTRAP_PERIOD_CHICKEN_IN, "CBM: First chicken in must wait until bootstrap period is over"); firstChickenInTime = block.timestamp; ( uint256 acquiredLUSDInSP, /* uint256 acquiredLUSDInCurve */, /* uint256 ownedLUSDInSP */, /* uint256 ownedLUSDInCurve */, /* uint256 permanentLUSDCached */ ) = _getLUSDSplit(_bammLUSDValue); // Make sure that LUSD available in B.Protocol is at least as much as acquired // If first chicken in happens after an scenario of heavy liquidations and before ETH has been sold by B.Protocol // so that there’s not enough LUSD available in B.Protocol to transfer all the acquired bucket to the staking contract, // the system would start with a backing ratio greater than 1 require(_lusdInBAMMSPVault >= acquiredLUSDInSP, "CBM: Not enough LUSD available in B.Protocol"); // From SP Vault if (acquiredLUSDInSP > 0) { _withdrawFromSPVaultAndTransferToRewardsStakingContract(acquiredLUSDInSP); } return _lusdInBAMMSPVault - acquiredLUSDInSP; } function chickenIn(uint256 _bondID) external { BondData memory bond = idToBondData[_bondID]; _requireCallerOwnsBond(_bondID); _requireActiveStatus(bond.status); uint256 updatedAccrualParameter = _updateAccrualParameter(); (uint256 bammLUSDValue, uint256 lusdInBAMMSPVault) = _updateBAMMDebt(); (uint256 chickenInFeeAmount, uint256 bondAmountMinusChickenInFee) = _getBondWithChickenInFeeApplied(bond.lusdAmount); /* Upon the first chicken-in after a) system deployment or b) redemption of the full bLUSD supply, divert * any earned yield to the bLUSD-LUSD AMM for fairness. * * This is not done in migration mode since there is no need to send rewards to the staking contract. */ if (bLUSDToken.totalSupply() == 0 && !migration) { lusdInBAMMSPVault = _firstChickenIn(bond.startTime, bammLUSDValue, lusdInBAMMSPVault); } // Get the LUSD amount to acquire from the bond in proportion to the system's current backing ratio, in order to maintain said ratio. uint256 lusdToAcquire = _calcAccruedAmount(bond.startTime, bondAmountMinusChickenInFee, updatedAccrualParameter); // Get backing ratio and accrued bLUSD uint256 backingRatio = _calcSystemBackingRatioFromBAMMValue(bammLUSDValue); uint256 accruedBLUSD = lusdToAcquire * 1e18 / backingRatio; idToBondData[_bondID].claimedBLUSD = uint64(Math.min(accruedBLUSD / 1e18, type(uint64).max)); // to units and uint64 idToBondData[_bondID].status = BondStatus.chickenedIn; idToBondData[_bondID].endTime = uint64(block.timestamp); uint80 newDna = bondNFT.setFinalExtraData(msg.sender, _bondID, permanentLUSD / NFT_RANDOMNESS_DIVISOR); countChickenIn += 1; // Subtract the bonded amount from the total pending LUSD (and implicitly increase the total acquired LUSD) pendingLUSD -= bond.lusdAmount; totalWeightedStartTimes -= bond.lusdAmount * bond.startTime; // Get the remaining surplus from the LUSD amount to acquire from the bond uint256 lusdSurplus = bondAmountMinusChickenInFee - lusdToAcquire; // Handle the surplus LUSD from the chicken-in: if (!migration) { // In normal mode, add the surplus to the permanent bucket by increasing the permament tracker. This implicitly decreases the acquired LUSD. permanentLUSD += lusdSurplus; } else { // In migration mode, withdraw surplus from B.Protocol and refund to bonder // TODO: should we allow to pass in a minimum value here too? (,lusdInBAMMSPVault,) = bammSPVault.getLUSDValue(); uint256 lusdToRefund = Math.min(lusdSurplus, lusdInBAMMSPVault); if (lusdToRefund > 0) { _withdrawFromBAMM(lusdToRefund, msg.sender); } } bLUSDToken.mint(msg.sender, accruedBLUSD); // Transfer the chicken in fee to the LUSD/bLUSD AMM LP Rewards staking contract during normal mode. if (!migration && lusdInBAMMSPVault >= chickenInFeeAmount) { _withdrawFromSPVaultAndTransferToRewardsStakingContract(chickenInFeeAmount); } emit BondClaimed(msg.sender, _bondID, bond.lusdAmount, accruedBLUSD, lusdSurplus, chickenInFeeAmount, migration, newDna); } function redeem(uint256 _bLUSDToRedeem, uint256 _minLUSDFromBAMMSPVault) external returns (uint256, uint256) { _requireNonZeroAmount(_bLUSDToRedeem); _requireRedemptionNotDepletingbLUSD(_bLUSDToRedeem); require(block.timestamp >= firstChickenInTime + BOOTSTRAP_PERIOD_REDEEM, "CBM: Redemption after first chicken in must wait until bootstrap period is over"); ( uint256 acquiredLUSDInSP, uint256 acquiredLUSDInCurve, /* uint256 ownedLUSDInSP */, uint256 ownedLUSDInCurve, uint256 permanentLUSDCached ) = _getLUSDSplitAfterUpdatingBAMMDebt(); uint256 fractionOfBLUSDToRedeem = _bLUSDToRedeem * 1e18 / bLUSDToken.totalSupply(); // Calculate redemption fee. No fee in migration mode. uint256 redemptionFeePercentage = migration ? 0 : _updateRedemptionFeePercentage(fractionOfBLUSDToRedeem); // Will collect redemption fees from both buckets (in LUSD). uint256 redemptionFeeLUSD; // TODO: Both _requireEnoughLUSDInBAMM and _updateBAMMDebt call B.Protocol getLUSDValue, so it may be optmized // Calculate the LUSD to withdraw from LUSD vault, withdraw and send to redeemer. Move the fee to the permanent bucket. uint256 lusdToWithdrawFromSP; { // Block scoping to avoid stack too deep issues uint256 acquiredLUSDInSPToRedeem = acquiredLUSDInSP * fractionOfBLUSDToRedeem / 1e18; uint256 acquiredLUSDInSPToWithdraw = acquiredLUSDInSPToRedeem * (1e18 - redemptionFeePercentage) / 1e18; redemptionFeeLUSD += acquiredLUSDInSPToRedeem - acquiredLUSDInSPToWithdraw; lusdToWithdrawFromSP = _requireEnoughLUSDInBAMM(acquiredLUSDInSPToWithdraw, _minLUSDFromBAMMSPVault); if (lusdToWithdrawFromSP > 0) { _withdrawFromBAMM(lusdToWithdrawFromSP, msg.sender); } } // Send yTokens to the redeemer according to the proportion of owned LUSD in Curve that's being redeemed uint256 yTokensFromCurveVault; if (ownedLUSDInCurve > 0) { uint256 acquiredLUSDInCurveToRedeem = acquiredLUSDInCurve * fractionOfBLUSDToRedeem / 1e18; uint256 lusdToWithdrawFromCurve = acquiredLUSDInCurveToRedeem * (1e18 - redemptionFeePercentage) / 1e18; redemptionFeeLUSD += acquiredLUSDInCurveToRedeem - lusdToWithdrawFromCurve; yTokensFromCurveVault = yTokensHeldByCBM * lusdToWithdrawFromCurve / ownedLUSDInCurve; if (yTokensFromCurveVault > 0) { _transferFromCurve(msg.sender, yTokensFromCurveVault); } } // Move the fee to permanent. This implicitly removes it from the acquired bucket permanentLUSD = permanentLUSDCached + redemptionFeeLUSD; _requireNonZeroAmount(lusdToWithdrawFromSP + yTokensFromCurveVault); // Burn the redeemed bLUSD bLUSDToken.burn(msg.sender, _bLUSDToRedeem); emit BLUSDRedeemed(msg.sender, _bLUSDToRedeem, _minLUSDFromBAMMSPVault, lusdToWithdrawFromSP, yTokensFromCurveVault, redemptionFeeLUSD); return (lusdToWithdrawFromSP, yTokensFromCurveVault); } function shiftLUSDFromSPToCurve(uint256 _maxLUSDToShift) external { _requireShiftBootstrapPeriodEnded(); _requireMigrationNotActive(); _requireNonZeroBLUSDSupply(); _requireShiftWindowIsOpen(); (uint256 bammLUSDValue, uint256 lusdInBAMMSPVault) = _updateBAMMDebt(); uint256 lusdOwnedInBAMMSPVault = bammLUSDValue - pendingLUSD; uint256 totalLUSDInCurve = getTotalLUSDInCurve(); // it can happen due to profits from shifts or rounding errors: _requirePermanentGreaterThanCurve(totalLUSDInCurve); // Make sure pending bucket is not moved to Curve, so it can be withdrawn on chicken out uint256 clampedLUSDToShift = Math.min(_maxLUSDToShift, lusdOwnedInBAMMSPVault); // Make sure there’s enough LUSD available in B.Protocol clampedLUSDToShift = Math.min(clampedLUSDToShift, lusdInBAMMSPVault); // Make sure we don’t make Curve bucket greater than Permanent one with the shift // subtraction is safe per _requirePermanentGreaterThanCurve above clampedLUSDToShift = Math.min(clampedLUSDToShift, permanentLUSD - totalLUSDInCurve); _requireNonZeroAmount(clampedLUSDToShift); // Get the 3CRV virtual price only once, and use it for both initial and final check. // Adding LUSD liquidity to the meta-pool does not change 3CRV virtual price. uint256 _3crvVirtualPrice = curveBasePool.get_virtual_price(); uint256 initialExchangeRate = _getLUSD3CRVExchangeRate(_3crvVirtualPrice); require( initialExchangeRate > curveDepositLUSD3CRVExchangeRateThreshold, "CBM: LUSD:3CRV exchange rate must be over the deposit threshold before SP->Curve shift" ); // Withdram LUSD from B.Protocol _withdrawFromBAMM(clampedLUSDToShift, address(this)); // Deposit the received LUSD to Curve in return for LUSD3CRV-f tokens uint256 lusd3CRVBalanceBefore = curvePool.balanceOf(address(this)); /* TODO: Determine if we should pass a minimum amount of LP tokens to receive here. Seems infeasible to determinine the mininum on-chain from * Curve spot price / quantities, which are manipulable. */ curvePool.add_liquidity([clampedLUSDToShift, 0], 0); uint256 lusd3CRVBalanceDelta = curvePool.balanceOf(address(this)) - lusd3CRVBalanceBefore; // Deposit the received LUSD3CRV-f to Yearn Curve vault _depositToCurve(lusd3CRVBalanceDelta); // Do price check: ensure the SP->Curve shift has decreased the LUSD:3CRV exchange rate, but not into unprofitable territory uint256 finalExchangeRate = _getLUSD3CRVExchangeRate(_3crvVirtualPrice); require( finalExchangeRate < initialExchangeRate && finalExchangeRate >= curveDepositLUSD3CRVExchangeRateThreshold, "CBM: SP->Curve shift must decrease LUSD:3CRV exchange rate to a value above the deposit threshold" ); } function shiftLUSDFromCurveToSP(uint256 _maxLUSDToShift) external { _requireShiftBootstrapPeriodEnded(); _requireMigrationNotActive(); _requireNonZeroBLUSDSupply(); _requireShiftWindowIsOpen(); // We can’t shift more than what’s in Curve uint256 ownedLUSDInCurve = getTotalLUSDInCurve(); uint256 clampedLUSDToShift = Math.min(_maxLUSDToShift, ownedLUSDInCurve); _requireNonZeroAmount(clampedLUSDToShift); // Get the 3CRV virtual price only once, and use it for both initial and final check. // Removing LUSD liquidity from the meta-pool does not change 3CRV virtual price. uint256 _3crvVirtualPrice = curveBasePool.get_virtual_price(); uint256 initialExchangeRate = _get3CRVLUSDExchangeRate(_3crvVirtualPrice); // Here we're using the 3CRV:LUSD exchange rate (with 3CRV being valued at its virtual price), // which increases as LUSD price decreases, hence the direction of the inequality. require( initialExchangeRate > curveWithdrawal3CRVLUSDExchangeRateThreshold, "CBM: 3CRV:LUSD exchange rate must be above the withdrawal threshold before Curve->SP shift" ); // Convert yTokens to LUSD3CRV-f uint256 lusd3CRVBalanceBefore = curvePool.balanceOf(address(this)); // ownedLUSDInCurve > 0 implied by _requireNonZeroAmount(clampedLUSDToShift) uint256 yTokensToBurnFromCurveVault = yTokensHeldByCBM * clampedLUSDToShift / ownedLUSDInCurve; _withdrawFromCurve(yTokensToBurnFromCurveVault); uint256 lusd3CRVBalanceDelta = curvePool.balanceOf(address(this)) - lusd3CRVBalanceBefore; // Withdraw LUSD from Curve uint256 lusdBalanceBefore = lusdToken.balanceOf(address(this)); /* TODO: Determine if we should pass a minimum amount of LUSD to receive here. Seems infeasible to determinine the mininum on-chain from * Curve spot price / quantities, which are manipulable. */ curvePool.remove_liquidity_one_coin(lusd3CRVBalanceDelta, INDEX_OF_LUSD_TOKEN_IN_CURVE_POOL, 0); uint256 lusdBalanceDelta = lusdToken.balanceOf(address(this)) - lusdBalanceBefore; // Assertion should hold in principle. In practice, there is usually minor rounding error // assert(lusdBalanceDelta == _lusdToShift); // Deposit the received LUSD to B.Protocol LUSD vault _depositToBAMM(lusdBalanceDelta); // Ensure the Curve->SP shift has decreased the 3CRV:LUSD exchange rate, but not into unprofitable territory uint256 finalExchangeRate = _get3CRVLUSDExchangeRate(_3crvVirtualPrice); require( finalExchangeRate < initialExchangeRate && finalExchangeRate >= curveWithdrawal3CRVLUSDExchangeRateThreshold, "CBM: Curve->SP shift must increase 3CRV:LUSD exchange rate to a value above the withdrawal threshold" ); } // --- B.Protocol debt functions --- // If the actual balance of B.Protocol is higher than our internal accounting, // it means that B.Protocol has had gains (through sell of ETH or LQTY). // We account for those gains // If the balance was lower (which would mean losses), we expect them to be eventually recovered function _getInternalBAMMLUSDValue() internal view returns (uint256) { (, uint256 lusdInBAMMSPVault,) = bammSPVault.getLUSDValue(); return Math.max(bammLUSDDebt, lusdInBAMMSPVault); } // TODO: Should we make this one publicly callable, so that external getters can be up to date (by previously calling this)? // Returns the value updated function _updateBAMMDebt() internal returns (uint256, uint256) { (, uint256 lusdInBAMMSPVault,) = bammSPVault.getLUSDValue(); uint256 bammLUSDDebtCached = bammLUSDDebt; // If the actual balance of B.Protocol is higher than our internal accounting, // it means that B.Protocol has had gains (through sell of ETH or LQTY). // We account for those gains // If the balance was lower (which would mean losses), we expect them to be eventually recovered if (lusdInBAMMSPVault > bammLUSDDebtCached) { bammLUSDDebt = lusdInBAMMSPVault; return (lusdInBAMMSPVault, lusdInBAMMSPVault); } return (bammLUSDDebtCached, lusdInBAMMSPVault); } function _depositToBAMM(uint256 _lusdAmount) internal { bammSPVault.deposit(_lusdAmount); bammLUSDDebt += _lusdAmount; } function _withdrawFromBAMM(uint256 _lusdAmount, address _to) internal { bammSPVault.withdraw(_lusdAmount, _to); bammLUSDDebt -= _lusdAmount; } // @dev make sure this wrappers are always used instead of calling yearnCurveVault functions directyl, // otherwise the internal accounting would fail function _depositToCurve(uint256 _lusd3CRV) internal { uint256 yTokensBalanceBefore = yearnCurveVault.balanceOf(address(this)); yearnCurveVault.deposit(_lusd3CRV); uint256 yTokensBalanceDelta = yearnCurveVault.balanceOf(address(this)) - yTokensBalanceBefore; yTokensHeldByCBM += yTokensBalanceDelta; } function _withdrawFromCurve(uint256 _yTokensToSwap) internal { yearnCurveVault.withdraw(_yTokensToSwap); yTokensHeldByCBM -= _yTokensToSwap; } function _transferFromCurve(address _to, uint256 _yTokensToTransfer) internal { yearnCurveVault.transfer(_to, _yTokensToTransfer); yTokensHeldByCBM -= _yTokensToTransfer; } // --- Migration functionality --- /* Migration function callable one-time and only by Yearn governance. * Moves all permanent LUSD in Curve to the Curve acquired bucket. */ function activateMigration() external { _requireCallerIsYearnGovernance(); _requireMigrationNotActive(); migration = true; emit MigrationTriggered(permanentLUSD); // Zero the permament LUSD tracker. This implicitly makes all permament liquidity acquired (and redeemable) permanentLUSD = 0; } // --- Shifter countdown starter --- function startShifterCountdown() public { // First check that the previous delay and shifting window have passed require(block.timestamp >= lastShifterCountdownStartTime + SHIFTER_DELAY + SHIFTER_WINDOW, "CBM: Previous shift delay and window must have passed"); // Begin the new countdown from now lastShifterCountdownStartTime = block.timestamp; } // --- Fee share --- function sendFeeShare(uint256 _lusdAmount) external { _requireCallerIsYearnGovernance(); require(!migration, "CBM: Receive fee share only in normal mode"); // Move LUSD from caller to CBM and deposit to B.Protocol LUSD Vault lusdToken.transferFrom(yearnGovernanceAddress, address(this), _lusdAmount); _depositToBAMM(_lusdAmount); } // --- Helper functions --- function _getLUSD3CRVExchangeRate(uint256 _3crvVirtualPrice) internal view returns (uint256) { // Get the amount of 3CRV that would be received by swapping 1 LUSD (after deduction of fees) // If p_{LUSD:3CRV} is the price of LUSD quoted in 3CRV, then this returns p_{LUSD:3CRV} * (1 - fee) // as long as the pool is large enough so that 1 LUSD doesn't introduce significant slippage. uint256 dy = curvePool.get_dy(INDEX_OF_LUSD_TOKEN_IN_CURVE_POOL, INDEX_OF_3CRV_TOKEN_IN_CURVE_POOL, 1e18); return dy * _3crvVirtualPrice / 1e18; } function _get3CRVLUSDExchangeRate(uint256 _3crvVirtualPrice) internal view returns (uint256) { // Get the amount of LUSD that would be received by swapping 1 3CRV (after deduction of fees) // If p_{3CRV:LUSD} is the price of 3CRV quoted in LUSD, then this returns p_{3CRV:LUSD} * (1 - fee) // as long as the pool is large enough so that 1 3CRV doesn't introduce significant slippage. uint256 dy = curvePool.get_dy(INDEX_OF_3CRV_TOKEN_IN_CURVE_POOL, INDEX_OF_LUSD_TOKEN_IN_CURVE_POOL, 1e18); return dy * 1e18 / _3crvVirtualPrice; } // Calc decayed redemption rate function calcRedemptionFeePercentage(uint256 _fractionOfBLUSDToRedeem) public view returns (uint256) { uint256 minutesPassed = _minutesPassedSinceLastRedemption(); uint256 decayFactor = decPow(MINUTE_DECAY_FACTOR, minutesPassed); uint256 decayedBaseRedemptionRate = baseRedemptionRate * decayFactor / DECIMAL_PRECISION; // Increase redemption base rate with the new redeemed amount uint256 newBaseRedemptionRate = decayedBaseRedemptionRate + _fractionOfBLUSDToRedeem / BETA; newBaseRedemptionRate = Math.min(newBaseRedemptionRate, DECIMAL_PRECISION); // cap baseRate at a maximum of 100% //assert(newBaseRedemptionRate <= DECIMAL_PRECISION); // This is already enforced in the line above return newBaseRedemptionRate; } // Update the base redemption rate and the last redemption time (only if time passed >= decay interval. This prevents base rate griefing) function _updateRedemptionFeePercentage(uint256 _fractionOfBLUSDToRedeem) internal returns (uint256) { uint256 newBaseRedemptionRate = calcRedemptionFeePercentage(_fractionOfBLUSDToRedeem); baseRedemptionRate = newBaseRedemptionRate; emit BaseRedemptionRateUpdated(newBaseRedemptionRate); uint256 timePassed = block.timestamp - lastRedemptionTime; if (timePassed >= SECONDS_IN_ONE_MINUTE) { lastRedemptionTime = block.timestamp; emit LastRedemptionTimeUpdated(block.timestamp); } return newBaseRedemptionRate; } function _minutesPassedSinceLastRedemption() internal view returns (uint256) { return (block.timestamp - lastRedemptionTime) / SECONDS_IN_ONE_MINUTE; } function _getBondWithChickenInFeeApplied(uint256 _bondLUSDAmount) internal view returns (uint256, uint256) { // Apply zero fee in migration mode if (migration) {return (0, _bondLUSDAmount);} // Otherwise, apply the constant fee rate uint256 chickenInFeeAmount = _bondLUSDAmount * CHICKEN_IN_AMM_FEE / 1e18; uint256 bondAmountMinusChickenInFee = _bondLUSDAmount - chickenInFeeAmount; return (chickenInFeeAmount, bondAmountMinusChickenInFee); } function _getBondAmountMinusChickenInFee(uint256 _bondLUSDAmount) internal view returns (uint256) { (, uint256 bondAmountMinusChickenInFee) = _getBondWithChickenInFeeApplied(_bondLUSDAmount); return bondAmountMinusChickenInFee; } /* _calcAccruedAmount: internal getter for calculating accrued token amount for a given bond. * * This function is unit-agnostic. It can be used to calculate a bonder's accrrued bLUSD, or the LUSD that that the * CB system would acquire (i.e. receive to the acquired bucket) if the bond were Chickened In now. * * For the bonder, _capAmount is their bLUSD cap. * For the CB system, _capAmount is the LUSD bond amount (less the Chicken In fee). */ function _calcAccruedAmount(uint256 _startTime, uint256 _capAmount, uint256 _accrualParameter) internal view returns (uint256) { // All bonds have a non-zero creation timestamp, so return accrued sLQTY 0 if the startTime is 0 if (_startTime == 0) {return 0;} // Scale `bondDuration` up to an 18 digit fixed-point number. // This lets us add it to `accrualParameter`, which is also an 18-digit FP. uint256 bondDuration = 1e18 * (block.timestamp - _startTime); uint256 accruedAmount = _capAmount * bondDuration / (bondDuration + _accrualParameter); //assert(accruedAmount < _capAmount); // we leave it as a comment so we can uncomment it for automated testing tools return accruedAmount; } // Gauge the average (size-weighted) outstanding bond age and adjust accrual parameter if it's higher than our target. // If there's been more than one adjustment period since the last adjustment, perform multiple adjustments retroactively. function _calcUpdatedAccrualParameter( uint256 _storedAccrualParameter, uint256 _storedAccrualAdjustmentCount ) internal view returns ( uint256 updatedAccrualParameter, uint256 updatedAccrualAdjustmentPeriodCount ) { updatedAccrualAdjustmentPeriodCount = (block.timestamp - deploymentTimestamp) / accrualAdjustmentPeriodSeconds; if ( // There hasn't been enough time since the last update to warrant another update updatedAccrualAdjustmentPeriodCount == _storedAccrualAdjustmentCount || // or `accrualParameter` is already bottomed-out _storedAccrualParameter == minimumAccrualParameter || // or there are no outstanding bonds (avoid division by zero) pendingLUSD == 0 ) { return (_storedAccrualParameter, updatedAccrualAdjustmentPeriodCount); } uint256 averageStartTime = totalWeightedStartTimes / pendingLUSD; // We want to calculate the period when the average age will have reached or exceeded the // target average age, to be used later in a check against the actual current period. // // At any given timestamp `t`, the average age can be calculated as: // averageAge(t) = t - averageStartTime // // For any period `n`, the average age is evaluated at the following timestamp: // tSample(n) = deploymentTimestamp + n * accrualAdjustmentPeriodSeconds // // Hence we're looking for the smallest integer `n` such that: // averageAge(tSample(n)) >= targetAverageAgeSeconds // // If `n` is the smallest integer for which the above inequality stands, then: // averageAge(tSample(n - 1)) < targetAverageAgeSeconds // // Combining the two inequalities: // averageAge(tSample(n - 1)) < targetAverageAgeSeconds <= averageAge(tSample(n)) // // Substituting and rearranging: // 1. deploymentTimestamp + (n - 1) * accrualAdjustmentPeriodSeconds - averageStartTime // < targetAverageAgeSeconds // <= deploymentTimestamp + n * accrualAdjustmentPeriodSeconds - averageStartTime // // 2. (n - 1) * accrualAdjustmentPeriodSeconds // < averageStartTime + targetAverageAgeSeconds - deploymentTimestamp // <= n * accrualAdjustmentPeriodSeconds // // 3. n - 1 < (averageStartTime + targetAverageAgeSeconds - deploymentTimestamp) / accrualAdjustmentPeriodSeconds <= n // // Using equivalence `n = ceil(x) <=> n - 1 < x <= n` we arrive at: // n = ceil((averageStartTime + targetAverageAgeSeconds - deploymentTimestamp) / accrualAdjustmentPeriodSeconds) // // We can calculate `ceil(a / b)` using `Math.ceilDiv(a, b)`. uint256 adjustmentPeriodCountWhenTargetIsExceeded = Math.ceilDiv( averageStartTime + targetAverageAgeSeconds - deploymentTimestamp, accrualAdjustmentPeriodSeconds ); if (updatedAccrualAdjustmentPeriodCount < adjustmentPeriodCountWhenTargetIsExceeded) { // No adjustment needed; target average age hasn't been exceeded yet return (_storedAccrualParameter, updatedAccrualAdjustmentPeriodCount); } uint256 numberOfAdjustments = updatedAccrualAdjustmentPeriodCount - Math.max( _storedAccrualAdjustmentCount, adjustmentPeriodCountWhenTargetIsExceeded - 1 ); updatedAccrualParameter = Math.max( _storedAccrualParameter * decPow(accrualAdjustmentMultiplier, numberOfAdjustments) / 1e18, minimumAccrualParameter ); } function _updateAccrualParameter() internal returns (uint256) { uint256 storedAccrualParameter = accrualParameter; uint256 storedAccrualAdjustmentPeriodCount = accrualAdjustmentPeriodCount; (uint256 updatedAccrualParameter, uint256 updatedAccrualAdjustmentPeriodCount) = _calcUpdatedAccrualParameter(storedAccrualParameter, storedAccrualAdjustmentPeriodCount); if (updatedAccrualAdjustmentPeriodCount != storedAccrualAdjustmentPeriodCount) { accrualAdjustmentPeriodCount = updatedAccrualAdjustmentPeriodCount; if (updatedAccrualParameter != storedAccrualParameter) { accrualParameter = updatedAccrualParameter; emit AccrualParameterUpdated(updatedAccrualParameter); } } return updatedAccrualParameter; } // Internal getter for calculating the bond bLUSD cap based on bonded amount and backing ratio function _calcBondBLUSDCap(uint256 _bondedAmount, uint256 _backingRatio) internal pure returns (uint256) { // TODO: potentially refactor this - i.e. have a (1 / backingRatio) function for more precision return _bondedAmount * 1e18 / _backingRatio; } // --- 'require' functions function _requireCallerOwnsBond(uint256 _bondID) internal view { require(msg.sender == bondNFT.ownerOf(_bondID), "CBM: Caller must own the bond"); } function _requireActiveStatus(BondStatus status) internal pure { require(status == BondStatus.active, "CBM: Bond must be active"); } function _requireNonZeroAmount(uint256 _amount) internal pure { require(_amount > 0, "CBM: Amount must be > 0"); } function _requireNonZeroBLUSDSupply() internal view { require(bLUSDToken.totalSupply() > 0, "CBM: bLUSD Supply must be > 0 upon shifting"); } function _requireMinBond(uint256 _lusdAmount) internal view { require(_lusdAmount >= MIN_BOND_AMOUNT, "CBM: Bond minimum amount not reached"); } function _requireRedemptionNotDepletingbLUSD(uint256 _bLUSDToRedeem) internal view { if (!migration) { //require(_bLUSDToRedeem < bLUSDTotalSupply, "CBM: Cannot redeem total supply"); require(_bLUSDToRedeem + MIN_BLUSD_SUPPLY <= bLUSDToken.totalSupply(), "CBM: Cannot redeem below min supply"); } } function _requireMigrationNotActive() internal view { require(!migration, "CBM: Migration must be not be active"); } function _requireCallerIsYearnGovernance() internal view { require(msg.sender == yearnGovernanceAddress, "CBM: Only Yearn Governance can call"); } function _requireEnoughLUSDInBAMM(uint256 _requestedLUSD, uint256 _minLUSD) internal view returns (uint256) { require(_requestedLUSD >= _minLUSD, "CBM: Min value cannot be greater than nominal amount"); (, uint256 lusdInBAMMSPVault,) = bammSPVault.getLUSDValue(); require(lusdInBAMMSPVault >= _minLUSD, "CBM: Not enough LUSD available in B.Protocol"); uint256 lusdToWithdraw = Math.min(_requestedLUSD, lusdInBAMMSPVault); return lusdToWithdraw; } function _requireShiftBootstrapPeriodEnded() internal view { require(block.timestamp - deploymentTimestamp >= BOOTSTRAP_PERIOD_SHIFT, "CBM: Shifter only callable after shift bootstrap period ends"); } function _requireShiftWindowIsOpen() internal view { uint256 shiftWindowStartTime = lastShifterCountdownStartTime + SHIFTER_DELAY; uint256 shiftWindowFinishTime = shiftWindowStartTime + SHIFTER_WINDOW; require(block.timestamp >= shiftWindowStartTime && block.timestamp < shiftWindowFinishTime, "CBM: Shift only possible inside shifting window"); } function _requirePermanentGreaterThanCurve(uint256 _totalLUSDInCurve) internal view { require(permanentLUSD >= _totalLUSDInCurve, "CBM: The amount in Curve cannot be greater than the Permanent bucket"); } // --- Getter convenience functions --- // Bond getters function getBondData(uint256 _bondID) external view returns ( uint256 lusdAmount, uint64 claimedBLUSD, uint64 startTime, uint64 endTime, uint8 status ) { BondData memory bond = idToBondData[_bondID]; return (bond.lusdAmount, bond.claimedBLUSD, bond.startTime, bond.endTime, uint8(bond.status)); } function getLUSDToAcquire(uint256 _bondID) external view returns (uint256) { BondData memory bond = idToBondData[_bondID]; (uint256 updatedAccrualParameter, ) = _calcUpdatedAccrualParameter(accrualParameter, accrualAdjustmentPeriodCount); return _calcAccruedAmount(bond.startTime, _getBondAmountMinusChickenInFee(bond.lusdAmount), updatedAccrualParameter); } function calcAccruedBLUSD(uint256 _bondID) external view returns (uint256) { BondData memory bond = idToBondData[_bondID]; if (bond.status != BondStatus.active) { return 0; } uint256 bondBLUSDCap = _calcBondBLUSDCap(_getBondAmountMinusChickenInFee(bond.lusdAmount), calcSystemBackingRatio()); (uint256 updatedAccrualParameter, ) = _calcUpdatedAccrualParameter(accrualParameter, accrualAdjustmentPeriodCount); return _calcAccruedAmount(bond.startTime, bondBLUSDCap, updatedAccrualParameter); } function calcBondBLUSDCap(uint256 _bondID) external view returns (uint256) { uint256 backingRatio = calcSystemBackingRatio(); BondData memory bond = idToBondData[_bondID]; return _calcBondBLUSDCap(_getBondAmountMinusChickenInFee(bond.lusdAmount), backingRatio); } function getLUSDInBAMMSPVault() external view returns (uint256) { (, uint256 lusdInBAMMSPVault,) = bammSPVault.getLUSDValue(); return lusdInBAMMSPVault; } // Native vault token value getters // Calculates the LUSD3CRV value of LUSD Curve Vault yTokens held by the ChickenBondManager function calcTotalYearnCurveVaultShareValue() public view returns (uint256) { return yTokensHeldByCBM * yearnCurveVault.pricePerShare() / 1e18; } // Calculates the LUSD value of this contract, including B.Protocol LUSD Vault and Curve Vault function calcTotalLUSDValue() external view returns (uint256) { uint256 totalLUSDInCurve = getTotalLUSDInCurve(); uint256 bammLUSDValue = _getInternalBAMMLUSDValue(); return bammLUSDValue + totalLUSDInCurve; } function getTotalLUSDInCurve() public view returns (uint256) { uint256 LUSD3CRVInCurve = calcTotalYearnCurveVaultShareValue(); uint256 totalLUSDInCurve; if (LUSD3CRVInCurve > 0) { uint256 LUSD3CRVVirtualPrice = curvePool.get_virtual_price(); totalLUSDInCurve = LUSD3CRVInCurve * LUSD3CRVVirtualPrice / 1e18; } return totalLUSDInCurve; } // Pending getter function getPendingLUSD() external view returns (uint256) { return pendingLUSD; } // Acquired getters function _getLUSDSplit(uint256 _bammLUSDValue) internal view returns ( uint256 acquiredLUSDInSP, uint256 acquiredLUSDInCurve, uint256 ownedLUSDInSP, uint256 ownedLUSDInCurve, uint256 permanentLUSDCached ) { // _bammLUSDValue is guaranteed to be at least pendingLUSD due to the way we track BAMM debt ownedLUSDInSP = _bammLUSDValue - pendingLUSD; ownedLUSDInCurve = getTotalLUSDInCurve(); // All LUSD in Curve is owned permanentLUSDCached = permanentLUSD; uint256 ownedLUSD = ownedLUSDInSP + ownedLUSDInCurve; if (ownedLUSD > permanentLUSDCached) { // ownedLUSD > 0 implied uint256 acquiredLUSD = ownedLUSD - permanentLUSDCached; acquiredLUSDInSP = acquiredLUSD * ownedLUSDInSP / ownedLUSD; acquiredLUSDInCurve = acquiredLUSD - acquiredLUSDInSP; } } // Helper to avoid stack too deep in redeem() (we save one local variable) function _getLUSDSplitAfterUpdatingBAMMDebt() internal returns ( uint256 acquiredLUSDInSP, uint256 acquiredLUSDInCurve, uint256 ownedLUSDInSP, uint256 ownedLUSDInCurve, uint256 permanentLUSDCached ) { (uint256 bammLUSDValue,) = _updateBAMMDebt(); return _getLUSDSplit(bammLUSDValue); } function getTotalAcquiredLUSD() public view returns (uint256) { uint256 bammLUSDValue = _getInternalBAMMLUSDValue(); (uint256 acquiredLUSDInSP, uint256 acquiredLUSDInCurve,,,) = _getLUSDSplit(bammLUSDValue); return acquiredLUSDInSP + acquiredLUSDInCurve; } function getAcquiredLUSDInSP() external view returns (uint256) { uint256 bammLUSDValue = _getInternalBAMMLUSDValue(); (uint256 acquiredLUSDInSP,,,,) = _getLUSDSplit(bammLUSDValue); return acquiredLUSDInSP; } function getAcquiredLUSDInCurve() external view returns (uint256) { uint256 bammLUSDValue = _getInternalBAMMLUSDValue(); (, uint256 acquiredLUSDInCurve,,,) = _getLUSDSplit(bammLUSDValue); return acquiredLUSDInCurve; } // Permanent getter function getPermanentLUSD() external view returns (uint256) { return permanentLUSD; } // Owned getters function getOwnedLUSDInSP() external view returns (uint256) { uint256 bammLUSDValue = _getInternalBAMMLUSDValue(); (,, uint256 ownedLUSDInSP,,) = _getLUSDSplit(bammLUSDValue); return ownedLUSDInSP; } function getOwnedLUSDInCurve() external view returns (uint256) { uint256 bammLUSDValue = _getInternalBAMMLUSDValue(); (,,, uint256 ownedLUSDInCurve,) = _getLUSDSplit(bammLUSDValue); return ownedLUSDInCurve; } // Other getters function calcSystemBackingRatio() public view returns (uint256) { uint256 bammLUSDValue = _getInternalBAMMLUSDValue(); return _calcSystemBackingRatioFromBAMMValue(bammLUSDValue); } function _calcSystemBackingRatioFromBAMMValue(uint256 _bammLUSDValue) public view returns (uint256) { uint256 totalBLUSDSupply = bLUSDToken.totalSupply(); (uint256 acquiredLUSDInSP, uint256 acquiredLUSDInCurve,,,) = _getLUSDSplit(_bammLUSDValue); /* TODO: Determine how to define the backing ratio when there is 0 bLUSD and 0 totalAcquiredLUSD, * i.e. before the first chickenIn. For now, return a backing ratio of 1. Note: Both quantities would be 0 * also when the bLUSD supply is fully redeemed. */ //if (totalBLUSDSupply == 0 && totalAcquiredLUSD == 0) {return 1e18;} //if (totalBLUSDSupply == 0) {return MAX_UINT256;} if (totalBLUSDSupply == 0) {return 1e18;} return (acquiredLUSDInSP + acquiredLUSDInCurve) * 1e18 / totalBLUSDSupply; } function calcUpdatedAccrualParameter() external view returns (uint256) { (uint256 updatedAccrualParameter, ) = _calcUpdatedAccrualParameter(accrualParameter, accrualAdjustmentPeriodCount); return updatedAccrualParameter; } function getBAMMLUSDDebt() external view returns (uint256) { return bammLUSDDebt; } function getTreasury() external view returns ( // We don't normally use leading underscores for return values, // but we do so here in order to avoid shadowing state variables uint256 _pendingLUSD, uint256 _totalAcquiredLUSD, uint256 _permanentLUSD ) { _pendingLUSD = pendingLUSD; _totalAcquiredLUSD = getTotalAcquiredLUSD(); _permanentLUSD = permanentLUSD; } function getOpenBondCount() external view returns (uint256 openBondCount) { return bondNFT.totalSupply() - countChickenIn - countChickenOut; } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"components":[{"internalType":"address","name":"bondNFTAddress","type":"address"},{"internalType":"address","name":"lusdTokenAddress","type":"address"},{"internalType":"address","name":"curvePoolAddress","type":"address"},{"internalType":"address","name":"curveBasePoolAddress","type":"address"},{"internalType":"address","name":"bammSPVaultAddress","type":"address"},{"internalType":"address","name":"yearnCurveVaultAddress","type":"address"},{"internalType":"address","name":"yearnRegistryAddress","type":"address"},{"internalType":"address","name":"yearnGovernanceAddress","type":"address"},{"internalType":"address","name":"bLUSDTokenAddress","type":"address"},{"internalType":"address","name":"curveLiquidityGaugeAddress","type":"address"}],"internalType":"struct ChickenBondManager.ExternalAdresses","name":"_externalContractAddresses","type":"tuple"},{"components":[{"internalType":"uint256","name":"targetAverageAgeSeconds","type":"uint256"},{"internalType":"uint256","name":"initialAccrualParameter","type":"uint256"},{"internalType":"uint256","name":"minimumAccrualParameter","type":"uint256"},{"internalType":"uint256","name":"accrualAdjustmentRate","type":"uint256"},{"internalType":"uint256","name":"accrualAdjustmentPeriodSeconds","type":"uint256"},{"internalType":"uint256","name":"chickenInAMMFee","type":"uint256"},{"internalType":"uint256","name":"curveDepositDydxThreshold","type":"uint256"},{"internalType":"uint256","name":"curveWithdrawalDxdyThreshold","type":"uint256"},{"internalType":"uint256","name":"bootstrapPeriodChickenIn","type":"uint256"},{"internalType":"uint256","name":"bootstrapPeriodRedeem","type":"uint256"},{"internalType":"uint256","name":"bootstrapPeriodShift","type":"uint256"},{"internalType":"uint256","name":"shifterDelay","type":"uint256"},{"internalType":"uint256","name":"shifterWindow","type":"uint256"},{"internalType":"uint256","name":"minBLUSDSupply","type":"uint256"},{"internalType":"uint256","name":"minBondAmount","type":"uint256"},{"internalType":"uint256","name":"nftRandomnessDivisor","type":"uint256"},{"internalType":"uint256","name":"redemptionFeeBeta","type":"uint256"},{"internalType":"uint256","name":"redemptionFeeMinuteDecayFactor","type":"uint256"}],"internalType":"struct ChickenBondManager.Params","name":"_params","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"accrualParameter","type":"uint256"}],"name":"AccrualParameterUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"redeemer","type":"address"},{"indexed":false,"internalType":"uint256","name":"bLusdAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"minLusdAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lusdAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"yTokens","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"redemptionFee","type":"uint256"}],"name":"BLUSDRedeemed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_baseRedemptionRate","type":"uint256"}],"name":"BaseRedemptionRateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"bonder","type":"address"},{"indexed":false,"internalType":"uint256","name":"bondId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"principalLusdAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"minLusdAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"withdrawnLusdAmount","type":"uint256"},{"indexed":false,"internalType":"uint80","name":"bondFinalHalfDna","type":"uint80"}],"name":"BondCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"bonder","type":"address"},{"indexed":false,"internalType":"uint256","name":"bondId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lusdAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"bLusdAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lusdSurplus","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"chickenInFeeAmount","type":"uint256"},{"indexed":false,"internalType":"bool","name":"migration","type":"bool"},{"indexed":false,"internalType":"uint80","name":"bondFinalHalfDna","type":"uint80"}],"name":"BondClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"bonder","type":"address"},{"indexed":false,"internalType":"uint256","name":"bondId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint80","name":"bondInitialHalfDna","type":"uint80"}],"name":"BondCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_lastRedemptionFeeOpTime","type":"uint256"}],"name":"LastRedemptionTimeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"previousPermanentLUSD","type":"uint256"}],"name":"MigrationTriggered","type":"event"},{"inputs":[],"name":"BETA","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BOOTSTRAP_PERIOD_CHICKEN_IN","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BOOTSTRAP_PERIOD_REDEEM","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BOOTSTRAP_PERIOD_SHIFT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CHICKEN_IN_AMM_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DECIMAL_PRECISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"INDEX_OF_LUSD_TOKEN_IN_CURVE_POOL","outputs":[{"internalType":"int128","name":"","type":"int128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINUTE_DECAY_FACTOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_BLUSD_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_BOND_AMOUNT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"NFT_RANDOMNESS_DIVISOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SECONDS_IN_ONE_MINUTE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SHIFTER_DELAY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SHIFTER_WINDOW","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_bammLUSDValue","type":"uint256"}],"name":"_calcSystemBackingRatioFromBAMMValue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"accrualAdjustmentMultiplier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"accrualAdjustmentPeriodCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"accrualAdjustmentPeriodSeconds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"accrualParameter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"activateMigration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"bLUSDToken","outputs":[{"internalType":"contract IBLUSDToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bammSPVault","outputs":[{"internalType":"contract IBAMM","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseRedemptionRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bondNFT","outputs":[{"internalType":"contract IBondNFT","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_bondID","type":"uint256"}],"name":"calcAccruedBLUSD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_bondID","type":"uint256"}],"name":"calcBondBLUSDCap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fractionOfBLUSDToRedeem","type":"uint256"}],"name":"calcRedemptionFeePercentage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"calcSystemBackingRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"calcTotalLUSDValue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"calcTotalYearnCurveVaultShareValue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"calcUpdatedAccrualParameter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_bondID","type":"uint256"}],"name":"chickenIn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_bondID","type":"uint256"},{"internalType":"uint256","name":"_minLUSD","type":"uint256"}],"name":"chickenOut","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"countChickenIn","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"countChickenOut","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_lusdAmount","type":"uint256"}],"name":"createBond","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"createBondWithPermit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"curveBasePool","outputs":[{"internalType":"contract ICurvePool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"curveDepositLUSD3CRVExchangeRateThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"curveLiquidityGauge","outputs":[{"internalType":"contract ICurveLiquidityGaugeV5","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"curvePool","outputs":[{"internalType":"contract ICurvePool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"curveWithdrawal3CRVLUSDExchangeRateThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"deploymentTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"firstChickenInTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAcquiredLUSDInCurve","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAcquiredLUSDInSP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBAMMLUSDDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_bondID","type":"uint256"}],"name":"getBondData","outputs":[{"internalType":"uint256","name":"lusdAmount","type":"uint256"},{"internalType":"uint64","name":"claimedBLUSD","type":"uint64"},{"internalType":"uint64","name":"startTime","type":"uint64"},{"internalType":"uint64","name":"endTime","type":"uint64"},{"internalType":"uint8","name":"status","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLUSDInBAMMSPVault","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_bondID","type":"uint256"}],"name":"getLUSDToAcquire","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOpenBondCount","outputs":[{"internalType":"uint256","name":"openBondCount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOwnedLUSDInCurve","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOwnedLUSDInSP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPendingLUSD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPermanentLUSD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalAcquiredLUSD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalLUSDInCurve","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTreasury","outputs":[{"internalType":"uint256","name":"_pendingLUSD","type":"uint256"},{"internalType":"uint256","name":"_totalAcquiredLUSD","type":"uint256"},{"internalType":"uint256","name":"_permanentLUSD","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastRedemptionTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastShifterCountdownStartTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lusdToken","outputs":[{"internalType":"contract ILUSDToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"migration","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minimumAccrualParameter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_bLUSDToRedeem","type":"uint256"},{"internalType":"uint256","name":"_minLUSDFromBAMMSPVault","type":"uint256"}],"name":"redeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_lusdAmount","type":"uint256"}],"name":"sendFeeShare","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxLUSDToShift","type":"uint256"}],"name":"shiftLUSDFromCurveToSP","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxLUSDToShift","type":"uint256"}],"name":"shiftLUSDFromSPToCurve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"startShifterCountdown","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"targetAverageAgeSeconds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalWeightedStartTimes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"yTokensHeldByCBM","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"yearnCurveVault","outputs":[{"internalType":"contract IYearnVault","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"yearnGovernanceAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"yearnRegistry","outputs":[{"internalType":"contract IYearnRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
6104006040523480156200001257600080fd5b50604051620058bb380380620058bb83398101604081905262000035916200070c565b81516001600160a01b039081166080908152602080850151831660c090815261010080870151851660a0908152604080890151871660e090815260608a0151881690935294880151861661012052870151851661014052908601518416610160528501519092166101a052426103605282516103805290820151600d558101516103a08190526200011f5760405162461bcd60e51b815260206004820152602960248201527f43424d3a204d696e206163637275616c20706172616d657465722063616e6e6f60448201526874206265207a65726f60b81b60648201526084015b60405180910390fd5b60608101516200013890670de0b6b3a76400006200082c565b6103c05260808101516103e0526101208201516001600160a01b039081166101805260a08201516101c05260e0516040805163ddca3f4360e01b81529051600093929092169163ddca3f43916004808201926020929091908290030181865afa158015620001aa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001d0919062000846565b90506402540be400620001e482826200082c565b8360c00151620001f5919062000860565b62000201919062000882565b610320526402540be4006200021782826200082c565b8360e0015162000228919062000860565b62000234919062000882565b610340526101008201516101e052610120820151610200526101408201516102205261016082015161024052610180820151610260526101a0820151610280526101c0820151620002de5760405162461bcd60e51b815260206004820152602d60248201527f43424d3a204d494e20424f4e4420414d4f554e5420706172616d65746572206360448201526c616e6e6f74206265207a65726f60981b606482015260840162000116565b6101c08201516102a0526101e08201516102c0526102008201516102e0526102208201516103005260c0516101205160405163095ea7b360e01b81526001600160a01b039182166004820152600019602482015291169063095ea7b3906044016020604051808303816000875af11580156200035e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620003849190620008a5565b5060c05160e05160405163095ea7b360e01b81526001600160a01b039182166004820152600019602482015291169063095ea7b3906044016020604051808303816000875af1158015620003dc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004029190620008a5565b5060e0516101405160405163095ea7b360e01b81526001600160a01b039182166004820152600019602482015291169063095ea7b3906044016020604051808303816000875af11580156200045b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004819190620008a5565b5060c0516101805160405163095ea7b360e01b81526001600160a01b039182166004820152600019602482015291169063095ea7b3906044016020604051808303816000875af1158015620004da573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005009190620008a5565b506101605160e051604051630e177dc760e41b81526001600160a01b03918216600482015291169063e177dc70906024016020604051808303816000875af115801562000551573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005779190620008d0565b6001600160a01b0316610140516001600160a01b0316146200059d576200059d620008ee565b50505062000904565b60405161024081016001600160401b0381118282101715620005d857634e487b7160e01b600052604160045260246000fd5b60405290565b60405161014081016001600160401b0381118282101715620005d857634e487b7160e01b600052604160045260246000fd5b80516001600160a01b03811681146200062857600080fd5b919050565b600061024082840312156200064157600080fd5b6200064b620005a6565b825181526020808401519082015260408084015190820152606080840151908201526080808401519082015260a0808401519082015260c0808401519082015260e08084015190820152610100808401519082015261012080840151908201526101408084015190820152610160808401519082015261018080840151908201526101a080840151908201526101c080840151908201526101e080840151908201526102008084015190820152610220928301519281019290925250919050565b6000808284036103808112156200072257600080fd5b610140808212156200073357600080fd5b6200073d620005de565b91506200074a8562000610565b82526200075a6020860162000610565b60208301526200076d6040860162000610565b6040830152620007806060860162000610565b6060830152620007936080860162000610565b6080830152620007a660a0860162000610565b60a0830152620007b960c0860162000610565b60c0830152620007cc60e0860162000610565b60e0830152610100620007e181870162000610565b90830152610120620007f586820162000610565b81840152508193506200080b868287016200062d565b925050509250929050565b634e487b7160e01b600052601160045260246000fd5b60008282101562000841576200084162000816565b500390565b6000602082840312156200085957600080fd5b5051919050565b60008160001904831182151516156200087d576200087d62000816565b500290565b600082620008a057634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215620008b857600080fd5b81518015158114620008c957600080fd5b9392505050565b600060208284031215620008e357600080fd5b620008c98262000610565b634e487b7160e01b600052600160045260246000fd5b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516101e05161020051610220516102405161026051610280516102a0516102c0516102e05161030051610320516103405161036051610380516103a0516103c0516103e051614c6162000c5a600039600081816104480152818161330f0152613418015260008181610b2e0152613483015260008181610a250152818161336f01526134be01526000818161052c01526133e70152600081816109d001528181613333015281816133c30152613bb7015260008181610953015281816127a40152612b7b0152600081816108f201528181611c5f0152611f13015260008181610a670152610ba90152600081816104820152610bfc015260008181610712015281816110a5015281816114fe0152612d8e0152600081816108710152613a220152600081816106c401526142080152600081816107d6015281816124780152613d6e015260008181610794015281816124990152613d390152600081816105940152613b930152600081816106eb0152611ffc015260008181610675015261384501526000818161060501526137f501526000818161075d015281816125f901526145790152600081816104a90152614888015260006109a9015260008181610a97015281816123df01528181613fc00152818161404c015281816140e4015281816144ee01526146c001526000818161055c015281816111dd015281816118b801528181613152015281816137260152818161399701528181613b1301526143d30152600081816108c301528181611bce01526127130152600081816105050152818161180a01528181611d3f01528181611de001528181611e7a015281816128750152818161293201528181612a5c01528181613f28015261462a015260008181610982015281816116f80152818161196a01528181611a250152818161262e015281816129ca01528181612ae2015281816147cc0152818161485601526148fc0152600081816105d601528181610eda0152818161129e015281816120de015281816122fb01528181612f2a01528181613c54015261418301526000818161092c0152818161106c015281816114ce01528181611aa001528181612d5d015261357e0152614c616000f3fe608060405234801561001057600080fd5b506004361061043e5760003560e01c80637cbc237311610236578063b83f91a21161013b578063cc0c986e116100c3578063e9dc9e6d11610087578063e9dc9e6d14610b18578063edb134f314610b20578063f1b0cff514610b29578063f3c4023d14610b50578063f58369b914610b5857600080fd5b8063cc0c986e14610a89578063cfc31f6f14610a92578063d2e892dd14610ab9578063da10594314610ac2578063e324634914610b0f57600080fd5b8063c3c297451161010a578063c3c2974514610a0d578063c484cc5f14610a20578063c6c50ce814610a47578063c6d2d26114610a4f578063c7b5548114610a6257600080fd5b8063b83f91a21461097d578063bb870317146109a4578063bfc12c05146109cb578063c0639bbd146109f257600080fd5b8063a21ec280116101be578063acf955c71161018d578063acf955c7146108ed578063aefcc4fd14610914578063b0f3af4714610927578063b23ad3ee1461094e578063b7a65dce1461097557600080fd5b8063a21ec280146108a2578063a79e5683146108b5578063a891c684146108be578063ac8af3a9146108e557600080fd5b806390d532901161020557806390d532901461085357806391dc186f1461085c5780639c283187146108645780639fbc4a5f1461086c578063a20baee61461089357600080fd5b80637cbc23731461081357806384c2dea51461083b5780638ac6e2f4146108435780638caffae11461084b57600080fd5b80634237e191116103475780636350e4b2116102cf578063695e89da11610293578063695e89da146107b65780636a57b253146107be5780636b4fbbed146107d15780636bdac50b146107f85780637b3c7df61461080057600080fd5b80636350e4b2146107455780636381211414610758578063653a81981461077f57806366462ab11461078757806367e48a7e1461078f57600080fd5b80635041382b116103165780635041382b146106bf57806351a643ae146106e6578063570dd5241461070d57806359372e2e1461073457806361ec893d1461073d57600080fd5b80634237e1911461065d5780634903970a146106705780634b10543b146106975780634bb41097146106ac57600080fd5b806335f1d0e0116103ca5780633792dcb9116103995780633792dcb9146105d157806339f01388146105f85780633a517326146106005780633b19e84a146106275780633cbe79261461064a57600080fd5b806335f1d0e014610587578063361628831461058f57806336e2819e146105b657806337303e58146105c957600080fd5b8063218751b211610411578063218751b214610500578063233b0ee71461052757806327fafcd31461054e57806333624a861461055757806335567cda1461057e57600080fd5b80630277407314610443578063071a75411461047d5780630f34d74d146104a45780631705a3bd146104e3575b600080fd5b61046a7f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b61046a7f000000000000000000000000000000000000000000000000000000000000000081565b6104cb7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610474565b6009546104f09060ff1681565b6040519015158152602001610474565b6104cb7f000000000000000000000000000000000000000000000000000000000000000081565b61046a7f000000000000000000000000000000000000000000000000000000000000000081565b61046a600a5481565b6104cb7f000000000000000000000000000000000000000000000000000000000000000081565b61046a60035481565b61046a610b61565b61046a7f000000000000000000000000000000000000000000000000000000000000000081565b61046a6105c4366004614987565b610b95565b61046a610c49565b6104cb7f000000000000000000000000000000000000000000000000000000000000000081565b60015461046a565b61046a7f000000000000000000000000000000000000000000000000000000000000000081565b61062f610c6d565b60408051938452602084019290925290820152606001610474565b61046a610658366004614987565b610c87565b61046a61066b366004614987565b610d55565b61046a7f000000000000000000000000000000000000000000000000000000000000000081565b6106aa6106a5366004614987565b610e08565b005b61046a6106ba366004614987565b6113a4565b61046a7f000000000000000000000000000000000000000000000000000000000000000081565b61046a7f000000000000000000000000000000000000000000000000000000000000000081565b61046a7f000000000000000000000000000000000000000000000000000000000000000081565b61046a60055481565b61046a603c81565b61046a610753366004614987565b6114ad565b6104cb7f000000000000000000000000000000000000000000000000000000000000000081565b61046a6117ce565b61046a6117f1565b61046a7f000000000000000000000000000000000000000000000000000000000000000081565b61046a6118b3565b61046a6107cc3660046149b5565b611940565b61046a7f000000000000000000000000000000000000000000000000000000000000000081565b61046a611a96565b6106aa61080e366004614987565b611b39565b610826610821366004614a17565b611fe5565b60408051928352602083019190915201610474565b61046a6123d2565b6106aa612476565b60005461046a565b61046a60045481565b61046a61254a565b60025461046a565b61046a7f000000000000000000000000000000000000000000000000000000000000000081565b61046a670de0b6b3a764000081565b6106aa6108b0366004614987565b612574565b61046a60075481565b6104cb7f000000000000000000000000000000000000000000000000000000000000000081565b61046a6126a8565b61046a7f000000000000000000000000000000000000000000000000000000000000000081565b6106aa610922366004614987565b6126cc565b6104cb7f000000000000000000000000000000000000000000000000000000000000000081565b61046a7f000000000000000000000000000000000000000000000000000000000000000081565b61046a612c44565b6104cb7f000000000000000000000000000000000000000000000000000000000000000081565b6104cb7f000000000000000000000000000000000000000000000000000000000000000081565b61046a7f000000000000000000000000000000000000000000000000000000000000000081565b6109fa600081565b604051600f9190910b8152602001610474565b6106aa610a1b366004614a17565b612c68565b61046a7f000000000000000000000000000000000000000000000000000000000000000081565b61046a612f0d565b61046a610a5d366004614987565b612f25565b61046a7f000000000000000000000000000000000000000000000000000000000000000081565b61046a600d5481565b6104cb7f000000000000000000000000000000000000000000000000000000000000000081565b61046a600c5481565b610ad5610ad0366004614987565b613001565b6040805195865267ffffffffffffffff948516602087015292841692850192909252909116606083015260ff16608082015260a001610474565b61046a60065481565b6106aa6130d6565b61046a600b5481565b61046a7f000000000000000000000000000000000000000000000000000000000000000081565b61046a613131565b61046a600e5481565b600080610b6c61314d565b9050600080610b7a836131e2565b505050915091508082610b8d9190614a4f565b935050505090565b600080610ba061325c565b90506000610bce7f00000000000000000000000000000000000000000000000000000000000000008361326e565b90506000670de0b6b3a764000082600754610be99190614a67565b610bf39190614a9c565b90506000610c217f000000000000000000000000000000000000000000000000000000000000000087614a9c565b610c2b9083614a4f565b9050610c3f81670de0b6b3a76400006132f2565b9695505050505050565b600080610c5461314d565b90506000610c61826131e2565b50909695505050505050565b600080549080610c7b610b61565b91506001549050909192565b6000818152600860209081526040808320815160a08101835281548152600182015467ffffffffffffffff80821695830195909552600160401b8104851693820193909352600160801b830490931660608401528392916080830190600160c01b900460ff166003811115610cfe57610cfe614ab0565b6003811115610d0f57610d0f614ab0565b8152505090506000610d25600d54600e5461330a565b509050610d4d826040015167ffffffffffffffff16610d4784600001516134ee565b836134fa565b949350505050565b600080610d60613131565b6000848152600860209081526040808320815160a08101835281548152600182015467ffffffffffffffff80821695830195909552600160401b8104851693820193909352600160801b83049093166060840152939450919290916080830190600160c01b900460ff166003811115610ddb57610ddb614ab0565b6003811115610dec57610dec614ab0565b815250509050610d4d610e0282600001516134ee565b83613549565b6000818152600860209081526040808320815160a08101835281548152600182015467ffffffffffffffff80821695830195909552600160401b8104851693820193909352600160801b83049093166060840152906080830190600160c01b900460ff166003811115610e7d57610e7d614ab0565b6003811115610e8e57610e8e614ab0565b9052509050610e9c82613568565b610ea98160800151613651565b6000610eb36136b2565b9050600080610ec061371f565b91509150600080610ed486600001516137cd565b915091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f5a9190614ac6565b158015610f6a575060095460ff16155b15610f8b57610f88866040015167ffffffffffffffff16858561383e565b92505b6000610fa6876040015167ffffffffffffffff1683886134fa565b90506000610fb386612f25565b9050600081610fca84670de0b6b3a7640000614a67565b610fd49190614a9c565b9050610ff9610feb670de0b6b3a764000083614a9c565b67ffffffffffffffff6132f2565b60008b81526008602052604081206001908101805467ffffffffffffffff9485167fffffffffffffff00ffffffffffffffffffffffffffffffff000000000000000090911617600360c01b1767ffffffffffffffff60801b1916600160801b4295909516949094029390931790925590547f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690639841a0189033908e906110ca907f000000000000000000000000000000000000000000000000000000000000000090614a9c565b6040516001600160e01b031960e086901b1681526001600160a01b039093166004840152602483019190915260448201526064016020604051808303816000875af115801561111d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111419190614afe565b90506001600a60008282546111569190614a4f565b9091555050895160008054819061116e908490614b19565b909155505060408a01518a5161118e9167ffffffffffffffff1690614a67565b6005600082825461119f9190614b19565b90915550600090506111b18587614b19565b60095490915060ff166111db5780600160008282546111d09190614a4f565b909155506112829050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bfca6c116040518163ffffffff1660e01b8152600401606060405180830381865afa158015611239573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125d9190614b30565b5098506000905061126e828a6132f2565b90508015611280576112808133613972565b505b6040516340c10f1960e01b8152336004820152602481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906340c10f1990604401600060405180830381600087803b1580156112ea57600080fd5b505af11580156112fe573d6000803e3d6000fd5b505060095460ff161591505080156113165750868810155b156113245761132487613a0d565b8a51600954604080518f815260208101939093528201859052606082018390526080820189905260ff16151560a082015269ffffffffffffffffffff831660c082015233907fe0ae890eaa03f699e40e47e1644539436b9871b84f64d484b069ac9e0e9189149060e00160405180910390a2505050505050505050505050565b6000818152600860209081526040808320815160a08101835281548152600182015467ffffffffffffffff80821695830195909552600160401b8104851693820193909352600160801b830490931660608401528392916080830190600160c01b900460ff16600381111561141b5761141b614ab0565b600381111561142c5761142c614ab0565b905250905060018160800151600381111561144957611449614ab0565b146114575750600092915050565b600061147661146983600001516134ee565b611471613131565b613549565b90506000611488600d54600e5461330a565b5090506114a4836040015167ffffffffffffffff1683836134fa565b95945050505050565b60006114b882613a20565b6114c0613a9c565b6114c86136b2565b506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166340c10f19337f000000000000000000000000000000000000000000000000000000000000000060015461152a9190614a9c565b6040516001600160e01b031960e085901b1681526001600160a01b039092166004830152602482015260440160408051808303816000875af1158015611574573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115989190614b5e565b915091506115cb6040805160a0810182526000808252602082018190529181018290526060810182905290608082015290565b8481524267ffffffffffffffff16604082015260016080820181905250600083815260086020908152604091829020835181559083015160018201805493850151606086015167ffffffffffffffff908116600160801b0267ffffffffffffffff60801b19928216600160401b026fffffffffffffffffffffffffffffffff199097169190941617949094179384168217815560808501518594909260ff60c01b191668ffffffffffffffffff60801b1990911617600160c01b83600381111561169757611697614ab0565b0217905550905050846000808282546116b09190614a4f565b909155506116c090504286614a67565b600560008282546116d19190614a4f565b90915550506040516323b872dd60e01b8152336004820152306024820152604481018690527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303816000875af1158015611749573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061176d9190614b8a565b5061177785613afd565b604080518481526020810187905269ffffffffffffffffffff841681830152905133917ff3305d3ff042bc9868a6e25d2980cb0790e1edd5d6f0a32bb73650bce4926dd2919081900360600190a250909392505050565b6000806117d961314d565b905060006117e6826131e2565b509695505050505050565b6000806117fc6123d2565b9050600081156118ad5760007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bb7b8b806040518163ffffffff1660e01b8152600401602060405180830381865afa158015611866573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061188a9190614ac6565b9050670de0b6b3a764000061189f8285614a67565b6118a99190614a9c565b9150505b92915050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bfca6c116040518163ffffffff1660e01b8152600401606060405180830381865afa158015611914573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119389190614b30565b509392505050565b604051636eb1769f60e11b81526001600160a01b03878116600483015230602483015260009187917f0000000000000000000000000000000000000000000000000000000000000000169063dd62ed3e90604401602060405180830381865afa1580156119b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119d59190614ac6565b1015611a825760405163d505accf60e01b81526001600160a01b038881166004830152306024830152604482018890526064820187905260ff8616608483015260a4820185905260c482018490527f0000000000000000000000000000000000000000000000000000000000000000169063d505accf9060e401600060405180830381600087803b158015611a6957600080fd5b505af1158015611a7d573d6000803e3d6000fd5b505050505b611a8b866114ad565b979650505050505050565b6000600b54600a547f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611afc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b209190614ac6565b611b2a9190614b19565b611b349190614b19565b905090565b611b41613b91565b611b49613a9c565b611b51613c50565b611b59613d35565b600080611b6461371f565b915091506000805483611b779190614b19565b90506000611b836117f1565b9050611b8e81613e1a565b6000611b9a86846132f2565b9050611ba681856132f2565b9050611bbf8183600154611bba9190614b19565b6132f2565b9050611bca81613ea0565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bb7b8b806040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c2a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c4e9190614ac6565b90506000611c5b82613ef0565b90507f00000000000000000000000000000000000000000000000000000000000000008111611d1d5760405162461bcd60e51b815260206004820152605660248201527f43424d3a204c5553443a334352562065786368616e67652072617465206d757360448201527f74206265206f76657220746865206465706f736974207468726573686f6c642060648201527f6265666f72652053502d3e437572766520736869667400000000000000000000608482015260a4015b60405180910390fd5b611d278330613972565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015611d8e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611db29190614ac6565b6040805180820182528681526000602082018190529151630b4c7e4d60e01b81529293506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001692630b4c7e4d92611e149291600401614bac565b6020604051808303816000875af1158015611e33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e579190614ac6565b506040516370a0823160e01b815230600482015260009082906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611ec1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ee59190614ac6565b611eef9190614b19565b9050611efa81613fa8565b6000611f0585613ef0565b90508381108015611f3657507f00000000000000000000000000000000000000000000000000000000000000008110155b611fd85760405162461bcd60e51b815260206004820152606160248201527f43424d3a2053502d3e4375727665207368696674206d7573742064656372656160448201527f7365204c5553443a334352562065786368616e6765207261746520746f20612060648201527f76616c75652061626f766520746865206465706f736974207468726573686f6c6084820152601960fa1b60a482015260c401611d14565b5050505050505050505050565b600080611ff184613ea0565b611ffa84614177565b7f00000000000000000000000000000000000000000000000000000000000000006004546120289190614a4f565b4210156120c35760405162461bcd60e51b815260206004820152604f60248201527f43424d3a20526564656d7074696f6e206166746572206669727374206368696360448201527f6b656e20696e206d757374207761697420756e74696c20626f6f74737472617060648201527f20706572696f64206973206f7665720000000000000000000000000000000000608482015260a401611d14565b6000806000806120d1614287565b94509450509350935060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561213a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061215e9190614ac6565b6121708a670de0b6b3a7640000614a67565b61217a9190614a9c565b60095490915060009060ff1661219857612193826142b6565b61219b565b60005b905060008080670de0b6b3a76400006121b4868b614a67565b6121be9190614a9c565b90506000670de0b6b3a76400006121d58682614b19565b6121df9084614a67565b6121e99190614a9c565b90506121f58183614b19565b6121ff9085614a4f565b935061220b818e614357565b9250821561221d5761221d8333613972565b506000905086156122b8576000670de0b6b3a764000061223d878b614a67565b6122479190614a9c565b90506000670de0b6b3a764000061225e8782614b19565b6122689084614a67565b6122729190614a9c565b905061227e8183614b19565b6122889086614a4f565b945088816003546122999190614a67565b6122a39190614a9c565b925082156122b5576122b533846144c8565b50505b6122c28387614a4f565b6001556122d76122d28284614a4f565b613ea0565b604051632770a7eb60e21b8152336004820152602481018e90526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690639dc29fac90604401600060405180830381600087803b15801561233f57600080fd5b505af1158015612353573d6000803e3d6000fd5b50505050336001600160a01b03167fc0ac8b09f0bc9dd02f48d9145336ab9df1dc378b6115bc78e0f6c3d72bc37b178e8e8585886040516123b6959493929190948552602085019390935260408401919091526060830152608082015260a00190565b60405180910390a29099509750505050505050505b9250929050565b6000670de0b6b3a76400007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166399530b066040518163ffffffff1660e01b8152600401602060405180830381865afa15801561243b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061245f9190614ac6565b60035461246c9190614a67565b611b349190614a9c565b7f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000600c546124c59190614a4f565b6124cf9190614a4f565b4210156125445760405162461bcd60e51b815260206004820152603560248201527f43424d3a2050726576696f75732073686966742064656c617920616e6420776960448201527f6e646f77206d75737420686176652070617373656400000000000000000000006064820152608401611d14565b42600c55565b6000806125556117f1565b9050600061256161314d565b905061256d8282614a4f565b9250505090565b61257c61456e565b60095460ff16156125e25760405162461bcd60e51b815260206004820152602a60248201527f43424d3a205265636569766520666565207368617265206f6e6c7920696e206e6044820152696f726d616c206d6f646560b01b6064820152608401611d14565b6040516323b872dd60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152306024830152604482018390527f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906064016020604051808303816000875af1158015612677573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061269b9190614b8a565b506126a581613afd565b50565b6000806126b361314d565b905060006126c0826131e2565b50929695505050505050565b6126d4613b91565b6126dc613a9c565b6126e4613c50565b6126ec613d35565b60006126f66117f1565b9050600061270483836132f2565b905061270f81613ea0565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bb7b8b806040518163ffffffff1660e01b8152600401602060405180830381865afa15801561276f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127939190614ac6565b905060006127a0826145f2565b90507f0000000000000000000000000000000000000000000000000000000000000000811161285d5760405162461bcd60e51b815260206004820152605a60248201527f43424d3a20334352563a4c5553442065786368616e67652072617465206d757360448201527f742062652061626f766520746865207769746864726177616c2074687265736860648201527f6f6c64206265666f72652043757276652d3e5350207368696674000000000000608482015260a401611d14565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156128c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128e89190614ac6565b9050600085856003546128fb9190614a67565b6129059190614a9c565b9050612910816146aa565b6040516370a0823160e01b815230600482015260009083906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015612979573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061299d9190614ac6565b6129a79190614b19565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015612a11573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a359190614ac6565b604051630d2680e960e11b81526004810184905260006024820181905260448201529091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690631a4d01d290606401600060405180830381600087803b158015612aa857600080fd5b505af1158015612abc573d6000803e3d6000fd5b50506040516370a0823160e01b8152306004820152600092508391506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015612b29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b4d9190614ac6565b612b579190614b19565b9050612b6281613afd565b6000612b6d886145f2565b90508681108015612b9e57507f00000000000000000000000000000000000000000000000000000000000000008110155b611fd85760405162461bcd60e51b8152602060048201526064602482018190527f43424d3a2043757276652d3e5350207368696674206d75737420696e6372656160448301527f736520334352563a4c5553442065786368616e6765207261746520746f206120908201527f76616c75652061626f766520746865207769746864726177616c2074687265736084820152631a1bdb1960e21b60a482015260c401611d14565b600080612c4f61314d565b90506000612c5c826131e2565b50919695505050505050565b6000828152600860209081526040808320815160a08101835281548152600182015467ffffffffffffffff80821695830195909552600160401b8104851693820193909352600160801b83049093166060840152906080830190600160c01b900460ff166003811115612cdd57612cdd614ab0565b6003811115612cee57612cee614ab0565b9052509050612cfc83613568565b612d098160800151613651565b612d116136b2565b5060008381526008602052604081206001908101805467ffffffffffffffff4216600160801b0268ffffffffffffffffff60801b1990911617600160c11b179055546001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690639841a0189033908790612db3907f000000000000000000000000000000000000000000000000000000000000000090614a9c565b6040516001600160e01b031960e086901b1681526001600160a01b039093166004840152602483019190915260448201526064016020604051808303816000875af1158015612e06573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e2a9190614afe565b90506001600b6000828254612e3f9190614a4f565b90915550508151600080548190612e57908490614b19565b909155505060408201518251612e779167ffffffffffffffff1690614a67565b60056000828254612e889190614b19565b90915550508151600090612e9c9085614357565b9050612ea88133613972565b825160408051878152602081019290925281018590526060810182905269ffffffffffffffffffff8316608082015233907f3bd7a45d09d2d31d78737a80c00ac48ba89dd3cce7537ad56bf1bee66c9dc39e9060a00160405180910390a25050505050565b600080612f1e600d54600e5461330a565b5092915050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612f86573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612faa9190614ac6565b9050600080612fb8856131e2565b505050915091508260001415612fda5750670de0b6b3a7640000949350505050565b82612fe58284614a4f565b612ff790670de0b6b3a7640000614a67565b6114a49190614a9c565b6000818152600860209081526040808320815160a08101835281548152600182015467ffffffffffffffff80821695830195909552600160401b8104851693820193909352600160801b83049093166060840152839283928392839283929091906080830190600160c01b900460ff16600381111561308257613082614ab0565b600381111561309357613093614ab0565b8152505090508060000151816020015182604001518360600151846080015160038111156130c3576130c3614ab0565b939b929a50909850965090945092505050565b6130de61456e565b6130e6613a9c565b6009805460ff19166001908117909155546040519081527f6330fd496eb4822cdd507776770666698db359e48ce5a7797a0aaba0c879adca9060200160405180910390a16000600155565b60008061313c61314d565b905061314781612f25565b91505090565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bfca6c116040518163ffffffff1660e01b8152600401606060405180830381865afa1580156131ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131d29190614b30565b5091505061314760025482614748565b60008060008060008054866131f79190614b19565b92506132016117f1565b600154909250905060006132158385614a4f565b90508181111561325257600061322b8383614b19565b9050816132388683614a67565b6132429190614a9c565b965061324e8782614b19565b9550505b5091939590929450565b6000603c6006544261246c9190614b19565b6000631f54050082111561328457631f54050091505b816132985750670de0b6b3a76400006118ad565b670de0b6b3a764000083835b60018111156132e8576132b8600282614be4565b156132ca576132c78284614758565b92505b6132d48283614758565b91506132e1600282614a9c565b90506132a4565b610c3f8284614758565b60008183106133015781613303565b825b9392505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006133587f000000000000000000000000000000000000000000000000000000000000000042614b19565b6133629190614a9c565b90508281148061339157507f000000000000000000000000000000000000000000000000000000000000000084145b8061339c5750600054155b156133a9578391506123cb565b600080546005546133ba9190614a9c565b9050600061343c7f000000000000000000000000000000000000000000000000000000000000000061340c7f000000000000000000000000000000000000000000000000000000000000000085614a4f565b6134169190614b19565b7f0000000000000000000000000000000000000000000000000000000000000000614782565b9050808310156134505785935050506123cb565b600061346686613461600185614b19565b614748565b6134709085614b19565b90506134e2670de0b6b3a76400006134a87f00000000000000000000000000000000000000000000000000000000000000008461326e565b6134b2908a614a67565b6134bc9190614a9c565b7f0000000000000000000000000000000000000000000000000000000000000000614748565b94505050509250929050565b600080610d4d836137cd565b60008361350957506000613303565b60006135158542614b19565b61352790670de0b6b3a7640000614a67565b905060006135358483614a4f565b61353f8387614a67565b610c3f9190614a9c565b60008161355e84670de0b6b3a7640000614a67565b6133039190614a9c565b6040516331a9108f60e11b8152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa1580156135cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135f19190614bf8565b6001600160a01b0316336001600160a01b0316146126a55760405162461bcd60e51b815260206004820152601d60248201527f43424d3a2043616c6c6572206d757374206f776e2074686520626f6e640000006044820152606401611d14565b600181600381111561366557613665614ab0565b146126a55760405162461bcd60e51b815260206004820152601860248201527f43424d3a20426f6e64206d7573742062652061637469766500000000000000006044820152606401611d14565b600d54600e546000919082806136c8848461330a565b9150915082811461193857600e81905581841461193857600d8290556040518281527fdf0b753b5dc9a250a9e6268e9c010c895cd12d6e66f6cfb57531a3a49315d09a9060200160405180910390a1509392505050565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bfca6c116040518163ffffffff1660e01b8152600401606060405180830381865afa158015613782573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137a69190614b30565b506002549092509050808211156137c557506002819055928392509050565b939092509050565b600954600090819060ff16156137e557506000929050565b6000670de0b6b3a764000061381a7f000000000000000000000000000000000000000000000000000000000000000086614a67565b6138249190614a9c565b905060006138328286614b19565b91959194509092505050565b600061386a7f000000000000000000000000000000000000000000000000000000000000000085614a4f565b4210156138df5760405162461bcd60e51b815260206004820152603e60248201527f43424d3a20466972737420636869636b656e20696e206d75737420776169742060448201527f756e74696c20626f6f74737472617020706572696f64206973206f76657200006064820152608401611d14565b4260045560006138ee846131e2565b505050509050808310156139595760405162461bcd60e51b815260206004820152602c60248201527f43424d3a204e6f7420656e6f756768204c55534420617661696c61626c65206960448201526b1b88108b941c9bdd1bd8dbdb60a21b6064820152608401611d14565b80156139685761396881613a0d565b6114a48184614b19565b604051627b8a6760e11b8152600481018390526001600160a01b0382811660248301527f0000000000000000000000000000000000000000000000000000000000000000169062f714ce90604401600060405180830381600087803b1580156139da57600080fd5b505af11580156139ee573d6000803e3d6000fd5b505050508160026000828254613a049190614b19565b90915550505050565b613a178130613972565b6126a5816147b4565b7f00000000000000000000000000000000000000000000000000000000000000008110156126a55760405162461bcd60e51b8152602060048201526024808201527f43424d3a20426f6e64206d696e696d756d20616d6f756e74206e6f742072656160448201526318da195960e21b6064820152608401611d14565b60095460ff1615613afb5760405162461bcd60e51b8152602060048201526024808201527f43424d3a204d6967726174696f6e206d757374206265206e6f742062652061636044820152637469766560e01b6064820152608401611d14565b565b60405163b6b55f2560e01b8152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063b6b55f2590602401600060405180830381600087803b158015613b5f57600080fd5b505af1158015613b73573d6000803e3d6000fd5b505050508060026000828254613b899190614a4f565b909155505050565b7f0000000000000000000000000000000000000000000000000000000000000000613bdc7f000000000000000000000000000000000000000000000000000000000000000042614b19565b1015613afb5760405162461bcd60e51b815260206004820152603c60248201527f43424d3a2053686966746572206f6e6c792063616c6c61626c6520616674657260448201527f20736869667420626f6f74737472617020706572696f6420656e6473000000006064820152608401611d14565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613cb0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cd49190614ac6565b11613afb5760405162461bcd60e51b815260206004820152602b60248201527f43424d3a20624c55534420537570706c79206d757374206265203e203020757060448201526a6f6e207368696674696e6760a81b6064820152608401611d14565b60007f0000000000000000000000000000000000000000000000000000000000000000600c54613d659190614a4f565b90506000613d937f000000000000000000000000000000000000000000000000000000000000000083614a4f565b9050814210158015613da457508042105b613e165760405162461bcd60e51b815260206004820152602f60248201527f43424d3a205368696674206f6e6c7920706f737369626c6520696e736964652060448201527f7368696674696e672077696e646f7700000000000000000000000000000000006064820152608401611d14565b5050565b8060015410156126a55760405162461bcd60e51b8152602060048201526044602482018190527f43424d3a2054686520616d6f756e7420696e2043757276652063616e6e6f7420908201527f62652067726561746572207468616e20746865205065726d616e656e7420627560648201526318dad95d60e21b608482015260a401611d14565b600081116126a55760405162461bcd60e51b815260206004820152601760248201527f43424d3a20416d6f756e74206d757374206265203e20300000000000000000006044820152606401611d14565b604051635e0d443f60e01b815260006004820181905260016024830152670de0b6b3a764000060448301529081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690635e0d443f90606401602060405180830381865afa158015613f6f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f939190614ac6565b9050670de0b6b3a764000061355e8483614a67565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561400f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140339190614ac6565b60405163b6b55f2560e01b8152600481018490529091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063b6b55f25906024016020604051808303816000875af115801561409d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140c19190614ac6565b506040516370a0823160e01b815230600482015260009082906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa15801561412b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061414f9190614ac6565b6141599190614b19565b9050806003600082825461416d9190614a4f565b9091555050505050565b60095460ff166126a5577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156141df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142039190614ac6565b61422d7f000000000000000000000000000000000000000000000000000000000000000083614a4f565b11156126a55760405162461bcd60e51b815260206004820152602360248201527f43424d3a2043616e6e6f742072656465656d2062656c6f77206d696e20737570604482015262706c7960e81b6064820152608401611d14565b60008060008060008061429861371f565b5090506142a4816131e2565b95509550955095509550509091929394565b6000806142c283610b95565b60078190556040518181529091507fe31dea26c34fb8440bf2eec033dfd26bd39e88e026348d996e275a396417109b9060200160405180910390a160006006544261430d9190614b19565b9050603c8110612f1e574260068190556040519081527fbab964312bdd13595266f3e549bca3102965a6d718c6c1f8cd7eaac076b9c6c29060200160405180910390a15092915050565b6000818310156143cf5760405162461bcd60e51b815260206004820152603460248201527f43424d3a204d696e2076616c75652063616e6e6f74206265206772656174657260448201527f207468616e206e6f6d696e616c20616d6f756e740000000000000000000000006064820152608401611d14565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bfca6c116040518163ffffffff1660e01b8152600401606060405180830381865afa15801561442f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144539190614b30565b50915050828110156144bc5760405162461bcd60e51b815260206004820152602c60248201527f43424d3a204e6f7420656e6f756768204c55534420617661696c61626c65206960448201526b1b88108b941c9bdd1bd8dbdb60a21b6064820152608401611d14565b60006114a485836132f2565b60405163a9059cbb60e01b81526001600160a01b038381166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015614537573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061455b9190614b8a565b508060036000828254613a049190614b19565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614613afb5760405162461bcd60e51b815260206004820152602360248201527f43424d3a204f6e6c7920596561726e20476f7665726e616e63652063616e2063604482015262185b1b60ea1b6064820152608401611d14565b604051635e0d443f60e01b815260016004820152600060248201819052670de0b6b3a764000060448301529081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690635e0d443f90606401602060405180830381865afa158015614671573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146959190614ac6565b90508261355e82670de0b6b3a7640000614a67565b604051632e1a7d4d60e01b8152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d906024016020604051808303816000875af1158015614711573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147359190614ac6565b508060036000828254613b899190614b19565b6000818310156133015781613303565b6000670de0b6b3a764000061476e600282614a9c565b6147788486614a67565b61355e9190614a4f565b600061478e8284614be4565b1561479a57600161479d565b60005b60ff166147aa8385614a9c565b6133039190614a4f565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561481b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061483f9190614ac6565b6040516393f7aa6760e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018590529192507f0000000000000000000000000000000000000000000000000000000000000000909116906393f7aa6790604401600060405180830381600087803b1580156148ce57600080fd5b505af11580156148e2573d6000803e3d6000fd5b50506040516370a0823160e01b81523060048201528492507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031691506370a0823190602401602060405180830381865afa15801561494c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906149709190614ac6565b61497a9083614b19565b14613e1657613e16614c15565b60006020828403121561499957600080fd5b5035919050565b6001600160a01b03811681146126a557600080fd5b60008060008060008060c087890312156149ce57600080fd5b86356149d9816149a0565b95506020870135945060408701359350606087013560ff811681146149fd57600080fd5b9598949750929560808101359460a0909101359350915050565b60008060408385031215614a2a57600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b60008219821115614a6257614a62614a39565b500190565b6000816000190483118215151615614a8157614a81614a39565b500290565b634e487b7160e01b600052601260045260246000fd5b600082614aab57614aab614a86565b500490565b634e487b7160e01b600052602160045260246000fd5b600060208284031215614ad857600080fd5b5051919050565b805169ffffffffffffffffffff81168114614af957600080fd5b919050565b600060208284031215614b1057600080fd5b61330382614adf565b600082821015614b2b57614b2b614a39565b500390565b600080600060608486031215614b4557600080fd5b8351925060208401519150604084015190509250925092565b60008060408385031215614b7157600080fd5b82519150614b8160208401614adf565b90509250929050565b600060208284031215614b9c57600080fd5b8151801515811461330357600080fd5b60608101818460005b6002811015614bd4578151835260209283019290910190600101614bb5565b5050508260408301529392505050565b600082614bf357614bf3614a86565b500690565b600060208284031215614c0a57600080fd5b8151613303816149a0565b634e487b7160e01b600052600160045260246000fdfea2646970667358221220d50cb42b3fa172de0f06883778cf4e6e0328c7e338330d8671e5c083cbaed28a64736f6c634300080b0033000000000000000000000000c96265c8748c8361d77fe99d42ae78aae63995a60000000000000000000000005f98805a4e8be255a32880fdec7f6728c6568ba0000000000000000000000000ed279fdd11ca84beef15af5d39bb4d4bee23f0ca000000000000000000000000bebc44782c7db0a1a60cb6fe97d0b483032ff1c70000000000000000000000009062d1477c3cd000301a471be03c9db85c3fc27a0000000000000000000000005fa5b62c8af877cb37031e0a3b2f34a78e3c56a600000000000000000000000050c1a2ea0a861a967d9d0ffe2ae4012c2e053804000000000000000000000000feb4acf3df3cdea7399794d0869ef76a6efaff5200000000000000000000000020658291677a29efddfd0e303f8b23113d837cc7000000000000000000000000009644832140fed8b3b2b40405612f0c06ab3917000000000000000000000000000000000000000000000000000000000013c68000000000000000000000000000000000000000000000437af901e1dfac4c000000000000000000000000000000000000000000000000001146649c213f678000000000000000000000000000000000000000000000000000002386f26fc100000000000000000000000000000000000000000000000000000000000000015180000000000000000000000000000000000000000000000000006a94d74f4300000000000000000000000000000000000000000000000000000de2227fe94d00000000000000000000000000000000000000000000000000000de2227fe94d0000000000000000000000000000000000000000000000000000000000000013c680000000000000000000000000000000000000000000000000000000000013c68000000000000000000000000000000000000000000000000000000000003b53800000000000000000000000000000000000000000000000000000000000000e1000000000000000000000000000000000000000000000000000000000000002580000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000056bc75e2d6310000000000000000000000000000000000000000000000000003635c9adc5dea00000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061043e5760003560e01c80637cbc237311610236578063b83f91a21161013b578063cc0c986e116100c3578063e9dc9e6d11610087578063e9dc9e6d14610b18578063edb134f314610b20578063f1b0cff514610b29578063f3c4023d14610b50578063f58369b914610b5857600080fd5b8063cc0c986e14610a89578063cfc31f6f14610a92578063d2e892dd14610ab9578063da10594314610ac2578063e324634914610b0f57600080fd5b8063c3c297451161010a578063c3c2974514610a0d578063c484cc5f14610a20578063c6c50ce814610a47578063c6d2d26114610a4f578063c7b5548114610a6257600080fd5b8063b83f91a21461097d578063bb870317146109a4578063bfc12c05146109cb578063c0639bbd146109f257600080fd5b8063a21ec280116101be578063acf955c71161018d578063acf955c7146108ed578063aefcc4fd14610914578063b0f3af4714610927578063b23ad3ee1461094e578063b7a65dce1461097557600080fd5b8063a21ec280146108a2578063a79e5683146108b5578063a891c684146108be578063ac8af3a9146108e557600080fd5b806390d532901161020557806390d532901461085357806391dc186f1461085c5780639c283187146108645780639fbc4a5f1461086c578063a20baee61461089357600080fd5b80637cbc23731461081357806384c2dea51461083b5780638ac6e2f4146108435780638caffae11461084b57600080fd5b80634237e191116103475780636350e4b2116102cf578063695e89da11610293578063695e89da146107b65780636a57b253146107be5780636b4fbbed146107d15780636bdac50b146107f85780637b3c7df61461080057600080fd5b80636350e4b2146107455780636381211414610758578063653a81981461077f57806366462ab11461078757806367e48a7e1461078f57600080fd5b80635041382b116103165780635041382b146106bf57806351a643ae146106e6578063570dd5241461070d57806359372e2e1461073457806361ec893d1461073d57600080fd5b80634237e1911461065d5780634903970a146106705780634b10543b146106975780634bb41097146106ac57600080fd5b806335f1d0e0116103ca5780633792dcb9116103995780633792dcb9146105d157806339f01388146105f85780633a517326146106005780633b19e84a146106275780633cbe79261461064a57600080fd5b806335f1d0e014610587578063361628831461058f57806336e2819e146105b657806337303e58146105c957600080fd5b8063218751b211610411578063218751b214610500578063233b0ee71461052757806327fafcd31461054e57806333624a861461055757806335567cda1461057e57600080fd5b80630277407314610443578063071a75411461047d5780630f34d74d146104a45780631705a3bd146104e3575b600080fd5b61046a7f000000000000000000000000000000000000000000000000000000000001518081565b6040519081526020015b60405180910390f35b61046a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81565b6104cb7f000000000000000000000000009644832140fed8b3b2b40405612f0c06ab391781565b6040516001600160a01b039091168152602001610474565b6009546104f09060ff1681565b6040519015158152602001610474565b6104cb7f000000000000000000000000ed279fdd11ca84beef15af5d39bb4d4bee23f0ca81565b61046a7f000000000000000000000000000000000000000000000000000000000013c68081565b61046a600a5481565b6104cb7f0000000000000000000000009062d1477c3cd000301a471be03c9db85c3fc27a81565b61046a60035481565b61046a610b61565b61046a7f00000000000000000000000000000000000000000000000000000000003b538081565b61046a6105c4366004614987565b610b95565b61046a610c49565b6104cb7f00000000000000000000000020658291677a29efddfd0e303f8b23113d837cc781565b60015461046a565b61046a7f000000000000000000000000000000000000000000000000006a94d74f43000081565b61062f610c6d565b60408051938452602084019290925290820152606001610474565b61046a610658366004614987565b610c87565b61046a61066b366004614987565b610d55565b61046a7f000000000000000000000000000000000000000000000000000000000013c68081565b6106aa6106a5366004614987565b610e08565b005b61046a6106ba366004614987565b6113a4565b61046a7f0000000000000000000000000000000000000000000000000de0b6b3a764000081565b61046a7f000000000000000000000000000000000000000000000000000000000013c68081565b61046a7f00000000000000000000000000000000000000000000003635c9adc5dea0000081565b61046a60055481565b61046a603c81565b61046a610753366004614987565b6114ad565b6104cb7f000000000000000000000000feb4acf3df3cdea7399794d0869ef76a6efaff5281565b61046a6117ce565b61046a6117f1565b61046a7f0000000000000000000000000000000000000000000000000000000000000e1081565b61046a6118b3565b61046a6107cc3660046149b5565b611940565b61046a7f000000000000000000000000000000000000000000000000000000000000025881565b61046a611a96565b6106aa61080e366004614987565b611b39565b610826610821366004614a17565b611fe5565b60408051928352602083019190915201610474565b61046a6123d2565b6106aa612476565b60005461046a565b61046a60045481565b61046a61254a565b60025461046a565b61046a7f0000000000000000000000000000000000000000000000056bc75e2d6310000081565b61046a670de0b6b3a764000081565b6106aa6108b0366004614987565b612574565b61046a60075481565b6104cb7f000000000000000000000000bebc44782c7db0a1a60cb6fe97d0b483032ff1c781565b61046a6126a8565b61046a7f0000000000000000000000000000000000000000000000000de0b68e66a5c00081565b6106aa610922366004614987565b6126cc565b6104cb7f000000000000000000000000c96265c8748c8361d77fe99d42ae78aae63995a681565b61046a7f0000000000000000000000000000000000000000000000000de0b68e66a5c00081565b61046a612c44565b6104cb7f0000000000000000000000005f98805a4e8be255a32880fdec7f6728c6568ba081565b6104cb7f00000000000000000000000050c1a2ea0a861a967d9d0ffe2ae4012c2e05380481565b61046a7f00000000000000000000000000000000000000000000000000000000633bee1781565b6109fa600081565b604051600f9190910b8152602001610474565b6106aa610a1b366004614a17565b612c68565b61046a7f00000000000000000000000000000000000000000000001146649c213f67800081565b61046a612f0d565b61046a610a5d366004614987565b612f25565b61046a7f000000000000000000000000000000000000000000000000000000000000000081565b61046a600d5481565b6104cb7f0000000000000000000000005fa5b62c8af877cb37031e0a3b2f34a78e3c56a681565b61046a600c5481565b610ad5610ad0366004614987565b613001565b6040805195865267ffffffffffffffff948516602087015292841692850192909252909116606083015260ff16608082015260a001610474565b61046a60065481565b6106aa6130d6565b61046a600b5481565b61046a7f0000000000000000000000000000000000000000000000000dbd2fc137a3000081565b61046a613131565b61046a600e5481565b600080610b6c61314d565b9050600080610b7a836131e2565b505050915091508082610b8d9190614a4f565b935050505090565b600080610ba061325c565b90506000610bce7f00000000000000000000000000000000000000000000000000000000000000008361326e565b90506000670de0b6b3a764000082600754610be99190614a67565b610bf39190614a9c565b90506000610c217fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff87614a9c565b610c2b9083614a4f565b9050610c3f81670de0b6b3a76400006132f2565b9695505050505050565b600080610c5461314d565b90506000610c61826131e2565b50909695505050505050565b600080549080610c7b610b61565b91506001549050909192565b6000818152600860209081526040808320815160a08101835281548152600182015467ffffffffffffffff80821695830195909552600160401b8104851693820193909352600160801b830490931660608401528392916080830190600160c01b900460ff166003811115610cfe57610cfe614ab0565b6003811115610d0f57610d0f614ab0565b8152505090506000610d25600d54600e5461330a565b509050610d4d826040015167ffffffffffffffff16610d4784600001516134ee565b836134fa565b949350505050565b600080610d60613131565b6000848152600860209081526040808320815160a08101835281548152600182015467ffffffffffffffff80821695830195909552600160401b8104851693820193909352600160801b83049093166060840152939450919290916080830190600160c01b900460ff166003811115610ddb57610ddb614ab0565b6003811115610dec57610dec614ab0565b815250509050610d4d610e0282600001516134ee565b83613549565b6000818152600860209081526040808320815160a08101835281548152600182015467ffffffffffffffff80821695830195909552600160401b8104851693820193909352600160801b83049093166060840152906080830190600160c01b900460ff166003811115610e7d57610e7d614ab0565b6003811115610e8e57610e8e614ab0565b9052509050610e9c82613568565b610ea98160800151613651565b6000610eb36136b2565b9050600080610ec061371f565b91509150600080610ed486600001516137cd565b915091507f00000000000000000000000020658291677a29efddfd0e303f8b23113d837cc76001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f5a9190614ac6565b158015610f6a575060095460ff16155b15610f8b57610f88866040015167ffffffffffffffff16858561383e565b92505b6000610fa6876040015167ffffffffffffffff1683886134fa565b90506000610fb386612f25565b9050600081610fca84670de0b6b3a7640000614a67565b610fd49190614a9c565b9050610ff9610feb670de0b6b3a764000083614a9c565b67ffffffffffffffff6132f2565b60008b81526008602052604081206001908101805467ffffffffffffffff9485167fffffffffffffff00ffffffffffffffffffffffffffffffff000000000000000090911617600360c01b1767ffffffffffffffff60801b1916600160801b4295909516949094029390931790925590547f000000000000000000000000c96265c8748c8361d77fe99d42ae78aae63995a66001600160a01b031690639841a0189033908e906110ca907f00000000000000000000000000000000000000000000003635c9adc5dea0000090614a9c565b6040516001600160e01b031960e086901b1681526001600160a01b039093166004840152602483019190915260448201526064016020604051808303816000875af115801561111d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111419190614afe565b90506001600a60008282546111569190614a4f565b9091555050895160008054819061116e908490614b19565b909155505060408a01518a5161118e9167ffffffffffffffff1690614a67565b6005600082825461119f9190614b19565b90915550600090506111b18587614b19565b60095490915060ff166111db5780600160008282546111d09190614a4f565b909155506112829050565b7f0000000000000000000000009062d1477c3cd000301a471be03c9db85c3fc27a6001600160a01b031663bfca6c116040518163ffffffff1660e01b8152600401606060405180830381865afa158015611239573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125d9190614b30565b5098506000905061126e828a6132f2565b90508015611280576112808133613972565b505b6040516340c10f1960e01b8152336004820152602481018490527f00000000000000000000000020658291677a29efddfd0e303f8b23113d837cc76001600160a01b0316906340c10f1990604401600060405180830381600087803b1580156112ea57600080fd5b505af11580156112fe573d6000803e3d6000fd5b505060095460ff161591505080156113165750868810155b156113245761132487613a0d565b8a51600954604080518f815260208101939093528201859052606082018390526080820189905260ff16151560a082015269ffffffffffffffffffff831660c082015233907fe0ae890eaa03f699e40e47e1644539436b9871b84f64d484b069ac9e0e9189149060e00160405180910390a2505050505050505050505050565b6000818152600860209081526040808320815160a08101835281548152600182015467ffffffffffffffff80821695830195909552600160401b8104851693820193909352600160801b830490931660608401528392916080830190600160c01b900460ff16600381111561141b5761141b614ab0565b600381111561142c5761142c614ab0565b905250905060018160800151600381111561144957611449614ab0565b146114575750600092915050565b600061147661146983600001516134ee565b611471613131565b613549565b90506000611488600d54600e5461330a565b5090506114a4836040015167ffffffffffffffff1683836134fa565b95945050505050565b60006114b882613a20565b6114c0613a9c565b6114c86136b2565b506000807f000000000000000000000000c96265c8748c8361d77fe99d42ae78aae63995a66001600160a01b03166340c10f19337f00000000000000000000000000000000000000000000003635c9adc5dea0000060015461152a9190614a9c565b6040516001600160e01b031960e085901b1681526001600160a01b039092166004830152602482015260440160408051808303816000875af1158015611574573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115989190614b5e565b915091506115cb6040805160a0810182526000808252602082018190529181018290526060810182905290608082015290565b8481524267ffffffffffffffff16604082015260016080820181905250600083815260086020908152604091829020835181559083015160018201805493850151606086015167ffffffffffffffff908116600160801b0267ffffffffffffffff60801b19928216600160401b026fffffffffffffffffffffffffffffffff199097169190941617949094179384168217815560808501518594909260ff60c01b191668ffffffffffffffffff60801b1990911617600160c01b83600381111561169757611697614ab0565b0217905550905050846000808282546116b09190614a4f565b909155506116c090504286614a67565b600560008282546116d19190614a4f565b90915550506040516323b872dd60e01b8152336004820152306024820152604481018690527f0000000000000000000000005f98805a4e8be255a32880fdec7f6728c6568ba06001600160a01b0316906323b872dd906064016020604051808303816000875af1158015611749573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061176d9190614b8a565b5061177785613afd565b604080518481526020810187905269ffffffffffffffffffff841681830152905133917ff3305d3ff042bc9868a6e25d2980cb0790e1edd5d6f0a32bb73650bce4926dd2919081900360600190a250909392505050565b6000806117d961314d565b905060006117e6826131e2565b509695505050505050565b6000806117fc6123d2565b9050600081156118ad5760007f000000000000000000000000ed279fdd11ca84beef15af5d39bb4d4bee23f0ca6001600160a01b031663bb7b8b806040518163ffffffff1660e01b8152600401602060405180830381865afa158015611866573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061188a9190614ac6565b9050670de0b6b3a764000061189f8285614a67565b6118a99190614a9c565b9150505b92915050565b6000807f0000000000000000000000009062d1477c3cd000301a471be03c9db85c3fc27a6001600160a01b031663bfca6c116040518163ffffffff1660e01b8152600401606060405180830381865afa158015611914573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119389190614b30565b509392505050565b604051636eb1769f60e11b81526001600160a01b03878116600483015230602483015260009187917f0000000000000000000000005f98805a4e8be255a32880fdec7f6728c6568ba0169063dd62ed3e90604401602060405180830381865afa1580156119b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119d59190614ac6565b1015611a825760405163d505accf60e01b81526001600160a01b038881166004830152306024830152604482018890526064820187905260ff8616608483015260a4820185905260c482018490527f0000000000000000000000005f98805a4e8be255a32880fdec7f6728c6568ba0169063d505accf9060e401600060405180830381600087803b158015611a6957600080fd5b505af1158015611a7d573d6000803e3d6000fd5b505050505b611a8b866114ad565b979650505050505050565b6000600b54600a547f000000000000000000000000c96265c8748c8361d77fe99d42ae78aae63995a66001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611afc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b209190614ac6565b611b2a9190614b19565b611b349190614b19565b905090565b611b41613b91565b611b49613a9c565b611b51613c50565b611b59613d35565b600080611b6461371f565b915091506000805483611b779190614b19565b90506000611b836117f1565b9050611b8e81613e1a565b6000611b9a86846132f2565b9050611ba681856132f2565b9050611bbf8183600154611bba9190614b19565b6132f2565b9050611bca81613ea0565b60007f000000000000000000000000bebc44782c7db0a1a60cb6fe97d0b483032ff1c76001600160a01b031663bb7b8b806040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c2a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c4e9190614ac6565b90506000611c5b82613ef0565b90507f0000000000000000000000000000000000000000000000000de0b68e66a5c0008111611d1d5760405162461bcd60e51b815260206004820152605660248201527f43424d3a204c5553443a334352562065786368616e67652072617465206d757360448201527f74206265206f76657220746865206465706f736974207468726573686f6c642060648201527f6265666f72652053502d3e437572766520736869667400000000000000000000608482015260a4015b60405180910390fd5b611d278330613972565b6040516370a0823160e01b81523060048201526000907f000000000000000000000000ed279fdd11ca84beef15af5d39bb4d4bee23f0ca6001600160a01b0316906370a0823190602401602060405180830381865afa158015611d8e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611db29190614ac6565b6040805180820182528681526000602082018190529151630b4c7e4d60e01b81529293506001600160a01b037f000000000000000000000000ed279fdd11ca84beef15af5d39bb4d4bee23f0ca1692630b4c7e4d92611e149291600401614bac565b6020604051808303816000875af1158015611e33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e579190614ac6565b506040516370a0823160e01b815230600482015260009082906001600160a01b037f000000000000000000000000ed279fdd11ca84beef15af5d39bb4d4bee23f0ca16906370a0823190602401602060405180830381865afa158015611ec1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ee59190614ac6565b611eef9190614b19565b9050611efa81613fa8565b6000611f0585613ef0565b90508381108015611f3657507f0000000000000000000000000000000000000000000000000de0b68e66a5c0008110155b611fd85760405162461bcd60e51b815260206004820152606160248201527f43424d3a2053502d3e4375727665207368696674206d7573742064656372656160448201527f7365204c5553443a334352562065786368616e6765207261746520746f20612060648201527f76616c75652061626f766520746865206465706f736974207468726573686f6c6084820152601960fa1b60a482015260c401611d14565b5050505050505050505050565b600080611ff184613ea0565b611ffa84614177565b7f000000000000000000000000000000000000000000000000000000000013c6806004546120289190614a4f565b4210156120c35760405162461bcd60e51b815260206004820152604f60248201527f43424d3a20526564656d7074696f6e206166746572206669727374206368696360448201527f6b656e20696e206d757374207761697420756e74696c20626f6f74737472617060648201527f20706572696f64206973206f7665720000000000000000000000000000000000608482015260a401611d14565b6000806000806120d1614287565b94509450509350935060007f00000000000000000000000020658291677a29efddfd0e303f8b23113d837cc76001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561213a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061215e9190614ac6565b6121708a670de0b6b3a7640000614a67565b61217a9190614a9c565b60095490915060009060ff1661219857612193826142b6565b61219b565b60005b905060008080670de0b6b3a76400006121b4868b614a67565b6121be9190614a9c565b90506000670de0b6b3a76400006121d58682614b19565b6121df9084614a67565b6121e99190614a9c565b90506121f58183614b19565b6121ff9085614a4f565b935061220b818e614357565b9250821561221d5761221d8333613972565b506000905086156122b8576000670de0b6b3a764000061223d878b614a67565b6122479190614a9c565b90506000670de0b6b3a764000061225e8782614b19565b6122689084614a67565b6122729190614a9c565b905061227e8183614b19565b6122889086614a4f565b945088816003546122999190614a67565b6122a39190614a9c565b925082156122b5576122b533846144c8565b50505b6122c28387614a4f565b6001556122d76122d28284614a4f565b613ea0565b604051632770a7eb60e21b8152336004820152602481018e90526001600160a01b037f00000000000000000000000020658291677a29efddfd0e303f8b23113d837cc71690639dc29fac90604401600060405180830381600087803b15801561233f57600080fd5b505af1158015612353573d6000803e3d6000fd5b50505050336001600160a01b03167fc0ac8b09f0bc9dd02f48d9145336ab9df1dc378b6115bc78e0f6c3d72bc37b178e8e8585886040516123b6959493929190948552602085019390935260408401919091526060830152608082015260a00190565b60405180910390a29099509750505050505050505b9250929050565b6000670de0b6b3a76400007f0000000000000000000000005fa5b62c8af877cb37031e0a3b2f34a78e3c56a66001600160a01b03166399530b066040518163ffffffff1660e01b8152600401602060405180830381865afa15801561243b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061245f9190614ac6565b60035461246c9190614a67565b611b349190614a9c565b7f00000000000000000000000000000000000000000000000000000000000002587f0000000000000000000000000000000000000000000000000000000000000e10600c546124c59190614a4f565b6124cf9190614a4f565b4210156125445760405162461bcd60e51b815260206004820152603560248201527f43424d3a2050726576696f75732073686966742064656c617920616e6420776960448201527f6e646f77206d75737420686176652070617373656400000000000000000000006064820152608401611d14565b42600c55565b6000806125556117f1565b9050600061256161314d565b905061256d8282614a4f565b9250505090565b61257c61456e565b60095460ff16156125e25760405162461bcd60e51b815260206004820152602a60248201527f43424d3a205265636569766520666565207368617265206f6e6c7920696e206e6044820152696f726d616c206d6f646560b01b6064820152608401611d14565b6040516323b872dd60e01b81526001600160a01b037f000000000000000000000000feb4acf3df3cdea7399794d0869ef76a6efaff5281166004830152306024830152604482018390527f0000000000000000000000005f98805a4e8be255a32880fdec7f6728c6568ba016906323b872dd906064016020604051808303816000875af1158015612677573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061269b9190614b8a565b506126a581613afd565b50565b6000806126b361314d565b905060006126c0826131e2565b50929695505050505050565b6126d4613b91565b6126dc613a9c565b6126e4613c50565b6126ec613d35565b60006126f66117f1565b9050600061270483836132f2565b905061270f81613ea0565b60007f000000000000000000000000bebc44782c7db0a1a60cb6fe97d0b483032ff1c76001600160a01b031663bb7b8b806040518163ffffffff1660e01b8152600401602060405180830381865afa15801561276f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127939190614ac6565b905060006127a0826145f2565b90507f0000000000000000000000000000000000000000000000000de0b68e66a5c000811161285d5760405162461bcd60e51b815260206004820152605a60248201527f43424d3a20334352563a4c5553442065786368616e67652072617465206d757360448201527f742062652061626f766520746865207769746864726177616c2074687265736860648201527f6f6c64206265666f72652043757276652d3e5350207368696674000000000000608482015260a401611d14565b6040516370a0823160e01b81523060048201526000907f000000000000000000000000ed279fdd11ca84beef15af5d39bb4d4bee23f0ca6001600160a01b0316906370a0823190602401602060405180830381865afa1580156128c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128e89190614ac6565b9050600085856003546128fb9190614a67565b6129059190614a9c565b9050612910816146aa565b6040516370a0823160e01b815230600482015260009083906001600160a01b037f000000000000000000000000ed279fdd11ca84beef15af5d39bb4d4bee23f0ca16906370a0823190602401602060405180830381865afa158015612979573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061299d9190614ac6565b6129a79190614b19565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f0000000000000000000000005f98805a4e8be255a32880fdec7f6728c6568ba016906370a0823190602401602060405180830381865afa158015612a11573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a359190614ac6565b604051630d2680e960e11b81526004810184905260006024820181905260448201529091507f000000000000000000000000ed279fdd11ca84beef15af5d39bb4d4bee23f0ca6001600160a01b031690631a4d01d290606401600060405180830381600087803b158015612aa857600080fd5b505af1158015612abc573d6000803e3d6000fd5b50506040516370a0823160e01b8152306004820152600092508391506001600160a01b037f0000000000000000000000005f98805a4e8be255a32880fdec7f6728c6568ba016906370a0823190602401602060405180830381865afa158015612b29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b4d9190614ac6565b612b579190614b19565b9050612b6281613afd565b6000612b6d886145f2565b90508681108015612b9e57507f0000000000000000000000000000000000000000000000000de0b68e66a5c0008110155b611fd85760405162461bcd60e51b8152602060048201526064602482018190527f43424d3a2043757276652d3e5350207368696674206d75737420696e6372656160448301527f736520334352563a4c5553442065786368616e6765207261746520746f206120908201527f76616c75652061626f766520746865207769746864726177616c2074687265736084820152631a1bdb1960e21b60a482015260c401611d14565b600080612c4f61314d565b90506000612c5c826131e2565b50919695505050505050565b6000828152600860209081526040808320815160a08101835281548152600182015467ffffffffffffffff80821695830195909552600160401b8104851693820193909352600160801b83049093166060840152906080830190600160c01b900460ff166003811115612cdd57612cdd614ab0565b6003811115612cee57612cee614ab0565b9052509050612cfc83613568565b612d098160800151613651565b612d116136b2565b5060008381526008602052604081206001908101805467ffffffffffffffff4216600160801b0268ffffffffffffffffff60801b1990911617600160c11b179055546001600160a01b037f000000000000000000000000c96265c8748c8361d77fe99d42ae78aae63995a61690639841a0189033908790612db3907f00000000000000000000000000000000000000000000003635c9adc5dea0000090614a9c565b6040516001600160e01b031960e086901b1681526001600160a01b039093166004840152602483019190915260448201526064016020604051808303816000875af1158015612e06573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e2a9190614afe565b90506001600b6000828254612e3f9190614a4f565b90915550508151600080548190612e57908490614b19565b909155505060408201518251612e779167ffffffffffffffff1690614a67565b60056000828254612e889190614b19565b90915550508151600090612e9c9085614357565b9050612ea88133613972565b825160408051878152602081019290925281018590526060810182905269ffffffffffffffffffff8316608082015233907f3bd7a45d09d2d31d78737a80c00ac48ba89dd3cce7537ad56bf1bee66c9dc39e9060a00160405180910390a25050505050565b600080612f1e600d54600e5461330a565b5092915050565b6000807f00000000000000000000000020658291677a29efddfd0e303f8b23113d837cc76001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612f86573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612faa9190614ac6565b9050600080612fb8856131e2565b505050915091508260001415612fda5750670de0b6b3a7640000949350505050565b82612fe58284614a4f565b612ff790670de0b6b3a7640000614a67565b6114a49190614a9c565b6000818152600860209081526040808320815160a08101835281548152600182015467ffffffffffffffff80821695830195909552600160401b8104851693820193909352600160801b83049093166060840152839283928392839283929091906080830190600160c01b900460ff16600381111561308257613082614ab0565b600381111561309357613093614ab0565b8152505090508060000151816020015182604001518360600151846080015160038111156130c3576130c3614ab0565b939b929a50909850965090945092505050565b6130de61456e565b6130e6613a9c565b6009805460ff19166001908117909155546040519081527f6330fd496eb4822cdd507776770666698db359e48ce5a7797a0aaba0c879adca9060200160405180910390a16000600155565b60008061313c61314d565b905061314781612f25565b91505090565b6000807f0000000000000000000000009062d1477c3cd000301a471be03c9db85c3fc27a6001600160a01b031663bfca6c116040518163ffffffff1660e01b8152600401606060405180830381865afa1580156131ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131d29190614b30565b5091505061314760025482614748565b60008060008060008054866131f79190614b19565b92506132016117f1565b600154909250905060006132158385614a4f565b90508181111561325257600061322b8383614b19565b9050816132388683614a67565b6132429190614a9c565b965061324e8782614b19565b9550505b5091939590929450565b6000603c6006544261246c9190614b19565b6000631f54050082111561328457631f54050091505b816132985750670de0b6b3a76400006118ad565b670de0b6b3a764000083835b60018111156132e8576132b8600282614be4565b156132ca576132c78284614758565b92505b6132d48283614758565b91506132e1600282614a9c565b90506132a4565b610c3f8284614758565b60008183106133015781613303565b825b9392505050565b6000807f00000000000000000000000000000000000000000000000000000000000151806133587f00000000000000000000000000000000000000000000000000000000633bee1742614b19565b6133629190614a9c565b90508281148061339157507f00000000000000000000000000000000000000000000001146649c213f67800084145b8061339c5750600054155b156133a9578391506123cb565b600080546005546133ba9190614a9c565b9050600061343c7f00000000000000000000000000000000000000000000000000000000633bee1761340c7f000000000000000000000000000000000000000000000000000000000013c68085614a4f565b6134169190614b19565b7f0000000000000000000000000000000000000000000000000000000000015180614782565b9050808310156134505785935050506123cb565b600061346686613461600185614b19565b614748565b6134709085614b19565b90506134e2670de0b6b3a76400006134a87f0000000000000000000000000000000000000000000000000dbd2fc137a300008461326e565b6134b2908a614a67565b6134bc9190614a9c565b7f00000000000000000000000000000000000000000000001146649c213f678000614748565b94505050509250929050565b600080610d4d836137cd565b60008361350957506000613303565b60006135158542614b19565b61352790670de0b6b3a7640000614a67565b905060006135358483614a4f565b61353f8387614a67565b610c3f9190614a9c565b60008161355e84670de0b6b3a7640000614a67565b6133039190614a9c565b6040516331a9108f60e11b8152600481018290527f000000000000000000000000c96265c8748c8361d77fe99d42ae78aae63995a66001600160a01b031690636352211e90602401602060405180830381865afa1580156135cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135f19190614bf8565b6001600160a01b0316336001600160a01b0316146126a55760405162461bcd60e51b815260206004820152601d60248201527f43424d3a2043616c6c6572206d757374206f776e2074686520626f6e640000006044820152606401611d14565b600181600381111561366557613665614ab0565b146126a55760405162461bcd60e51b815260206004820152601860248201527f43424d3a20426f6e64206d7573742062652061637469766500000000000000006044820152606401611d14565b600d54600e546000919082806136c8848461330a565b9150915082811461193857600e81905581841461193857600d8290556040518281527fdf0b753b5dc9a250a9e6268e9c010c895cd12d6e66f6cfb57531a3a49315d09a9060200160405180910390a1509392505050565b60008060007f0000000000000000000000009062d1477c3cd000301a471be03c9db85c3fc27a6001600160a01b031663bfca6c116040518163ffffffff1660e01b8152600401606060405180830381865afa158015613782573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137a69190614b30565b506002549092509050808211156137c557506002819055928392509050565b939092509050565b600954600090819060ff16156137e557506000929050565b6000670de0b6b3a764000061381a7f000000000000000000000000000000000000000000000000006a94d74f43000086614a67565b6138249190614a9c565b905060006138328286614b19565b91959194509092505050565b600061386a7f000000000000000000000000000000000000000000000000000000000013c68085614a4f565b4210156138df5760405162461bcd60e51b815260206004820152603e60248201527f43424d3a20466972737420636869636b656e20696e206d75737420776169742060448201527f756e74696c20626f6f74737472617020706572696f64206973206f76657200006064820152608401611d14565b4260045560006138ee846131e2565b505050509050808310156139595760405162461bcd60e51b815260206004820152602c60248201527f43424d3a204e6f7420656e6f756768204c55534420617661696c61626c65206960448201526b1b88108b941c9bdd1bd8dbdb60a21b6064820152608401611d14565b80156139685761396881613a0d565b6114a48184614b19565b604051627b8a6760e11b8152600481018390526001600160a01b0382811660248301527f0000000000000000000000009062d1477c3cd000301a471be03c9db85c3fc27a169062f714ce90604401600060405180830381600087803b1580156139da57600080fd5b505af11580156139ee573d6000803e3d6000fd5b505050508160026000828254613a049190614b19565b90915550505050565b613a178130613972565b6126a5816147b4565b7f0000000000000000000000000000000000000000000000056bc75e2d631000008110156126a55760405162461bcd60e51b8152602060048201526024808201527f43424d3a20426f6e64206d696e696d756d20616d6f756e74206e6f742072656160448201526318da195960e21b6064820152608401611d14565b60095460ff1615613afb5760405162461bcd60e51b8152602060048201526024808201527f43424d3a204d6967726174696f6e206d757374206265206e6f742062652061636044820152637469766560e01b6064820152608401611d14565b565b60405163b6b55f2560e01b8152600481018290527f0000000000000000000000009062d1477c3cd000301a471be03c9db85c3fc27a6001600160a01b03169063b6b55f2590602401600060405180830381600087803b158015613b5f57600080fd5b505af1158015613b73573d6000803e3d6000fd5b505050508060026000828254613b899190614a4f565b909155505050565b7f00000000000000000000000000000000000000000000000000000000003b5380613bdc7f00000000000000000000000000000000000000000000000000000000633bee1742614b19565b1015613afb5760405162461bcd60e51b815260206004820152603c60248201527f43424d3a2053686966746572206f6e6c792063616c6c61626c6520616674657260448201527f20736869667420626f6f74737472617020706572696f6420656e6473000000006064820152608401611d14565b60007f00000000000000000000000020658291677a29efddfd0e303f8b23113d837cc76001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613cb0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cd49190614ac6565b11613afb5760405162461bcd60e51b815260206004820152602b60248201527f43424d3a20624c55534420537570706c79206d757374206265203e203020757060448201526a6f6e207368696674696e6760a81b6064820152608401611d14565b60007f0000000000000000000000000000000000000000000000000000000000000e10600c54613d659190614a4f565b90506000613d937f000000000000000000000000000000000000000000000000000000000000025883614a4f565b9050814210158015613da457508042105b613e165760405162461bcd60e51b815260206004820152602f60248201527f43424d3a205368696674206f6e6c7920706f737369626c6520696e736964652060448201527f7368696674696e672077696e646f7700000000000000000000000000000000006064820152608401611d14565b5050565b8060015410156126a55760405162461bcd60e51b8152602060048201526044602482018190527f43424d3a2054686520616d6f756e7420696e2043757276652063616e6e6f7420908201527f62652067726561746572207468616e20746865205065726d616e656e7420627560648201526318dad95d60e21b608482015260a401611d14565b600081116126a55760405162461bcd60e51b815260206004820152601760248201527f43424d3a20416d6f756e74206d757374206265203e20300000000000000000006044820152606401611d14565b604051635e0d443f60e01b815260006004820181905260016024830152670de0b6b3a764000060448301529081906001600160a01b037f000000000000000000000000ed279fdd11ca84beef15af5d39bb4d4bee23f0ca1690635e0d443f90606401602060405180830381865afa158015613f6f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f939190614ac6565b9050670de0b6b3a764000061355e8483614a67565b6040516370a0823160e01b81523060048201526000907f0000000000000000000000005fa5b62c8af877cb37031e0a3b2f34a78e3c56a66001600160a01b0316906370a0823190602401602060405180830381865afa15801561400f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140339190614ac6565b60405163b6b55f2560e01b8152600481018490529091507f0000000000000000000000005fa5b62c8af877cb37031e0a3b2f34a78e3c56a66001600160a01b03169063b6b55f25906024016020604051808303816000875af115801561409d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140c19190614ac6565b506040516370a0823160e01b815230600482015260009082906001600160a01b037f0000000000000000000000005fa5b62c8af877cb37031e0a3b2f34a78e3c56a616906370a0823190602401602060405180830381865afa15801561412b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061414f9190614ac6565b6141599190614b19565b9050806003600082825461416d9190614a4f565b9091555050505050565b60095460ff166126a5577f00000000000000000000000020658291677a29efddfd0e303f8b23113d837cc76001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156141df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142039190614ac6565b61422d7f0000000000000000000000000000000000000000000000000de0b6b3a764000083614a4f565b11156126a55760405162461bcd60e51b815260206004820152602360248201527f43424d3a2043616e6e6f742072656465656d2062656c6f77206d696e20737570604482015262706c7960e81b6064820152608401611d14565b60008060008060008061429861371f565b5090506142a4816131e2565b95509550955095509550509091929394565b6000806142c283610b95565b60078190556040518181529091507fe31dea26c34fb8440bf2eec033dfd26bd39e88e026348d996e275a396417109b9060200160405180910390a160006006544261430d9190614b19565b9050603c8110612f1e574260068190556040519081527fbab964312bdd13595266f3e549bca3102965a6d718c6c1f8cd7eaac076b9c6c29060200160405180910390a15092915050565b6000818310156143cf5760405162461bcd60e51b815260206004820152603460248201527f43424d3a204d696e2076616c75652063616e6e6f74206265206772656174657260448201527f207468616e206e6f6d696e616c20616d6f756e740000000000000000000000006064820152608401611d14565b60007f0000000000000000000000009062d1477c3cd000301a471be03c9db85c3fc27a6001600160a01b031663bfca6c116040518163ffffffff1660e01b8152600401606060405180830381865afa15801561442f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144539190614b30565b50915050828110156144bc5760405162461bcd60e51b815260206004820152602c60248201527f43424d3a204e6f7420656e6f756768204c55534420617661696c61626c65206960448201526b1b88108b941c9bdd1bd8dbdb60a21b6064820152608401611d14565b60006114a485836132f2565b60405163a9059cbb60e01b81526001600160a01b038381166004830152602482018390527f0000000000000000000000005fa5b62c8af877cb37031e0a3b2f34a78e3c56a6169063a9059cbb906044016020604051808303816000875af1158015614537573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061455b9190614b8a565b508060036000828254613a049190614b19565b336001600160a01b037f000000000000000000000000feb4acf3df3cdea7399794d0869ef76a6efaff521614613afb5760405162461bcd60e51b815260206004820152602360248201527f43424d3a204f6e6c7920596561726e20476f7665726e616e63652063616e2063604482015262185b1b60ea1b6064820152608401611d14565b604051635e0d443f60e01b815260016004820152600060248201819052670de0b6b3a764000060448301529081906001600160a01b037f000000000000000000000000ed279fdd11ca84beef15af5d39bb4d4bee23f0ca1690635e0d443f90606401602060405180830381865afa158015614671573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146959190614ac6565b90508261355e82670de0b6b3a7640000614a67565b604051632e1a7d4d60e01b8152600481018290527f0000000000000000000000005fa5b62c8af877cb37031e0a3b2f34a78e3c56a66001600160a01b031690632e1a7d4d906024016020604051808303816000875af1158015614711573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147359190614ac6565b508060036000828254613b899190614b19565b6000818310156133015781613303565b6000670de0b6b3a764000061476e600282614a9c565b6147788486614a67565b61355e9190614a4f565b600061478e8284614be4565b1561479a57600161479d565b60005b60ff166147aa8385614a9c565b6133039190614a4f565b6040516370a0823160e01b81523060048201526000907f0000000000000000000000005f98805a4e8be255a32880fdec7f6728c6568ba06001600160a01b0316906370a0823190602401602060405180830381865afa15801561481b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061483f9190614ac6565b6040516393f7aa6760e01b81526001600160a01b037f0000000000000000000000005f98805a4e8be255a32880fdec7f6728c6568ba081166004830152602482018590529192507f000000000000000000000000009644832140fed8b3b2b40405612f0c06ab3917909116906393f7aa6790604401600060405180830381600087803b1580156148ce57600080fd5b505af11580156148e2573d6000803e3d6000fd5b50506040516370a0823160e01b81523060048201528492507f0000000000000000000000005f98805a4e8be255a32880fdec7f6728c6568ba06001600160a01b031691506370a0823190602401602060405180830381865afa15801561494c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906149709190614ac6565b61497a9083614b19565b14613e1657613e16614c15565b60006020828403121561499957600080fd5b5035919050565b6001600160a01b03811681146126a557600080fd5b60008060008060008060c087890312156149ce57600080fd5b86356149d9816149a0565b95506020870135945060408701359350606087013560ff811681146149fd57600080fd5b9598949750929560808101359460a0909101359350915050565b60008060408385031215614a2a57600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b60008219821115614a6257614a62614a39565b500190565b6000816000190483118215151615614a8157614a81614a39565b500290565b634e487b7160e01b600052601260045260246000fd5b600082614aab57614aab614a86565b500490565b634e487b7160e01b600052602160045260246000fd5b600060208284031215614ad857600080fd5b5051919050565b805169ffffffffffffffffffff81168114614af957600080fd5b919050565b600060208284031215614b1057600080fd5b61330382614adf565b600082821015614b2b57614b2b614a39565b500390565b600080600060608486031215614b4557600080fd5b8351925060208401519150604084015190509250925092565b60008060408385031215614b7157600080fd5b82519150614b8160208401614adf565b90509250929050565b600060208284031215614b9c57600080fd5b8151801515811461330357600080fd5b60608101818460005b6002811015614bd4578151835260209283019290910190600101614bb5565b5050508260408301529392505050565b600082614bf357614bf3614a86565b500690565b600060208284031215614c0a57600080fd5b8151613303816149a0565b634e487b7160e01b600052600160045260246000fdfea2646970667358221220d50cb42b3fa172de0f06883778cf4e6e0328c7e338330d8671e5c083cbaed28a64736f6c634300080b0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000c96265c8748c8361d77fe99d42ae78aae63995a60000000000000000000000005f98805a4e8be255a32880fdec7f6728c6568ba0000000000000000000000000ed279fdd11ca84beef15af5d39bb4d4bee23f0ca000000000000000000000000bebc44782c7db0a1a60cb6fe97d0b483032ff1c70000000000000000000000009062d1477c3cd000301a471be03c9db85c3fc27a0000000000000000000000005fa5b62c8af877cb37031e0a3b2f34a78e3c56a600000000000000000000000050c1a2ea0a861a967d9d0ffe2ae4012c2e053804000000000000000000000000feb4acf3df3cdea7399794d0869ef76a6efaff5200000000000000000000000020658291677a29efddfd0e303f8b23113d837cc7000000000000000000000000009644832140fed8b3b2b40405612f0c06ab3917000000000000000000000000000000000000000000000000000000000013c68000000000000000000000000000000000000000000000437af901e1dfac4c000000000000000000000000000000000000000000000000001146649c213f678000000000000000000000000000000000000000000000000000002386f26fc100000000000000000000000000000000000000000000000000000000000000015180000000000000000000000000000000000000000000000000006a94d74f4300000000000000000000000000000000000000000000000000000de2227fe94d00000000000000000000000000000000000000000000000000000de2227fe94d0000000000000000000000000000000000000000000000000000000000000013c680000000000000000000000000000000000000000000000000000000000013c68000000000000000000000000000000000000000000000000000000000003b53800000000000000000000000000000000000000000000000000000000000000e1000000000000000000000000000000000000000000000000000000000000002580000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000056bc75e2d6310000000000000000000000000000000000000000000000000003635c9adc5dea00000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _externalContractAddresses (tuple): System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput]
Arg [1] : _params (tuple): System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput]
-----Encoded View---------------
28 Constructor Arguments found :
Arg [0] : 000000000000000000000000c96265c8748c8361d77fe99d42ae78aae63995a6
Arg [1] : 0000000000000000000000005f98805a4e8be255a32880fdec7f6728c6568ba0
Arg [2] : 000000000000000000000000ed279fdd11ca84beef15af5d39bb4d4bee23f0ca
Arg [3] : 000000000000000000000000bebc44782c7db0a1a60cb6fe97d0b483032ff1c7
Arg [4] : 0000000000000000000000009062d1477c3cd000301a471be03c9db85c3fc27a
Arg [5] : 0000000000000000000000005fa5b62c8af877cb37031e0a3b2f34a78e3c56a6
Arg [6] : 00000000000000000000000050c1a2ea0a861a967d9d0ffe2ae4012c2e053804
Arg [7] : 000000000000000000000000feb4acf3df3cdea7399794d0869ef76a6efaff52
Arg [8] : 00000000000000000000000020658291677a29efddfd0e303f8b23113d837cc7
Arg [9] : 000000000000000000000000009644832140fed8b3b2b40405612f0c06ab3917
Arg [10] : 000000000000000000000000000000000000000000000000000000000013c680
Arg [11] : 00000000000000000000000000000000000000000000437af901e1dfac4c0000
Arg [12] : 00000000000000000000000000000000000000000000001146649c213f678000
Arg [13] : 000000000000000000000000000000000000000000000000002386f26fc10000
Arg [14] : 0000000000000000000000000000000000000000000000000000000000015180
Arg [15] : 000000000000000000000000000000000000000000000000006a94d74f430000
Arg [16] : 0000000000000000000000000000000000000000000000000de2227fe94d0000
Arg [17] : 0000000000000000000000000000000000000000000000000de2227fe94d0000
Arg [18] : 000000000000000000000000000000000000000000000000000000000013c680
Arg [19] : 000000000000000000000000000000000000000000000000000000000013c680
Arg [20] : 00000000000000000000000000000000000000000000000000000000003b5380
Arg [21] : 0000000000000000000000000000000000000000000000000000000000000e10
Arg [22] : 0000000000000000000000000000000000000000000000000000000000000258
Arg [23] : 0000000000000000000000000000000000000000000000000de0b6b3a7640000
Arg [24] : 0000000000000000000000000000000000000000000000056bc75e2d63100000
Arg [25] : 00000000000000000000000000000000000000000000003635c9adc5dea00000
Arg [26] : ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
Arg [27] : 0000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode Sourcemap
22654:57812:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;31030:55;;;;;;;;160:25:1;;;148:2;133:18;31030:55:0;;;;;;;;29805:29;;;;;23321:59;;;;;;;;-1:-1:-1;;;;;391:55:1;;;373:74;;361:2;346:18;23321:59:0;196:257:1;27888:21:0;;;;;;;;;;;;623:14:1;;616:22;598:41;;586:2;571:18;27888:21:0;458:187:1;22947:37:0;;;;;30556:48;;;;;27918:29;;;;;;23142:34;;;;;23802:31;;;;;;76911:288;;;:::i;28467:47::-;;;;;60230:802;;;;;;:::i;:::-;;:::i;77869:231::-;;;:::i;22814:39::-;;;;;77738:99;77816:13;;77738:99;;23445:43;;;;;79802:497;;;:::i;:::-;;;;1780:25:1;;;1836:2;1821:18;;1814:34;;;;1864:18;;;1857:34;1768:2;1753:18;79802:497:0;1578:319:1;72721:394:0;;;;;;:::i;:::-;;:::i;73703:299::-;;;;;;:::i;:::-;;:::i;28264:52::-;;;;;42233:3375;;;;;;:::i;:::-;;:::i;:::-;;73123:572;;;;;;:::i;:::-;;:::i;28815:41::-;;;;;28359:48;;;;;29531:47;;;;;26971:38;;;;;;28205:50;;28253:2;28205:50;;36583:1049;;;;;;:::i;:::-;;:::i;23389:47::-;;;;;78108:240;;;:::i;74855:414::-;;;:::i;28595:38::-;;;;;74010:179;;;:::i;37640:497::-;;;;;;:::i;:::-;;:::i;28687:39::-;;;;;80307:156;;;:::i;48811:3052::-;;;;;;:::i;:::-;;:::i;45616:3187::-;;;;;;:::i;:::-;;:::i;:::-;;;;3411:25:1;;;3467:2;3452:18;;3445:34;;;;3384:18;45616:3187:0;3237:248:1;74337:159:0;;;:::i;58160:391::-;;;:::i;75302:95::-;75351:7;75378:11;75302:95;;26867:33;;;;;;74604:243;;;:::i;79697:97::-;79774:12;;79697:97;;28944:40;;;;;4093:45;;4134:4;4093:45;;58587:383;;;;;;:::i;:::-;;:::i;27200:33::-;;;;;;23068:41;;;;;77207:239;;;:::i;29992:66::-;;;;;51871:2993;;;;;;:::i;:::-;;:::i;22772:33::-;;;;;30065:69;;;;;77454:249;;;:::i;22860:37::-;;;;;23269:45;;;;;30378:44;;;;;28076:60;;28135:1;28076:60;;;;;4414:2:1;4403:22;;;;4385:41;;4373:2;4358:18;28076:60:0;4241:191:1;38145:1422:0;;;;;;:::i;:::-;;:::i;30683:48::-;;;;;79444:245;;;:::i;78591:845::-;;;;;;:::i;:::-;;:::i;29841:44::-;;;;;31206:31;;;;;;23218:44;;;;;30205;;;;;;72288:425;;;;;;:::i;:::-;;:::i;:::-;;;;4936:25:1;;;4980:18;5034:15;;;5029:2;5014:18;;5007:43;5086:15;;;5066:18;;;5059:43;;;;5138:15;;;5133:2;5118:18;;5111:43;5203:4;5191:17;5185:3;5170:19;;5163:46;4923:3;4908:19;72288:425:0;4687:528:1;27118:33:0;;;;;;57752:356;;;:::i;27954:30::-;;;;;;30847:52;;;;;78380:203;;;:::i;31644:43::-;;;;;;76911:288;76964:7;76984:21;77008:27;:25;:27::i;:::-;76984:51;;77047:24;77073:27;77107:28;77121:13;77107;:28::i;:::-;77046:89;;;;;;;77172:19;77153:16;:38;;;;:::i;:::-;77146:45;;;;;76911:288;:::o;60230:802::-;60322:7;60342:21;60366:35;:33;:35::i;:::-;60342:59;;60412:19;60434:42;60441:19;60462:13;60434:6;:42::i;:::-;60412:64;;60489:33;4134:4;60546:11;60525:18;;:32;;;;:::i;:::-;:52;;;;:::i;:::-;60489:88;-1:-1:-1;60661:29:0;60721:31;60748:4;60721:24;:31;:::i;:::-;60693:59;;:25;:59;:::i;:::-;60661:91;;60787:50;60796:21;4134:4;60787:8;:50::i;:::-;60763:74;60230:802;-1:-1:-1;;;;;;60230:802:0:o;77869:231::-;77920:7;77940:21;77964:27;:25;:27::i;:::-;77940:51;;78006:21;78033:28;78047:13;78033;:28::i;:::-;-1:-1:-1;78002:59:0;;77869:231;-1:-1:-1;;;;;;77869:231:0:o;79802:497::-;80044:20;80185:11;;;80044:20;80228:22;:20;:22::i;:::-;80207:43;;80278:13;;80261:30;;79802:497;;;:::o;72721:394::-;72787:7;72830:21;;;:12;:21;;;;;;;;72807:44;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;72807:44:0;;;;;;;;;;;-1:-1:-1;;;72807:44:0;;;;;;;;;72787:7;;72807:44;;;;;-1:-1:-1;;;72807:44:0;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;72865:31;72902:76;72931:16;;72949:28;;72902;:76::i;:::-;72864:114;;;72998:109;73017:4;:14;;;72998:109;;73033:48;73065:4;:15;;;73033:31;:48::i;:::-;73083:23;72998:18;:109::i;:::-;72991:116;72721:394;-1:-1:-1;;;;72721:394:0:o;73703:299::-;73769:7;73789:20;73812:24;:22;:24::i;:::-;73849:20;73872:21;;;:12;:21;;;;;;;;73849:44;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;73849:44:0;;;;;;;;;;;-1:-1:-1;;;73849:44:0;;;;;;;;;73789:47;;-1:-1:-1;73849:20:0;;:44;;;;;;-1:-1:-1;;;73849:44:0;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;73913:81;73931:48;73963:4;:15;;;73931:31;:48::i;:::-;73981:12;73913:17;:81::i;42233:3375::-;42289:20;42312:21;;;:12;:21;;;;;;;;42289:44;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;42289:44:0;;;;;;;;;;;-1:-1:-1;;;42289:44:0;;;;;;;;;42312:21;42289:44;;;;-1:-1:-1;;;42289:44:0;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;-1:-1:-1;42289:44:0;-1:-1:-1;42346:31:0;42369:7;42346:22;:31::i;:::-;42388:33;42409:4;:11;;;42388:20;:33::i;:::-;42434:31;42468:25;:23;:25::i;:::-;42434:59;;42505:21;42528:25;42557:17;:15;:17::i;:::-;42504:70;;;;42588:26;42616:35;42655:48;42687:4;:15;;;42655:31;:48::i;:::-;42587:116;;;;43032:10;-1:-1:-1;;;;;43032:22:0;;:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:29;:43;;;;-1:-1:-1;43066:9:0;;;;43065:10;43032:43;43028:161;;;43112:65;43128:4;:14;;;43112:65;;43144:13;43159:17;43112:15;:65::i;:::-;43092:85;;43028:161;43344:21;43368:88;43387:4;:14;;;43368:88;;43403:27;43432:23;43368:18;:88::i;:::-;43344:112;;43515:20;43538:51;43575:13;43538:36;:51::i;:::-;43515:74;-1:-1:-1;43600:20:0;43515:74;43623:20;:13;43639:4;43623:20;:::i;:::-;:35;;;;:::i;:::-;43600:58;-1:-1:-1;43715:47:0;43724:19;43739:4;43600:58;43724:19;:::i;:::-;43745:16;43715:8;:47::i;:::-;43671:21;;;;:12;:21;;;;;:34;;;;:92;;;;;;43797:53;;;;;-1:-1:-1;;;43797:53:0;-1:-1:-1;;;;43861:55:0;-1:-1:-1;;;43900:15:0;43861:55;;;;;;;;;;;;;;;43990:13;;43943:7;-1:-1:-1;;;;;43943:25:0;;;;43969:10;;43671:21;;43990:38;;44006:22;;43990:38;:::i;:::-;43943:86;;-1:-1:-1;;;;;;43943:86:0;;;;;;;-1:-1:-1;;;;;6456:55:1;;;43943:86:0;;;6438:74:1;6528:18;;;6521:34;;;;6571:18;;;6564:34;6411:18;;43943:86:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;43927:102;;44060:1;44042:14;;:19;;;;;;;:::i;:::-;;;;-1:-1:-1;;44206:15:0;;;44191:30;;44206:15;;44191:30;;44206:15;;44191:30;:::i;:::-;;;;-1:-1:-1;;44277:14:0;;;;44259:15;;:32;;;;;;:::i;:::-;44232:23;;:59;;;;;;;:::i;:::-;;;;-1:-1:-1;44388:19:0;;-1:-1:-1;44410:43:0;44440:13;44410:27;:43;:::i;:::-;44528:9;;44388:65;;-1:-1:-1;44528:9:0;;44523:608;;44712:11;44695:13;;:28;;;;;;;:::i;:::-;;;;-1:-1:-1;44523:608:0;;-1:-1:-1;44523:608:0;;44931:11;-1:-1:-1;;;;;44931:24:0;;:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;44907:50:0;-1:-1:-1;44972:20:0;;-1:-1:-1;44995:40:0;45004:11;44907:50;44995:8;:40::i;:::-;44972:63;-1:-1:-1;45054:16:0;;45050:70;;45074:43;45092:12;45106:10;45074:17;:43::i;:::-;44741:390;44523:608;45143:41;;-1:-1:-1;;;45143:41:0;;45159:10;45143:41;;;7619:74:1;7709:18;;;7702:34;;;45143:10:0;-1:-1:-1;;;;;45143:15:0;;;;7592:18:1;;45143:41:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;45312:9:0;;;;45311:10;;-1:-1:-1;;45311:53:0;;;;;45346:18;45325:17;:39;;45311:53;45307:161;;;45381:75;45437:18;45381:55;:75::i;:::-;45518:15;;45582:9;;45485:115;;;8054:25:1;;;8110:2;8095:18;;8088:34;;;;8138:18;;8131:34;;;8196:2;8181:18;;8174:34;;;8239:3;8224:19;;8217:35;;;45582:9:0;;8296:14:1;8289:22;8283:3;8268:19;;8261:51;8361:22;8349:35;;8343:3;8328:19;;8321:64;45497:10:0;;45485:115;;8041:3:1;8026:19;45485:115:0;;;;;;;42278:3330;;;;;;;;;;;42233:3375;:::o;73123:572::-;73189:7;73232:21;;;:12;:21;;;;;;;;73209:44;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;73209:44:0;;;;;;;;;;;-1:-1:-1;;;73209:44:0;;;;;;;;;73189:7;;73209:44;;;;;-1:-1:-1;;;73209:44:0;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;-1:-1:-1;73209:44:0;-1:-1:-1;73285:17:0;73270:4;:11;;;:32;;;;;;;;:::i;:::-;;73266:73;;-1:-1:-1;73326:1:0;;73123:572;-1:-1:-1;;73123:572:0:o;73266:73::-;73351:20;73374:93;73392:48;73424:4;:15;;;73392:31;:48::i;:::-;73442:24;:22;:24::i;:::-;73374:17;:93::i;:::-;73351:116;;73481:31;73518:76;73547:16;;73565:28;;73518;:76::i;:::-;73480:114;;;73614:73;73633:4;:14;;;73614:73;;73649:12;73663:23;73614:18;:73::i;:::-;73607:80;73123:572;-1:-1:-1;;;;;73123:572:0:o;36583:1049::-;36640:7;36660:28;36676:11;36660:15;:28::i;:::-;36699;:26;:28::i;:::-;36740:25;:23;:25::i;:::-;;36843:14;36859:21;36884:7;-1:-1:-1;;;;;36884:12:0;;36897:10;36925:22;36909:13;;:38;;;;:::i;:::-;36884:64;;-1:-1:-1;;;;;;36884:64:0;;;;;;;-1:-1:-1;;;;;7637:55:1;;;36884:64:0;;;7619:74:1;7709:18;;;7702:34;7592:18;;36884:64:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;36842:106;;;;37030:24;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;37030:24:0;37065:33;;;37137:15;37109:44;;:18;;;:44;37182:17;37164:15;;;37182:17;37164:35;;-1:-1:-1;37210:20:0;;;;:12;:20;;;;;;;;;:31;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;37210:31:0;-1:-1:-1;;;;37210:31:0;;;-1:-1:-1;;;37210:31:0;-1:-1:-1;;37210:31:0;;;;;;;;;;;;;;;;;;;;;;;37233:8;;37210:31;;-1:-1:-1;;;;37210:31:0;-1:-1:-1;;;;37210:31:0;;;;-1:-1:-1;;;37210:31:0;;;;;;;;;:::i;:::-;;;;;;;;;37269:11;37254;;:26;;;;;;;:::i;:::-;;;;-1:-1:-1;37318:29:0;;-1:-1:-1;37332:15:0;37318:11;:29;:::i;:::-;37291:23;;:56;;;;;;;:::i;:::-;;;;-1:-1:-1;;37360:62:0;;-1:-1:-1;;;37360:62:0;;37383:10;37360:62;;;8931:34:1;37403:4:0;8981:18:1;;;8974:43;9033:18;;;9026:34;;;37360:9:0;-1:-1:-1;;;;;37360:22:0;;;;8843:18:1;;37360:62:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;37493:27;37508:11;37493:14;:27::i;:::-;37538:60;;;9553:25:1;;;9609:2;9594:18;;9587:34;;;9669:22;9657:35;;9637:18;;;9630:63;37538:60:0;;37550:10;;37538:60;;;;;;9541:2:1;37538:60:0;;;-1:-1:-1;37618:6:0;;36583:1049;-1:-1:-1;;;36583:1049:0:o;78108:240::-;78162:7;78182:21;78206:27;:25;:27::i;:::-;78182:51;;78249:24;78278:28;78292:13;78278;:28::i;:::-;-1:-1:-1;78244:62:0;78108:240;-1:-1:-1;;;;;;78108:240:0:o;74855:414::-;74907:7;74927:23;74953:36;:34;:36::i;:::-;74927:62;-1:-1:-1;75000:24:0;75039:19;;75035:191;;75075:28;75106:9;-1:-1:-1;;;;;75106:27:0;;:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;75075:60;-1:-1:-1;75210:4:0;75169:38;75075:60;75169:15;:38;:::i;:::-;:45;;;;:::i;:::-;75150:64;;75060:166;75035:191;75245:16;74855:414;-1:-1:-1;;74855:414:0:o;74010:179::-;74065:7;74088:25;74118:11;-1:-1:-1;;;;;74118:24:0;;:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;74085:59:0;74010:179;-1:-1:-1;;;74010:179:0:o;37640:497::-;37950:41;;-1:-1:-1;;;37950:41:0;;-1:-1:-1;;;;;9957:15:1;;;37950:41:0;;;9939:34:1;37985:4:0;9989:18:1;;;9982:43;37834:7:0;;37994:6;;37950:9;:19;;;;9851:18:1;;37950:41:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:50;37946:148;;;38017:65;;-1:-1:-1;;;38017:65:0;;-1:-1:-1;;;;;10426:15:1;;;38017:65:0;;;10408:34:1;38049:4:0;10458:18:1;;;10451:43;10510:18;;;10503:34;;;10553:18;;;10546:34;;;10629:4;10617:17;;10596:19;;;10589:46;10651:19;;;10644:35;;;10695:19;;;10688:35;;;38017:9:0;:16;;;;10319:19:1;;38017:65:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;37946:148;38111:18;38122:6;38111:10;:18::i;:::-;38104:25;37640:497;-1:-1:-1;;;;;;;37640:497:0:o;80307:156::-;80358:21;80440:15;;80423:14;;80399:7;-1:-1:-1;;;;;80399:19:0;;:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:38;;;;:::i;:::-;:56;;;;:::i;:::-;80392:63;;80307:156;:::o;48811:3052::-;48888:35;:33;:35::i;:::-;48934:28;:26;:28::i;:::-;48973;:26;:28::i;:::-;49012:27;:25;:27::i;:::-;49053:21;49076:25;49105:17;:15;:17::i;:::-;49052:70;;;;49133:30;49182:11;;49166:13;:27;;;;:::i;:::-;49133:60;;49206:24;49233:21;:19;:21::i;:::-;49206:48;;49338:51;49372:16;49338:33;:51::i;:::-;49500:26;49529:49;49538:15;49555:22;49529:8;:49::i;:::-;49500:78;;49680:47;49689:18;49709:17;49680:8;:47::i;:::-;49659:68;;49930:62;49939:18;49975:16;49959:13;;:32;;;;:::i;:::-;49930:8;:62::i;:::-;49909:83;;50005:41;50027:18;50005:21;:41::i;:::-;50241:25;50269:13;-1:-1:-1;;;;;50269:31:0;;:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;50241:61;;50313:27;50343:43;50368:17;50343:24;:43::i;:::-;50313:73;;50443:41;50421:19;:63;50399:199;;;;-1:-1:-1;;;50399:199:0;;10936:2:1;50399:199:0;;;10918:21:1;10975:2;10955:18;;;10948:30;11014:34;10994:18;;;10987:62;11085:34;11065:18;;;11058:62;11157:24;11136:19;;;11129:53;11199:19;;50399:199:0;;;;;;;;;50653:52;50671:18;50699:4;50653:17;:52::i;:::-;50829:34;;-1:-1:-1;;;50829:34:0;;50857:4;50829:34;;;373:74:1;50797:29:0;;50829:9;-1:-1:-1;;;;;50829:19:0;;;;346:18:1;;50829:34:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;51093:51;;;;;;;;;;;-1:-1:-1;51093:51:0;;;;;;;;-1:-1:-1;;;51093:51:0;;50797:66;;-1:-1:-1;;;;;;51093:9:0;:23;;;;:51;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;51186:34:0;;-1:-1:-1;;;51186:34:0;;51214:4;51186:34;;;373:74:1;51155:28:0;;51223:21;;-1:-1:-1;;;;;51186:9:0;:19;;;;346:18:1;;51186:34:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:58;;;;:::i;:::-;51155:89;;51322:37;51338:20;51322:15;:37::i;:::-;51506:25;51534:43;51559:17;51534:24;:43::i;:::-;51506:71;;51632:19;51612:17;:39;:118;;;;;51689:41;51668:17;:62;;51612:118;51590:265;;;;-1:-1:-1;;;51590:265:0;;12009:2:1;51590:265:0;;;11991:21:1;12048:2;12028:18;;;12021:30;12087:34;12067:18;;;12060:62;12158:34;12138:18;;;12131:62;12230:34;12209:19;;;12202:63;-1:-1:-1;;;12281:19:1;;;12274:32;12323:19;;51590:265:0;11807:541:1;51590:265:0;48877:2986;;;;;;;;;;48811:3052;:::o;45616:3187::-;45707:7;45716;45736:37;45758:14;45736:21;:37::i;:::-;45784:51;45820:14;45784:35;:51::i;:::-;45896:23;45875:18;;:44;;;;:::i;:::-;45856:15;:63;;45848:155;;;;-1:-1:-1;;;45848:155:0;;12555:2:1;45848:155:0;;;12537:21:1;12594:2;12574:18;;;12567:30;12633:34;12613:18;;;12606:62;12704:34;12684:18;;;12677:62;12776:17;12755:19;;;12748:46;12811:19;;45848:155:0;12353:483:1;45848:155:0;46031:24;46070:27;46154:24;46193:27;46234:36;:34;:36::i;:::-;46016:254;;;;;;;;;46283:31;46341:10;-1:-1:-1;;;;;46341:22:0;;:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;46317:21;:14;46334:4;46317:21;:::i;:::-;:48;;;;:::i;:::-;46474:9;;46283:82;;-1:-1:-1;46440:31:0;;46474:9;;:71;;46490:55;46521:23;46490:30;:55::i;:::-;46474:71;;;46486:1;46474:71;46440:105;-1:-1:-1;46626:25:0;;;47095:4;47050:42;47069:23;47050:16;:42;:::i;:::-;:49;;;;:::i;:::-;47015:84;-1:-1:-1;47114:34:0;47213:4;47179:30;47186:23;47213:4;47179:30;:::i;:::-;47151:59;;:24;:59;:::i;:::-;:66;;;;:::i;:::-;47114:103;-1:-1:-1;47253:53:0;47114:103;47253:24;:53;:::i;:::-;47232:74;;;;:::i;:::-;;;47344:77;47369:26;47397:23;47344:24;:77::i;:::-;47321:100;-1:-1:-1;47440:24:0;;47436:86;;47468:51;47486:20;47508:10;47468:17;:51::i;:::-;-1:-1:-1;47659:29:0;;-1:-1:-1;47703:20:0;;47699:553;;47740:35;47826:4;47778:45;47800:23;47778:19;:45;:::i;:::-;:52;;;;:::i;:::-;47740:90;-1:-1:-1;47845:31:0;47944:4;47910:30;47917:23;47944:4;47910:30;:::i;:::-;47879:62;;:27;:62;:::i;:::-;:69;;;;:::i;:::-;47845:103;-1:-1:-1;47984:53:0;47845:103;47984:27;:53;:::i;:::-;47963:74;;;;:::i;:::-;;;48121:16;48095:23;48076:16;;:42;;;;:::i;:::-;:61;;;;:::i;:::-;48052:85;-1:-1:-1;48156:25:0;;48152:89;;48185:53;48204:10;48216:21;48185:18;:53::i;:::-;47725:527;;47699:553;48371:39;48393:17;48371:19;:39;:::i;:::-;48355:13;:55;48423:67;48445:44;48468:21;48445:20;:44;:::i;:::-;48423:21;:67::i;:::-;48539:43;;-1:-1:-1;;;48539:43:0;;48555:10;48539:43;;;7619:74:1;7709:18;;;7702:34;;;-1:-1:-1;;;;;48539:10:0;:15;;;;7592:18:1;;48539:43:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;48614:10;-1:-1:-1;;;;;48600:130:0;;48626:14;48642:23;48667:20;48689:21;48712:17;48600:130;;;;;;;;;13100:25:1;;;13156:2;13141:18;;13134:34;;;;13199:2;13184:18;;13177:34;;;;13242:2;13227:18;;13220:34;13285:3;13270:19;;13263:35;13087:3;13072:19;;12841:463;48600:130:0;;;;;;;;48751:20;;-1:-1:-1;48773:21:0;-1:-1:-1;;;;;;;;45616:3187:0;;;;;;:::o;74337:159::-;74404:7;74484:4;74450:15;-1:-1:-1;;;;;74450:29:0;;:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;74431:16;;:50;;;;:::i;:::-;:57;;;;:::i;58160:391::-;58366:14;58350:13;58318:29;;:45;;;;:::i;:::-;:62;;;;:::i;:::-;58299:15;:81;;58291:147;;;;-1:-1:-1;;;58291:147:0;;13511:2:1;58291:147:0;;;13493:21:1;13550:2;13530:18;;;13523:30;13589:34;13569:18;;;13562:62;13660:23;13640:18;;;13633:51;13701:19;;58291:147:0;13309:417:1;58291:147:0;58528:15;58496:29;:47;58160:391::o;74604:243::-;74657:7;74677:24;74704:21;:19;:21::i;:::-;74677:48;;74736:21;74760:27;:25;:27::i;:::-;74736:51;-1:-1:-1;74807:32:0;74823:16;74736:51;74807:32;:::i;:::-;74800:39;;;;74604:243;:::o;58587:383::-;58650:33;:31;:33::i;:::-;58703:9;;;;58702:10;58694:65;;;;-1:-1:-1;;;58694:65:0;;13933:2:1;58694:65:0;;;13915:21:1;13972:2;13952:18;;;13945:30;14011:34;13991:18;;;13984:62;-1:-1:-1;;;14062:18:1;;;14055:40;14112:19;;58694:65:0;13731:406:1;58694:65:0;58850:74;;-1:-1:-1;;;58850:74:0;;-1:-1:-1;;;;;58873:22:0;8949:15:1;;58850:74:0;;;8931:34:1;58905:4:0;8981:18:1;;;8974:43;9033:18;;;9026:34;;;58850:9:0;:22;;;;8843:18:1;;58850:74:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;58935:27;58950:11;58935:14;:27::i;:::-;58587:383;:::o;77207:239::-;77261:7;77281:21;77305:27;:25;:27::i;:::-;77281:51;;77344:24;77376:28;77390:13;77376;:28::i;:::-;-1:-1:-1;77343:61:0;;77207:239;-1:-1:-1;;;;;;77207:239:0:o;51871:2993::-;51948:35;:33;:35::i;:::-;51994:28;:26;:28::i;:::-;52033;:26;:28::i;:::-;52072:27;:25;:27::i;:::-;52169:24;52196:21;:19;:21::i;:::-;52169:48;;52228:26;52257:43;52266:15;52283:16;52257:8;:43::i;:::-;52228:72;;52311:41;52333:18;52311:21;:41::i;:::-;52551:25;52579:13;-1:-1:-1;;;;;52579:31:0;;:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;52551:61;;52623:27;52653:43;52678:17;52653:24;:43::i;:::-;52623:73;;52949:44;52927:19;:66;52905:206;;;;-1:-1:-1;;;52905:206:0;;14344:2:1;52905:206:0;;;14326:21:1;14383:2;14363:18;;;14356:30;14422:34;14402:18;;;14395:62;14493:34;14473:18;;;14466:62;14565:28;14544:19;;;14537:57;14611:19;;52905:206:0;14142:494:1;52905:206:0;53198:34;;-1:-1:-1;;;53198:34:0;;53226:4;53198:34;;;373:74:1;53166:29:0;;53198:9;-1:-1:-1;;;;;53198:19:0;;;;346:18:1;;53198:34:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;53166:66;;53331:35;53409:16;53388:18;53369:16;;:37;;;;:::i;:::-;:56;;;;:::i;:::-;53331:94;;53436:47;53455:27;53436:18;:47::i;:::-;53525:34;;-1:-1:-1;;;53525:34:0;;53553:4;53525:34;;;373:74:1;53494:28:0;;53562:21;;-1:-1:-1;;;;;53525:9:0;:19;;;;346:18:1;;53525:34:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:58;;;;:::i;:::-;53661:34;;-1:-1:-1;;;53661:34:0;;53689:4;53661:34;;;373:74:1;53494:89:0;;-1:-1:-1;53633:25:0;;-1:-1:-1;;;;;53661:9:0;:19;;;;346:18:1;;53661:34:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;53920:95;;-1:-1:-1;;;53920:95:0;;;;;14849:25:1;;;28135:1:0;14890:18:1;;;14883:50;;;14949:18;;;14942:34;53633:62:0;;-1:-1:-1;53920:9:0;-1:-1:-1;;;;;53920:35:0;;;;14822:18:1;;53920:95:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;54053:34:0;;-1:-1:-1;;;54053:34:0;;54081:4;54053:34;;;373:74:1;54026:24:0;;-1:-1:-1;54090:17:0;;-1:-1:-1;;;;;;54053:9:0;:19;;;;346:18:1;;54053:34:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:54;;;;:::i;:::-;54026:81;;54338:32;54353:16;54338:14;:32::i;:::-;54501:25;54529:43;54554:17;54529:24;:43::i;:::-;54501:71;;54627:19;54607:17;:39;:121;;;;;54684:44;54663:17;:65;;54607:121;54585:271;;;;-1:-1:-1;;;54585:271:0;;15189:2:1;54585:271:0;;;15171:21:1;15228:3;15208:18;;;15201:31;;;15268:34;15248:18;;;15241:62;15339:34;15319:18;;;15312:62;15411:34;15390:19;;;15383:63;-1:-1:-1;;;15462:19:1;;;15455:35;15507:19;;54585:271:0;14987:545:1;77454:249:0;77511:7;77531:21;77555:27;:25;:27::i;:::-;77531:51;;77596:27;77630:28;77644:13;77630;:28::i;:::-;-1:-1:-1;77593:65:0;;77454:249;-1:-1:-1;;;;;;77454:249:0:o;38145:1422::-;38220:20;38243:21;;;:12;:21;;;;;;;;38220:44;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;38220:44:0;;;;;;;;;;;-1:-1:-1;;;38220:44:0;;;;;;;;;38243:21;38220:44;;;;-1:-1:-1;;;38220:44:0;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;-1:-1:-1;38220:44:0;-1:-1:-1;38277:31:0;38300:7;38277:22;:31::i;:::-;38319:33;38340:4;:11;;;38319:20;:33::i;:::-;38365:25;:23;:25::i;:::-;-1:-1:-1;38403:21:0;;;;:12;:21;;;;;:28;;;;:54;;38468:55;38507:15;38468:55;-1:-1:-1;;;38468:55:0;-1:-1:-1;;;;38468:55:0;;;;-1:-1:-1;;;38468:55:0;;;38597:13;-1:-1:-1;;;;;38550:7:0;:25;;;;38576:10;;38403:21;;38597:38;;38613:22;;38597:38;:::i;:::-;38550:86;;-1:-1:-1;;;;;;38550:86:0;;;;;;;-1:-1:-1;;;;;6456:55:1;;;38550:86:0;;;6438:74:1;6528:18;;;6521:34;;;;6571:18;;;6564:34;6411:18;;38550:86:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;38534:102;;38668:1;38649:15;;:20;;;;;;;:::i;:::-;;;;-1:-1:-1;;38697:15:0;;;38682:30;;38697:15;;38682:30;;38697:15;;38682:30;:::i;:::-;;;;-1:-1:-1;;38768:14:0;;;;38750:15;;:32;;;;;;:::i;:::-;38723:23;;:59;;;;;;;:::i;:::-;;;;-1:-1:-1;;39324:15:0;;39274:22;;39299:51;;39341:8;39299:24;:51::i;:::-;39274:76;;39411:45;39429:14;39445:10;39411:17;:45::i;:::-;39509:15;;39474:85;;;15794:25:1;;;15850:2;15835:18;;15828:34;;;;15878:18;;15871:34;;;15936:2;15921:18;;15914:34;;;15997:22;15985:35;;15979:3;15964:19;;15957:64;39488:10:0;;39474:85;;15781:3:1;15766:19;39474:85:0;;;;;;;38209:1358;;;38145:1422;;:::o;79444:245::-;79506:7;79527:31;79564:76;79593:16;;79611:28;;79564;:76::i;:::-;-1:-1:-1;79526:114:0;79444:245;-1:-1:-1;;79444:245:0:o;78591:845::-;78682:7;78702:24;78729:10;-1:-1:-1;;;;;78729:22:0;;:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;78702:51;;78765:24;78791:27;78825:29;78839:14;78825:13;:29::i;:::-;78764:90;;;;;;;79305:16;79325:1;79305:21;79301:41;;;-1:-1:-1;79336:4:0;;78591:845;-1:-1:-1;;;;78591:845:0:o;79301:41::-;79412:16;79363:38;79382:19;79363:16;:38;:::i;:::-;79362:47;;79405:4;79362:47;:::i;:::-;:66;;;;:::i;72288:425::-;72390:18;72580:21;;;:12;:21;;;;;;;;72557:44;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;72557:44:0;;;;;;;;;;;-1:-1:-1;;;72557:44:0;;;;;;;;;72390:18;;;;;;;;;;72557:44;;72580:21;72557:44;;;;-1:-1:-1;;;72557:44:0;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;72620:4;:15;;;72637:4;:17;;;72656:4;:14;;;72672:4;:12;;;72692:4;:11;;;72686:18;;;;;;;;:::i;:::-;72612:93;;;;-1:-1:-1;72612:93:0;;-1:-1:-1;72612:93:0;-1:-1:-1;72612:93:0;;-1:-1:-1;72288:425:0;-1:-1:-1;;;72288:425:0:o;57752:356::-;57801:33;:31;:33::i;:::-;57845:28;:26;:28::i;:::-;57886:9;:16;;-1:-1:-1;;57886:16:0;57898:4;57886:16;;;;;;57939:13;57920:33;;160:25:1;;;57920:33:0;;148:2:1;133:18;57920:33:0;;;;;;;58099:1;58083:13;:17;57752:356::o;78380:203::-;78435:7;78455:21;78479:27;:25;:27::i;:::-;78455:51;;78524;78561:13;78524:36;:51::i;:::-;78517:58;;;78380:203;:::o;55215:208::-;55275:7;55298:25;55328:11;-1:-1:-1;;;;;55328:24:0;;:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;55295:59;;;;55374:41;55383:12;;55397:17;55374:8;:41::i;75432:978::-;75543:24;75582:27;75624:21;75660:24;75699:27;75889:11;;75872:14;:28;;;;:::i;:::-;75856:44;;75930:21;:19;:21::i;:::-;76014:13;;75911:40;;-1:-1:-1;76014:13:0;-1:-1:-1;76040:17:0;76060:32;75911:40;76060:13;:32;:::i;:::-;76040:52;;76121:19;76109:9;:31;76105:298;;;76195:20;76218:31;76230:19;76218:9;:31;:::i;:::-;76195:54;-1:-1:-1;76314:9:0;76283:28;76298:13;76195:54;76283:28;:::i;:::-;:40;;;;:::i;:::-;76264:59;-1:-1:-1;76360:31:0;76264:59;76360:12;:31;:::i;:::-;76338:53;;76142:261;76105:298;75743:667;75432:978;;;;;;;:::o;61802:165::-;61870:7;28253:2;61916:18;;61898:15;:36;;;;:::i;5487:582::-;5560:4;5595:9;5583;:21;5579:51;;;5619:9;5607:21;;5579:51;5672:14;5668:47;;-1:-1:-1;4134:4:0;5689:24;;5668:47;4134:4;5779:5;5807:9;5868:162;5879:1;5875;:5;5868:162;;;5901:5;5905:1;5901;:5;:::i;:::-;:10;5897:67;;5936:12;5943:1;5946;5936:6;:12::i;:::-;5932:16;;5897:67;5982:12;5989:1;5992;5982:6;:12::i;:::-;5978:16;-1:-1:-1;6013:5:0;6017:1;6013;:5;:::i;:::-;6009:9;;5868:162;;;6049:12;6056:1;6059;6049:6;:12::i;485:106::-;543:7;574:1;570;:5;:13;;582:1;570:13;;;578:1;570:13;563:20;485:106;-1:-1:-1;;;485:106:0:o;64264:3870::-;64463:31;;64660:30;64619:37;64637:19;64619:15;:37;:::i;:::-;64618:72;;;;:::i;:::-;64580:110;;64854:29;64815:35;:68;:197;;;;64989:23;64962;:50;64815:197;:305;;;-1:-1:-1;65104:11:0;;:16;64815:305;64703:525;;;65155:23;65147:69;;;;64703:525;65240:24;65293:11;;65267:23;;:37;;;;:::i;:::-;65240:64;-1:-1:-1;67248:49:0;67300:147;67372:19;67327:42;67346:23;65240:64;67327:42;:::i;:::-;:64;;;;:::i;:::-;67406:30;67300:12;:147::i;:::-;67248:199;;67502:41;67464:35;:79;67460:263;;;67650:23;67642:69;;;;;;67460:263;67735:27;67803:123;67826:29;67870:45;67914:1;67870:41;:45;:::i;:::-;67803:8;:123::i;:::-;67765:161;;:35;:161;:::i;:::-;67735:191;;67965:161;68073:4;68014:56;68021:27;68050:19;68014:6;:56::i;:::-;67988:82;;:23;:82;:::i;:::-;:89;;;;:::i;:::-;68092:23;67965:8;:161::i;:::-;67939:187;;64569:3565;;;64264:3870;;;;;:::o;62488:252::-;62577:7;62600:35;62639:48;62671:15;62639:31;:48::i;63235:770::-;63353:7;63483:15;63479:32;;-1:-1:-1;63508:1:0;63501:8;;63479:32;63679:20;63710:28;63728:10;63710:15;:28;:::i;:::-;63702:37;;:4;:37;:::i;:::-;63679:60;-1:-1:-1;63752:21:0;63805:32;63820:17;63679:60;63805:32;:::i;:::-;63776:25;63789:12;63776:10;:25;:::i;:::-;:62;;;;:::i;69106:273::-;69202:7;69358:13;69335:20;:13;69351:4;69335:20;:::i;:::-;:36;;;;:::i;69421:162::-;69517:24;;-1:-1:-1;;;69517:24:0;;;;;160:25:1;;;69517:7:0;-1:-1:-1;;;;;69517:15:0;;;;133:18:1;;69517:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;69503:38:0;:10;-1:-1:-1;;;;;69503:38:0;;69495:80;;;;-1:-1:-1;;;69495:80:0;;16607:2:1;69495:80:0;;;16589:21:1;16646:2;16626:18;;;16619:30;16685:31;16665:18;;;16658:59;16734:18;;69495:80:0;16405:353:1;69591:146:0;69683:17;69673:6;:27;;;;;;;;:::i;:::-;;69665:64;;;;-1:-1:-1;;;69665:64:0;;16965:2:1;69665:64:0;;;16947:21:1;17004:2;16984:18;;;16977:30;17043:26;17023:18;;;17016:54;17087:18;;69665:64:0;16763:348:1;68142:856:0;68248:16;;68320:28;;68195:7;;68248:16;68195:7;;68455:88;68248:16;68320:28;68455;:88::i;:::-;68361:182;;;;68599:34;68560:35;:73;68556:392;;68650:28;:66;;;68737:49;;;68733:204;;68807:16;:42;;;68873:48;;160:25:1;;;68873:48:0;;148:2:1;133:18;68873:48:0;;;;;;;-1:-1:-1;68967:23:0;68142:856;-1:-1:-1;;;68142:856:0:o;55595:742::-;55640:7;55649;55672:25;55702:11;-1:-1:-1;;;;;55702:24:0;;:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;55768:12:0;;55669:59;;-1:-1:-1;55768:12:0;-1:-1:-1;56112:38:0;;;56108:163;;;-1:-1:-1;56167:12:0;:32;;;56182:17;;;-1:-1:-1;55595:742:0;-1:-1:-1;55595:742:0:o;56108:163::-;56291:18;56311:17;;-1:-1:-1;55595:742:0;-1:-1:-1;55595:742:0:o;61975:505::-;62142:9;;62064:7;;;;62142:9;;62138:45;;;-1:-1:-1;62162:1:0;;61975:505;-1:-1:-1;61975:505:0:o;62138:45::-;62246:26;62314:4;62275:36;62293:18;62275:15;:36;:::i;:::-;:43;;;;:::i;:::-;62246:72;-1:-1:-1;62329:35:0;62367:36;62246:72;62367:15;:36;:::i;:::-;62424:18;;62329:74;;-1:-1:-1;61975:505:0;;-1:-1:-1;;;61975:505:0:o;40761:1464::-;40880:7;41039:44;41056:27;41039:14;:44;:::i;:::-;41020:15;:63;;41012:138;;;;-1:-1:-1;;;41012:138:0;;17318:2:1;41012:138:0;;;17300:21:1;17357:2;17337:18;;;17330:30;17396:34;17376:18;;;17369:62;17467:32;17447:18;;;17440:60;17517:19;;41012:138:0;17116:426:1;41012:138:0;41182:15;41161:18;:36;41225:24;41446:29;41460:14;41446:13;:29::i;:::-;41210:265;;;;;;41931:16;41909:18;:38;;41901:95;;;;-1:-1:-1;;;41901:95:0;;17749:2:1;41901:95:0;;;17731:21:1;17788:2;17768:18;;;17761:30;17827:34;17807:18;;;17800:62;-1:-1:-1;;;17878:18:1;;;17871:42;17930:19;;41901:95:0;17547:408:1;41901:95:0;42039:20;;42035:126;;42076:73;42132:16;42076:55;:73::i;:::-;42180:37;42201:16;42180:18;:37;:::i;56496:165::-;56577:38;;-1:-1:-1;;;56577:38:0;;;;;18134:25:1;;;-1:-1:-1;;;;;18195:55:1;;;18175:18;;;18168:83;56577:11:0;:20;;;;18107:18:1;;56577:38:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;56642:11;56626:12;;:27;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;56496:165:0:o;40006:318::-;40172:45;40190:11;40211:4;40172:17;:45::i;:::-;40270:46;40304:11;40270:33;:46::i;70044:158::-;70138:15;70123:11;:30;;70115:79;;;;-1:-1:-1;;;70115:79:0;;18464:2:1;70115:79:0;;;18446:21:1;18503:2;18483:18;;;18476:30;18542:34;18522:18;;;18515:62;-1:-1:-1;;;18593:18:1;;;18586:34;18637:19;;70115:79:0;18262:400:1;70565:130:0;70637:9;;;;70636:10;70628:59;;;;-1:-1:-1;;;70628:59:0;;18869:2:1;70628:59:0;;;18851:21:1;18908:2;18888:18;;;18881:30;18947:34;18927:18;;;18920:62;-1:-1:-1;;;18998:18:1;;;18991:34;19042:19;;70628:59:0;18667:400:1;70628:59:0;70565:130::o;56345:143::-;56410:32;;-1:-1:-1;;;56410:32:0;;;;;160:25:1;;;56410:11:0;-1:-1:-1;;;;;56410:19:0;;;;133:18:1;;56410:32:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;56469:11;56453:12;;:27;;;;;;;:::i;:::-;;;;-1:-1:-1;;;56345:143:0:o;71381:214::-;71500:22;71459:37;71477:19;71459:15;:37;:::i;:::-;:63;;71451:136;;;;-1:-1:-1;;;71451:136:0;;19274:2:1;71451:136:0;;;19256:21:1;19313:2;19293:18;;;19286:30;19352:34;19332:18;;;19325:62;19423:30;19403:18;;;19396:58;19471:19;;71451:136:0;19072:424:1;69881:155:0;69979:1;69952:10;-1:-1:-1;;;;;69952:22:0;;:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:28;69944:84;;;;-1:-1:-1;;;69944:84:0;;19703:2:1;69944:84:0;;;19685:21:1;19742:2;19722:18;;;19715:30;19781:34;19761:18;;;19754:62;-1:-1:-1;;;19832:18:1;;;19825:41;19883:19;;69944:84:0;19501:407:1;71603:381:0;71665:28;71728:13;71696:29;;:45;;;;:::i;:::-;71665:76;-1:-1:-1;71752:29:0;71784:37;71807:14;71665:76;71784:37;:::i;:::-;71752:69;;71861:20;71842:15;:39;;:82;;;;;71903:21;71885:15;:39;71842:82;71834:142;;;;-1:-1:-1;;;71834:142:0;;20115:2:1;71834:142:0;;;20097:21:1;20154:2;20134:18;;;20127:30;20193:34;20173:18;;;20166:62;20264:17;20244:18;;;20237:45;20299:19;;71834:142:0;19913:411:1;71834:142:0;71654:330;;71603:381::o;71992:218::-;72112:17;72095:13;;:34;;72087:115;;;;-1:-1:-1;;;72087:115:0;;20531:2:1;72087:115:0;;;20513:21:1;20570:2;20550:18;;;20543:30;;;20609:34;20589:18;;;20582:62;20680:34;20660:18;;;20653:62;-1:-1:-1;;;20731:19:1;;;20724:35;20776:19;;72087:115:0;20329:472:1;69745:128:0;69836:1;69826:7;:11;69818:47;;;;-1:-1:-1;;;69818:47:0;;21008:2:1;69818:47:0;;;20990:21:1;21047:2;21027:18;;;21020:30;21086:25;21066:18;;;21059:53;21129:18;;69818:47:0;20806:347:1;59013:582:0;59446:92;;-1:-1:-1;;;59446:92:0;;59097:7;59446:92;;;21382:41:1;;;28195:1:0;21439:18:1;;;21432:50;59533:4:0;21498:18:1;;;21491:34;59097:7:0;;;-1:-1:-1;;;;;59446:9:0;:16;;;;21355:18:1;;59446:92:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;59433:105;-1:-1:-1;59583:4:0;59558:22;59563:17;59433:105;59558:22;:::i;56830:342::-;56925:40;;-1:-1:-1;;;56925:40:0;;56959:4;56925:40;;;373:74:1;56894:28:0;;56925:15;-1:-1:-1;;;;;56925:25:0;;;;346:18:1;;56925:40:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;56976:34;;-1:-1:-1;;;56976:34:0;;;;;160:25:1;;;56894:71:0;;-1:-1:-1;56976:15:0;-1:-1:-1;;;;;56976:23:0;;;;133:18:1;;56976:34:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;57051:40:0;;-1:-1:-1;;;57051:40:0;;57085:4;57051:40;;;373:74:1;57021:27:0;;57094:20;;-1:-1:-1;;;;;57051:15:0;:25;;;;346:18:1;;57051:40:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:63;;;;:::i;:::-;57021:93;;57145:19;57125:16;;:39;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;56830:342:0:o;70210:347::-;70309:9;;;;70304:246;;70474:10;-1:-1:-1;;;;;70474:22:0;;:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;70437:33;70454:16;70437:14;:33;:::i;:::-;:61;;70429:109;;;;-1:-1:-1;;;70429:109:0;;21738:2:1;70429:109:0;;;21720:21:1;21777:2;21757:18;;;21750:30;21816:34;21796:18;;;21789:62;-1:-1:-1;;;21867:18:1;;;21860:33;21910:19;;70429:109:0;21536:399:1;76498:405:0;76594:24;76633:27;76675:21;76711:24;76750:27;76806:21;76832:17;:15;:17::i;:::-;76805:44;;;76867:28;76881:13;76867;:28::i;:::-;76860:35;;;;;;;;;;;76498:405;;;;;:::o;61183:611::-;61275:7;61295:29;61327:53;61355:24;61327:27;:53::i;:::-;61391:18;:42;;;61449:48;;160:25:1;;;61295:85:0;;-1:-1:-1;61449:48:0;;148:2:1;133:18;61449:48:0;;;;;;;61510:18;61549;;61531:15;:36;;;;:::i;:::-;61510:57;;28253:2;61584:10;:35;61580:166;;61657:15;61636:18;:36;;;61692:42;;160:25:1;;;61692:42:0;;148:2:1;133:18;61692:42:0;;;;;;;-1:-1:-1;61765:21:0;61183:611;-1:-1:-1;;61183:611:0:o;70871:502::-;70970:7;71016:8;70998:14;:26;;70990:91;;;;-1:-1:-1;;;70990:91:0;;22142:2:1;70990:91:0;;;22124:21:1;22181:2;22161:18;;;22154:30;22220:34;22200:18;;;22193:62;22291:22;22271:18;;;22264:50;22331:19;;70990:91:0;21940:416:1;70990:91:0;71097:25;71127:11;-1:-1:-1;;;;;71127:24:0;;:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;71094:59;;;;71193:8;71172:17;:29;;71164:86;;;;-1:-1:-1;;;71164:86:0;;17749:2:1;71164:86:0;;;17731:21:1;17788:2;17768:18;;;17761:30;17827:34;17807:18;;;17800:62;-1:-1:-1;;;17878:18:1;;;17871:42;17930:19;;71164:86:0;17547:408:1;71164:86:0;71263:22;71288:43;71297:14;71313:17;71288:8;:43::i;57353:195::-;57442:49;;-1:-1:-1;;;57442:49:0;;-1:-1:-1;;;;;7637:55:1;;;57442:49:0;;;7619:74:1;7709:18;;;7702:34;;;57442:15:0;:24;;;;7592:18:1;;57442:49:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;57522:18;57502:16;;:38;;;;;;;:::i;70703:160::-;70779:10;-1:-1:-1;;;;;70793:22:0;70779:36;;70771:84;;;;-1:-1:-1;;;70771:84:0;;22563:2:1;70771:84:0;;;22545:21:1;22602:2;22582:18;;;22575:30;22641:34;22621:18;;;22614:62;-1:-1:-1;;;22692:18:1;;;22685:33;22735:19;;70771:84:0;22361:399:1;59603:582:0;60036:92;;-1:-1:-1;;;60036:92:0;;28195:1;60036:92;;;21382:41:1;59687:7:0;21439:18:1;;;21432:50;;;60123:4:0;21498:18:1;;;21491:34;59687:7:0;;;-1:-1:-1;;;;;60036:9:0;:16;;;;21355:18:1;;60036:92:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;60023:105;-1:-1:-1;60160:17:0;60148:9;60023:105;60153:4;60148:9;:::i;57180:165::-;57252:40;;-1:-1:-1;;;57252:40:0;;;;;160:25:1;;;57252:15:0;-1:-1:-1;;;;;57252:24:0;;;;133:18:1;;57252:40:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;57323:14;57303:16;;:34;;;;;;;:::i;302:107::-;360:7;392:1;387;:6;;:14;;400:1;387:14;;4598:147;4659:7;4134:4;4695:21;4715:1;4134:4;4695:21;:::i;:::-;4687:5;4691:1;4687;:5;:::i;:::-;:29;;;;:::i;1073:197::-;1135:7;1243:5;1247:1;1243;:5;:::i;:::-;:10;:18;;1260:1;1243:18;;;1256:1;1243:18;1234:28;;:5;1238:1;1234;:5;:::i;:::-;:28;;;;:::i;39658:340::-;39774:34;;-1:-1:-1;;;39774:34:0;;39802:4;39774:34;;;373:74:1;39746:25:0;;39774:9;-1:-1:-1;;;;;39774:19:0;;;;346:18:1;;39774:34:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;39819:77;;-1:-1:-1;;;39819:77:0;;-1:-1:-1;;;;;39868:9:0;7637:55:1;;39819:77:0;;;7619:74:1;7709:18;;;7702:34;;;39746:62:0;;-1:-1:-1;39819:19:0;:40;;;;;;7592:18:1;;39819:77:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;39936:34:0;;-1:-1:-1;;;39936:34:0;;39964:4;39936:34;;;373:74:1;39974:15:0;;-1:-1:-1;39936:9:0;-1:-1:-1;;;;;39936:19:0;;-1:-1:-1;39936:19:0;;346:18:1;;39936:34:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;39916:54;;:17;:54;:::i;:::-;:73;39909:81;;;;:::i;1143:180:1:-;1202:6;1255:2;1243:9;1234:7;1230:23;1226:32;1223:52;;;1271:1;1268;1261:12;1223:52;-1:-1:-1;1294:23:1;;1143:180;-1:-1:-1;1143:180:1:o;2133:154::-;-1:-1:-1;;;;;2212:5:1;2208:54;2201:5;2198:65;2188:93;;2277:1;2274;2267:12;2292:687;2394:6;2402;2410;2418;2426;2434;2487:3;2475:9;2466:7;2462:23;2458:33;2455:53;;;2504:1;2501;2494:12;2455:53;2543:9;2530:23;2562:31;2587:5;2562:31;:::i;:::-;2612:5;-1:-1:-1;2664:2:1;2649:18;;2636:32;;-1:-1:-1;2715:2:1;2700:18;;2687:32;;-1:-1:-1;2771:2:1;2756:18;;2743:32;2819:4;2806:18;;2794:31;;2784:59;;2839:1;2836;2829:12;2784:59;2292:687;;;;-1:-1:-1;2292:687:1;;2916:3;2901:19;;2888:33;;2968:3;2953:19;;;2940:33;;-1:-1:-1;2292:687:1;-1:-1:-1;;2292:687:1:o;2984:248::-;3052:6;3060;3113:2;3101:9;3092:7;3088:23;3084:32;3081:52;;;3129:1;3126;3119:12;3081:52;-1:-1:-1;;3152:23:1;;;3222:2;3207:18;;;3194:32;;-1:-1:-1;2984:248:1:o;5220:127::-;5281:10;5276:3;5272:20;5269:1;5262:31;5312:4;5309:1;5302:15;5336:4;5333:1;5326:15;5352:128;5392:3;5423:1;5419:6;5416:1;5413:13;5410:39;;;5429:18;;:::i;:::-;-1:-1:-1;5465:9:1;;5352:128::o;5485:168::-;5525:7;5591:1;5587;5583:6;5579:14;5576:1;5573:21;5568:1;5561:9;5554:17;5550:45;5547:71;;;5598:18;;:::i;:::-;-1:-1:-1;5638:9:1;;5485:168::o;5658:127::-;5719:10;5714:3;5710:20;5707:1;5700:31;5750:4;5747:1;5740:15;5774:4;5771:1;5764:15;5790:120;5830:1;5856;5846:35;;5861:18;;:::i;:::-;-1:-1:-1;5895:9:1;;5790:120::o;5915:127::-;5976:10;5971:3;5967:20;5964:1;5957:31;6007:4;6004:1;5997:15;6031:4;6028:1;6021:15;6047:184;6117:6;6170:2;6158:9;6149:7;6145:23;6141:32;6138:52;;;6186:1;6183;6176:12;6138:52;-1:-1:-1;6209:16:1;;6047:184;-1:-1:-1;6047:184:1:o;6609:179::-;6687:13;;6740:22;6729:34;;6719:45;;6709:73;;6778:1;6775;6768:12;6709:73;6609:179;;;:::o;6793:206::-;6862:6;6915:2;6903:9;6894:7;6890:23;6886:32;6883:52;;;6931:1;6928;6921:12;6883:52;6954:39;6983:9;6954:39;:::i;7004:125::-;7044:4;7072:1;7069;7066:8;7063:34;;;7077:18;;:::i;:::-;-1:-1:-1;7114:9:1;;7004:125::o;7134:306::-;7222:6;7230;7238;7291:2;7279:9;7270:7;7266:23;7262:32;7259:52;;;7307:1;7304;7297:12;7259:52;7336:9;7330:16;7320:26;;7386:2;7375:9;7371:18;7365:25;7355:35;;7430:2;7419:9;7415:18;7409:25;7399:35;;7134:306;;;;;:::o;8396:267::-;8474:6;8482;8535:2;8523:9;8514:7;8510:23;8506:32;8503:52;;;8551:1;8548;8541:12;8503:52;8580:9;8574:16;8564:26;;8609:48;8653:2;8642:9;8638:18;8609:48;:::i;:::-;8599:58;;8396:267;;;;;:::o;9071:277::-;9138:6;9191:2;9179:9;9170:7;9166:23;9162:32;9159:52;;;9207:1;9204;9197:12;9159:52;9239:9;9233:16;9292:5;9285:13;9278:21;9271:5;9268:32;9258:60;;9314:1;9311;9304:12;11229:573;11445:2;11430:18;;11434:9;11525:6;11403:4;11559:194;11573:4;11570:1;11567:11;11559:194;;;11632:13;;11620:26;;11669:4;11693:12;;;;11728:15;;;;11593:1;11586:9;11559:194;;;11563:3;;;11789:6;11784:2;11773:9;11769:18;11762:34;11229:573;;;;;:::o;16032:112::-;16064:1;16090;16080:35;;16095:18;;:::i;:::-;-1:-1:-1;16129:9:1;;16032:112::o;16149:251::-;16219:6;16272:2;16260:9;16251:7;16247:23;16243:32;16240:52;;;16288:1;16285;16278:12;16240:52;16320:9;16314:16;16339:31;16364:5;16339:31;:::i;22765:127::-;22826:10;22821:3;22817:20;22814:1;22807:31;22857:4;22854:1;22847:15;22881:4;22878:1;22871:15
Swarm Source
ipfs://d50cb42b3fa172de0f06883778cf4e6e0328c7e338330d8671e5c083cbaed28a
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.