Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00Token Holdings
More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 80 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Lock Longer | 21472337 | 3 days ago | IN | 0 ETH | 0.00148915 | ||||
Sync | 20602123 | 125 days ago | IN | 0 ETH | 0.00011632 | ||||
Sync | 20530564 | 135 days ago | IN | 0 ETH | 0.00037487 | ||||
Lock Longer | 19851842 | 229 days ago | IN | 0 ETH | 0.00094438 | ||||
Sync | 19756377 | 243 days ago | IN | 0 ETH | 0.00052469 | ||||
Sync | 19073416 | 339 days ago | IN | 0 ETH | 0.00110211 | ||||
Withdraw Locked | 19063087 | 340 days ago | IN | 0 ETH | 0.0117701 | ||||
Get Reward | 19063080 | 340 days ago | IN | 0 ETH | 0.00835972 | ||||
Get Reward | 18846169 | 370 days ago | IN | 0 ETH | 0.00703344 | ||||
Get Reward | 18846158 | 370 days ago | IN | 0 ETH | 0.00740638 | ||||
Sync | 18751989 | 384 days ago | IN | 0 ETH | 0.00458389 | ||||
Get Reward | 18213425 | 459 days ago | IN | 0 ETH | 0.00391426 | ||||
Withdraw Locked | 18212718 | 459 days ago | IN | 0 ETH | 0.0089947 | ||||
Get Reward | 18189396 | 462 days ago | IN | 0 ETH | 0.0022475 | ||||
Get Reward | 18189388 | 462 days ago | IN | 0 ETH | 0.00239805 | ||||
Sync | 18114123 | 473 days ago | IN | 0 ETH | 0.00657716 | ||||
Sync | 17779694 | 520 days ago | IN | 0 ETH | 0.00430235 | ||||
Sync | 17478692 | 562 days ago | IN | 0 ETH | 0.00258926 | ||||
Get Reward | 17443601 | 567 days ago | IN | 0 ETH | 0.00695227 | ||||
Get Reward | 17299552 | 587 days ago | IN | 0 ETH | 0.0067073 | ||||
Get Reward | 17299536 | 587 days ago | IN | 0 ETH | 0.00660415 | ||||
Withdraw Locked | 17299475 | 587 days ago | IN | 0 ETH | 0.01704693 | ||||
Withdraw Locked | 17231219 | 597 days ago | IN | 0 ETH | 0.0832973 | ||||
Withdraw Locked | 17231215 | 597 days ago | IN | 0 ETH | 0.09533808 | ||||
Stake Locked | 17187922 | 603 days ago | IN | 0 ETH | 0.03866416 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
FraxUnifiedFarm_ERC20_Convex_FRAXBP_Volatile
Compiler Version
v0.8.17+commit.8df45f5f
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2022-09-20 */ /** *Submitted for verification at Etherscan.io on 2022-09-19 */ // SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.0; // Sources flattened with hardhat v2.11.1 https://hardhat.org // File contracts/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, so we distribute return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2); } // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) function sqrt(uint y) internal pure returns (uint z) { if (y > 3) { z = y; uint x = y / 2 + 1; while (x < z) { z = x; x = (y / x + x) / 2; } } else if (y != 0) { z = 1; } } } // File contracts/Curve/IveFXS.sol pragma abicoder v2; interface IveFXS { struct LockedBalance { int128 amount; uint256 end; } function commit_transfer_ownership(address addr) external; function apply_transfer_ownership() external; function commit_smart_wallet_checker(address addr) external; function apply_smart_wallet_checker() external; function toggleEmergencyUnlock() external; function recoverERC20(address token_addr, uint256 amount) external; function get_last_user_slope(address addr) external view returns (int128); function user_point_history__ts(address _addr, uint256 _idx) external view returns (uint256); function locked__end(address _addr) external view returns (uint256); function checkpoint() external; function deposit_for(address _addr, uint256 _value) external; function create_lock(uint256 _value, uint256 _unlock_time) external; function increase_amount(uint256 _value) external; function increase_unlock_time(uint256 _unlock_time) external; function withdraw() external; function balanceOf(address addr) external view returns (uint256); function balanceOf(address addr, uint256 _t) external view returns (uint256); function balanceOfAt(address addr, uint256 _block) external view returns (uint256); function totalSupply() external view returns (uint256); function totalSupply(uint256 t) external view returns (uint256); function totalSupplyAt(uint256 _block) external view returns (uint256); function totalFXSSupply() external view returns (uint256); function totalFXSSupplyAt(uint256 _block) external view returns (uint256); function changeController(address _newController) external; function token() external view returns (address); function supply() external view returns (uint256); function locked(address addr) external view returns (LockedBalance memory); function epoch() external view returns (uint256); function point_history(uint256 arg0) external view returns (int128 bias, int128 slope, uint256 ts, uint256 blk, uint256 fxs_amt); function user_point_history(address arg0, uint256 arg1) external view returns (int128 bias, int128 slope, uint256 ts, uint256 blk, uint256 fxs_amt); function user_point_epoch(address arg0) external view returns (uint256); function slope_changes(uint256 arg0) external view returns (int128); function controller() external view returns (address); function transfersEnabled() external view returns (bool); function emergencyUnlockActive() external view returns (bool); function name() external view returns (string memory); function symbol() external view returns (string memory); function version() external view returns (string memory); function decimals() external view returns (uint256); function future_smart_wallet_checker() external view returns (address); function smart_wallet_checker() external view returns (address); function admin() external view returns (address); function future_admin() external view returns (address); } // File contracts/Curve/IFraxGaugeController.sol // https://github.com/swervefi/swerve/edit/master/packages/swerve-contracts/interfaces/IGaugeController.sol interface IFraxGaugeController { struct Point { uint256 bias; uint256 slope; } struct VotedSlope { uint256 slope; uint256 power; uint256 end; } // Public variables function admin() external view returns (address); function future_admin() external view returns (address); function token() external view returns (address); function voting_escrow() external view returns (address); function n_gauge_types() external view returns (int128); function n_gauges() external view returns (int128); function gauge_type_names(int128) external view returns (string memory); function gauges(uint256) external view returns (address); function vote_user_slopes(address, address) external view returns (VotedSlope memory); function vote_user_power(address) external view returns (uint256); function last_user_vote(address, address) external view returns (uint256); function points_weight(address, uint256) external view returns (Point memory); function time_weight(address) external view returns (uint256); function points_sum(int128, uint256) external view returns (Point memory); function time_sum(uint256) external view returns (uint256); function points_total(uint256) external view returns (uint256); function time_total() external view returns (uint256); function points_type_weight(int128, uint256) external view returns (uint256); function time_type_weight(uint256) external view returns (uint256); // Getter functions function gauge_types(address) external view returns (int128); function gauge_relative_weight(address) external view returns (uint256); function gauge_relative_weight(address, uint256) external view returns (uint256); function get_gauge_weight(address) external view returns (uint256); function get_type_weight(int128) external view returns (uint256); function get_total_weight() external view returns (uint256); function get_weights_sum_per_type(int128) external view returns (uint256); // External functions function commit_transfer_ownership(address) external; function apply_transfer_ownership() external; function add_gauge( address, int128, uint256 ) external; function checkpoint() external; function checkpoint_gauge(address) external; function global_emission_rate() external view returns (uint256); function gauge_relative_weight_write(address) external returns (uint256); function gauge_relative_weight_write(address, uint256) external returns (uint256); function add_type(string memory, uint256) external; function change_type_weight(int128, uint256) external; function change_gauge_weight(address, uint256) external; function change_global_emission_rate(uint256) external; function vote_for_gauge_weights(address, uint256) external; } // File contracts/Common/Context.sol /* * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with GSN meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address payable) { return payable(msg.sender); } function _msgData() internal view virtual returns (bytes memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } } // File contracts/Math/SafeMath.sol /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction overflow"); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. * * _Available since v2.4.0._ */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } /** * @dev Returns the integer division of two unsigned integers. Reverts with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. * * _Available since v2.4.0._ */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { // Solidity only automatically asserts when dividing by 0 require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, "SafeMath: modulo by zero"); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. * * _Available since v2.4.0._ */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } } // File contracts/ERC20/IERC20.sol /** * @dev Interface of the ERC20 standard as defined in the EIP. Does not include * the optional functions; to access them see {ERC20Detailed}. */ 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 `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, 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 `sender` to `recipient` 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 sender, address recipient, 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); } // File contracts/Curve/IFraxGaugeFXSRewardsDistributor.sol interface IFraxGaugeFXSRewardsDistributor { function acceptOwnership() external; function curator_address() external view returns(address); function currentReward(address gauge_address) external view returns(uint256 reward_amount); function distributeReward(address gauge_address) external returns(uint256 weeks_elapsed, uint256 reward_tally); function distributionsOn() external view returns(bool); function gauge_whitelist(address) external view returns(bool); function is_middleman(address) external view returns(bool); function last_time_gauge_paid(address) external view returns(uint256); function nominateNewOwner(address _owner) external; function nominatedOwner() external view returns(address); function owner() external view returns(address); function recoverERC20(address tokenAddress, uint256 tokenAmount) external; function setCurator(address _new_curator_address) external; function setGaugeController(address _gauge_controller_address) external; function setGaugeState(address _gauge_address, bool _is_middleman, bool _is_active) external; function setTimelock(address _new_timelock) external; function timelock_address() external view returns(address); function toggleDistributions() external; } // File contracts/Uniswap/TransferHelper.sol // helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false library TransferHelper { function safeApprove(address token, address to, uint value) internal { // bytes4(keccak256(bytes('approve(address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: APPROVE_FAILED'); } function safeTransfer(address token, address to, uint value) internal { // bytes4(keccak256(bytes('transfer(address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FAILED'); } function safeTransferFrom(address token, address from, address to, uint value) internal { // bytes4(keccak256(bytes('transferFrom(address,address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FROM_FAILED'); } function safeTransferETH(address to, uint value) internal { (bool success,) = to.call{value:value}(new bytes(0)); require(success, 'TransferHelper: ETH_TRANSFER_FAILED'); } } // File contracts/Utils/ReentrancyGuard.sol /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor () internal { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and make it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } } // File contracts/Staking/Owned.sol // https://docs.synthetix.io/contracts/Owned contract Owned { address public owner; address public nominatedOwner; constructor (address _owner) public { require(_owner != address(0), "Owner address cannot be 0"); owner = _owner; emit OwnerChanged(address(0), _owner); } function nominateNewOwner(address _owner) external onlyOwner { nominatedOwner = _owner; emit OwnerNominated(_owner); } function acceptOwnership() external { require(msg.sender == nominatedOwner, "You must be nominated before you can accept ownership"); emit OwnerChanged(owner, nominatedOwner); owner = nominatedOwner; nominatedOwner = address(0); } modifier onlyOwner { require(msg.sender == owner, "Only the contract owner may perform this action"); _; } event OwnerNominated(address newOwner); event OwnerChanged(address oldOwner, address newOwner); } // File contracts/Misc_AMOs/convex/IConvexBaseRewardPool.sol interface IConvexBaseRewardPool { function addExtraReward(address _reward) external returns (bool); function balanceOf(address account) external view returns (uint256); function clearExtraRewards() external; function currentRewards() external view returns (uint256); function donate(uint256 _amount) external returns (bool); function duration() external view returns (uint256); function earned(address account) external view returns (uint256); function extraRewards(uint256) external view returns (address); function extraRewardsLength() external view returns (uint256); function getReward() external returns (bool); function getReward(address _account, bool _claimExtras) external returns (bool); function historicalRewards() external view returns (uint256); function lastTimeRewardApplicable() external view returns (uint256); function lastUpdateTime() external view returns (uint256); function newRewardRatio() external view returns (uint256); function operator() external view returns (address); function periodFinish() external view returns (uint256); function pid() external view returns (uint256); function queueNewRewards(uint256 _rewards) external returns (bool); function queuedRewards() external view returns (uint256); function rewardManager() external view returns (address); function rewardPerToken() external view returns (uint256); function rewardPerTokenStored() external view returns (uint256); function rewardRate() external view returns (uint256); function rewardToken() external view returns (address); function rewards(address) external view returns (uint256); function stake(uint256 _amount) external returns (bool); function stakeAll() external returns (bool); function stakeFor(address _for, uint256 _amount) external returns (bool); function stakingToken() external view returns (address); function totalSupply() external view returns (uint256); function userRewardPerTokenPaid(address) external view returns (uint256); function withdraw(uint256 amount, bool claim) external returns (bool); function withdrawAll(bool claim) external; function withdrawAllAndUnwrap(bool claim) external; function withdrawAndUnwrap(uint256 amount, bool claim) external returns (bool); } // File contracts/Staking/FraxUnifiedFarmTemplate.sol // ==================================================================== // | ______ _______ | // | / _____________ __ __ / ____(_____ ____ _____ ________ | // | / /_ / ___/ __ `| |/_/ / /_ / / __ \/ __ `/ __ \/ ___/ _ \ | // | / __/ / / / /_/ _> < / __/ / / / / / /_/ / / / / /__/ __/ | // | /_/ /_/ \__,_/_/|_| /_/ /_/_/ /_/\__,_/_/ /_/\___/\___/ | // | | // ==================================================================== // ====================== FraxUnifiedFarmTemplate ===================== // ==================================================================== // Farming contract that accounts for veFXS // Overrideable for UniV3, ERC20s, etc // New for V2 // - Multiple reward tokens possible // - Can add to existing locked stakes // - Contract is aware of proxied veFXS // - veFXS multiplier formula changed // Apes together strong // Frax Finance: https://github.com/FraxFinance // Primary Author(s) // Travis Moore: https://github.com/FortisFortuna // Reviewer(s) / Contributor(s) // Jason Huan: https://github.com/jasonhuan // Sam Kazemian: https://github.com/samkazemian // Dennis: github.com/denett // Originally inspired by Synthetix.io, but heavily modified by the Frax team // (Locked, veFXS, and UniV3 portions are new) // https://raw.githubusercontent.com/Synthetixio/synthetix/develop/contracts/StakingRewards.sol // Extra rewards contract FraxUnifiedFarmTemplate is Owned, ReentrancyGuard { /* ========== STATE VARIABLES ========== */ // Instances IveFXS private immutable veFXS = IveFXS(0xc8418aF6358FFddA74e09Ca9CC3Fe03Ca6aDC5b0); // Frax related address internal immutable frax_address = 0x853d955aCEf822Db058eb8505911ED77F175b99e; uint256 public fraxPerLPStored; // Constant for various precisions uint256 internal constant MULTIPLIER_PRECISION = 1e18; // Time tracking uint256 public periodFinish; uint256 public lastUpdateTime; // Lock time and multiplier settings uint256 public lock_max_multiplier = uint256(2e18); // E18. 1x = e18 uint256 public lock_time_for_max_multiplier = 1 * 365 * 86400; // 1 year // uint256 public lock_time_for_max_multiplier = 2 * 86400; // 2 days uint256 public lock_time_min = 594000; // 6.875 * 86400 (~7 day) // veFXS related uint256 public vefxs_boost_scale_factor = uint256(4e18); // E18. 4x = 4e18; 100 / scale_factor = % vefxs supply needed for max boost uint256 public vefxs_max_multiplier = uint256(2e18); // E18. 1x = 1e18 uint256 public vefxs_per_frax_for_max_boost = uint256(4e18); // E18. 2e18 means 2 veFXS must be held by the staker per 1 FRAX mapping(address => uint256) internal _vefxsMultiplierStored; mapping(address => bool) internal valid_vefxs_proxies; mapping(address => mapping(address => bool)) internal proxy_allowed_stakers; // Reward addresses, gauge addresses, reward rates, and reward managers mapping(address => address) public rewardManagers; // token addr -> manager addr address[] internal rewardTokens; address[] internal gaugeControllers; address[] internal rewardDistributors; uint256[] internal rewardRatesManual; mapping(address => uint256) public rewardTokenAddrToIdx; // token addr -> token index // Reward period uint256 public constant rewardsDuration = 604800; // 7 * 86400 (7 days) // Reward tracking uint256[] private rewardsPerTokenStored; mapping(address => mapping(uint256 => uint256)) private userRewardsPerTokenPaid; // staker addr -> token id -> paid amount mapping(address => mapping(uint256 => uint256)) private rewards; // staker addr -> token id -> reward amount mapping(address => uint256) public lastRewardClaimTime; // staker addr -> timestamp // Gauge tracking uint256[] private last_gauge_relative_weights; uint256[] private last_gauge_time_totals; // Balance tracking uint256 internal _total_liquidity_locked; uint256 internal _total_combined_weight; mapping(address => uint256) internal _locked_liquidity; mapping(address => uint256) internal _combined_weights; mapping(address => uint256) public proxy_lp_balances; // Keeps track of LP balances proxy-wide. Needed to make sure the proxy boost is kept in line // Stakers set which proxy(s) they want to use mapping(address => address) public staker_designated_proxies; // Keep public so users can see on the frontend if they have a proxy // Admin booleans for emergencies and overrides bool public stakesUnlocked; // Release locked stakes in case of emergency bool internal withdrawalsPaused; // For emergencies bool internal rewardsCollectionPaused; // For emergencies bool internal stakingPaused; // For emergencies /* ========== STRUCTS ========== */ // In children... /* ========== MODIFIERS ========== */ modifier onlyByOwnGov() { require(msg.sender == owner || msg.sender == 0x8412ebf45bAC1B340BbE8F318b928C466c4E39CA, "Not owner or timelock"); _; } modifier onlyTknMgrs(address reward_token_address) { require(msg.sender == owner || isTokenManagerFor(msg.sender, reward_token_address), "Not owner or tkn mgr"); _; } modifier updateRewardAndBalanceMdf(address account, bool sync_too) { updateRewardAndBalance(account, sync_too); _; } /* ========== CONSTRUCTOR ========== */ constructor ( address _owner, address[] memory _rewardTokens, address[] memory _rewardManagers, uint256[] memory _rewardRatesManual, address[] memory _gaugeControllers, address[] memory _rewardDistributors ) Owned(_owner) { // Address arrays rewardTokens = _rewardTokens; gaugeControllers = _gaugeControllers; rewardDistributors = _rewardDistributors; rewardRatesManual = _rewardRatesManual; for (uint256 i = 0; i < _rewardTokens.length; i++){ // For fast token address -> token ID lookups later rewardTokenAddrToIdx[_rewardTokens[i]] = i; // Initialize the stored rewards rewardsPerTokenStored.push(0); // Initialize the reward managers rewardManagers[_rewardTokens[i]] = _rewardManagers[i]; // Push in empty relative weights to initialize the array last_gauge_relative_weights.push(0); // Push in empty time totals to initialize the array last_gauge_time_totals.push(0); } // Other booleans stakesUnlocked = false; // Initialization lastUpdateTime = block.timestamp; periodFinish = block.timestamp + rewardsDuration; } /* ============= VIEWS ============= */ // ------ REWARD RELATED ------ // See if the caller_addr is a manager for the reward token function isTokenManagerFor(address caller_addr, address reward_token_addr) public view returns (bool){ if (caller_addr == owner) return true; // Contract owner else if (rewardManagers[reward_token_addr] == caller_addr) return true; // Reward manager return false; } // All the reward tokens function getAllRewardTokens() external view returns (address[] memory) { return rewardTokens; } // Last time the reward was applicable function lastTimeRewardApplicable() internal view returns (uint256) { return Math.min(block.timestamp, periodFinish); } function rewardRates(uint256 token_idx) public view returns (uint256 rwd_rate) { address gauge_controller_address = gaugeControllers[token_idx]; if (gauge_controller_address != address(0)) { rwd_rate = (IFraxGaugeController(gauge_controller_address).global_emission_rate() * last_gauge_relative_weights[token_idx]) / 1e18; } else { rwd_rate = rewardRatesManual[token_idx]; } } // Amount of reward tokens per LP token / liquidity unit function rewardsPerToken() public view returns (uint256[] memory newRewardsPerTokenStored) { if (_total_liquidity_locked == 0 || _total_combined_weight == 0) { return rewardsPerTokenStored; } else { newRewardsPerTokenStored = new uint256[](rewardTokens.length); for (uint256 i = 0; i < rewardsPerTokenStored.length; i++){ newRewardsPerTokenStored[i] = rewardsPerTokenStored[i] + ( ((lastTimeRewardApplicable() - lastUpdateTime) * rewardRates(i) * 1e18) / _total_combined_weight ); } return newRewardsPerTokenStored; } } // Amount of reward tokens an account has earned / accrued // Note: In the edge-case of one of the account's stake expiring since the last claim, this will // return a slightly inflated number function earned(address account) public view returns (uint256[] memory new_earned) { uint256[] memory reward_arr = rewardsPerToken(); new_earned = new uint256[](rewardTokens.length); if (_combined_weights[account] > 0){ for (uint256 i = 0; i < rewardTokens.length; i++){ new_earned[i] = ((_combined_weights[account] * (reward_arr[i] - userRewardsPerTokenPaid[account][i])) / 1e18) + rewards[account][i]; } } } // Total reward tokens emitted in the given period function getRewardForDuration() external view returns (uint256[] memory rewards_per_duration_arr) { rewards_per_duration_arr = new uint256[](rewardRatesManual.length); for (uint256 i = 0; i < rewardRatesManual.length; i++){ rewards_per_duration_arr[i] = rewardRates(i) * rewardsDuration; } } // ------ LIQUIDITY AND WEIGHTS ------ // User locked liquidity / LP tokens function totalLiquidityLocked() external view returns (uint256) { return _total_liquidity_locked; } // Total locked liquidity / LP tokens function lockedLiquidityOf(address account) external view returns (uint256) { return _locked_liquidity[account]; } // Total combined weight function totalCombinedWeight() external view returns (uint256) { return _total_combined_weight; } // Total 'balance' used for calculating the percent of the pool the account owns // Takes into account the locked stake time multiplier and veFXS multiplier function combinedWeightOf(address account) external view returns (uint256) { return _combined_weights[account]; } // Calculated the combined weight for an account function calcCurCombinedWeight(address account) public virtual view returns ( uint256 old_combined_weight, uint256 new_vefxs_multiplier, uint256 new_combined_weight ) { revert("Need cCCW logic"); } // ------ LOCK RELATED ------ // Multiplier amount, given the length of the lock function lockMultiplier(uint256 secs) public view returns (uint256) { // return Math.min( // lock_max_multiplier, // uint256(MULTIPLIER_PRECISION) + ( // (secs * (lock_max_multiplier - MULTIPLIER_PRECISION)) / lock_time_for_max_multiplier // ) // ) ; return Math.min( lock_max_multiplier, (secs * lock_max_multiplier) / lock_time_for_max_multiplier ) ; } // ------ FRAX RELATED ------ function userStakedFrax(address account) public view returns (uint256) { return (fraxPerLPStored * _locked_liquidity[account]) / MULTIPLIER_PRECISION; } function proxyStakedFrax(address proxy_address) public view returns (uint256) { return (fraxPerLPStored * proxy_lp_balances[proxy_address]) / MULTIPLIER_PRECISION; } // Max LP that can get max veFXS boosted for a given address at its current veFXS balance function maxLPForMaxBoost(address account) external view returns (uint256) { return (veFXS.balanceOf(account) * MULTIPLIER_PRECISION * MULTIPLIER_PRECISION) / (vefxs_per_frax_for_max_boost * fraxPerLPStored); } // Meant to be overridden function fraxPerLPToken() public virtual view returns (uint256) { revert("Need fPLPT logic"); } // ------ veFXS RELATED ------ function minVeFXSForMaxBoost(address account) public view returns (uint256) { return (userStakedFrax(account) * vefxs_per_frax_for_max_boost) / MULTIPLIER_PRECISION; } function minVeFXSForMaxBoostProxy(address proxy_address) public view returns (uint256) { return (proxyStakedFrax(proxy_address) * vefxs_per_frax_for_max_boost) / MULTIPLIER_PRECISION; } function getProxyFor(address addr) public view returns (address){ if (valid_vefxs_proxies[addr]) { // If addr itself is a proxy, return that. // If it farms itself directly, it should use the shared LP tally in proxyStakedFrax return addr; } else { // Otherwise, return the proxy, or address(0) return staker_designated_proxies[addr]; } } function veFXSMultiplier(address account) public view returns (uint256 vefxs_multiplier) { // Use either the user's or their proxy's veFXS balance uint256 vefxs_bal_to_use = 0; address the_proxy = getProxyFor(account); vefxs_bal_to_use = (the_proxy == address(0)) ? veFXS.balanceOf(account) : veFXS.balanceOf(the_proxy); // First option based on fraction of total veFXS supply, with an added scale factor uint256 mult_optn_1 = (vefxs_bal_to_use * vefxs_max_multiplier * vefxs_boost_scale_factor) / (veFXS.totalSupply() * MULTIPLIER_PRECISION); // Second based on old method, where the amount of FRAX staked comes into play uint256 mult_optn_2; { uint256 veFXS_needed_for_max_boost; // Need to use proxy-wide FRAX balance if applicable, to prevent exploiting veFXS_needed_for_max_boost = (the_proxy == address(0)) ? minVeFXSForMaxBoost(account) : minVeFXSForMaxBoostProxy(the_proxy); if (veFXS_needed_for_max_boost > 0){ uint256 user_vefxs_fraction = (vefxs_bal_to_use * MULTIPLIER_PRECISION) / veFXS_needed_for_max_boost; mult_optn_2 = (user_vefxs_fraction * vefxs_max_multiplier) / MULTIPLIER_PRECISION; } else mult_optn_2 = 0; // This will happen with the first stake, when user_staked_frax is 0 } // Select the higher of the two vefxs_multiplier = (mult_optn_1 > mult_optn_2 ? mult_optn_1 : mult_optn_2); // Cap the boost to the vefxs_max_multiplier if (vefxs_multiplier > vefxs_max_multiplier) vefxs_multiplier = vefxs_max_multiplier; } /* =============== MUTATIVE FUNCTIONS =============== */ // Proxy can allow a staker to use their veFXS balance (the staker will have to reciprocally toggle them too) // Must come before stakerSetVeFXSProxy // CALLED BY PROXY function proxyToggleStaker(address staker_address) external { require(valid_vefxs_proxies[msg.sender], "Invalid proxy"); proxy_allowed_stakers[msg.sender][staker_address] = !proxy_allowed_stakers[msg.sender][staker_address]; // Disable the staker's set proxy if it was the toggler and is currently on if (staker_designated_proxies[staker_address] == msg.sender){ staker_designated_proxies[staker_address] = address(0); // Remove the LP as well proxy_lp_balances[msg.sender] -= _locked_liquidity[staker_address]; } } // Staker can allow a veFXS proxy (the proxy will have to toggle them first) // CALLED BY STAKER function stakerSetVeFXSProxy(address proxy_address) external { require(valid_vefxs_proxies[proxy_address], "Invalid proxy"); require(proxy_allowed_stakers[proxy_address][msg.sender], "Proxy has not allowed you yet"); // Corner case sanity check to make sure LP isn't double counted address old_proxy_addr = staker_designated_proxies[msg.sender]; if (old_proxy_addr != address(0)) { // Remove the LP count from the old proxy proxy_lp_balances[old_proxy_addr] -= _locked_liquidity[msg.sender]; } // Set the new proxy staker_designated_proxies[msg.sender] = proxy_address; // Add the the LP as well proxy_lp_balances[proxy_address] += _locked_liquidity[msg.sender]; } // ------ STAKING ------ // In children... // ------ WITHDRAWING ------ // In children... // ------ REWARDS SYNCING ------ function updateRewardAndBalance(address account, bool sync_too) public { // Need to retro-adjust some things if the period hasn't been renewed, then start a new one if (sync_too){ sync(); } if (account != address(0)) { // To keep the math correct, the user's combined weight must be recomputed to account for their // ever-changing veFXS balance. ( uint256 old_combined_weight, uint256 new_vefxs_multiplier, uint256 new_combined_weight ) = calcCurCombinedWeight(account); // Calculate the earnings first _syncEarned(account); // Update the user's stored veFXS multipliers _vefxsMultiplierStored[account] = new_vefxs_multiplier; // Update the user's and the global combined weights if (new_combined_weight >= old_combined_weight) { uint256 weight_diff = new_combined_weight - old_combined_weight; _total_combined_weight = _total_combined_weight + weight_diff; _combined_weights[account] = old_combined_weight + weight_diff; } else { uint256 weight_diff = old_combined_weight - new_combined_weight; _total_combined_weight = _total_combined_weight - weight_diff; _combined_weights[account] = old_combined_weight - weight_diff; } } } function _syncEarned(address account) internal { if (account != address(0)) { // Calculate the earnings uint256[] memory earned_arr = earned(account); // Update the rewards array for (uint256 i = 0; i < earned_arr.length; i++){ rewards[account][i] = earned_arr[i]; } // Update the rewards paid array for (uint256 i = 0; i < earned_arr.length; i++){ userRewardsPerTokenPaid[account][i] = rewardsPerTokenStored[i]; } } } // ------ REWARDS CLAIMING ------ function getRewardExtraLogic(address destination_address) public nonReentrant { require(rewardsCollectionPaused == false, "Rewards collection paused"); return _getRewardExtraLogic(msg.sender, destination_address); } function _getRewardExtraLogic(address rewardee, address destination_address) internal virtual { revert("Need gREL logic"); } // Two different getReward functions are needed because of delegateCall and msg.sender issues // For backwards-compatibility function getReward(address destination_address) external nonReentrant returns (uint256[] memory) { return _getReward(msg.sender, destination_address, true); } function getReward2(address destination_address, bool claim_extra_too) external nonReentrant returns (uint256[] memory) { return _getReward(msg.sender, destination_address, claim_extra_too); } // No withdrawer == msg.sender check needed since this is only internally callable function _getReward(address rewardee, address destination_address, bool do_extra_logic) internal updateRewardAndBalanceMdf(rewardee, true) returns (uint256[] memory rewards_before) { // Update the last reward claim time first, as an extra reentrancy safeguard lastRewardClaimTime[rewardee] = block.timestamp; // Make sure rewards collection isn't paused require(rewardsCollectionPaused == false, "Rewards collection paused"); // Update the rewards array and distribute rewards rewards_before = new uint256[](rewardTokens.length); for (uint256 i = 0; i < rewardTokens.length; i++){ rewards_before[i] = rewards[rewardee][i]; rewards[rewardee][i] = 0; if (rewards_before[i] > 0) { TransferHelper.safeTransfer(rewardTokens[i], destination_address, rewards_before[i]); emit RewardPaid(rewardee, rewards_before[i], rewardTokens[i], destination_address); } } // Handle additional reward logic if (do_extra_logic) { _getRewardExtraLogic(rewardee, destination_address); } } // ------ FARM SYNCING ------ // If the period expired, renew it function retroCatchUp() internal { // Pull in rewards from the rewards distributor, if applicable for (uint256 i = 0; i < rewardDistributors.length; i++){ address reward_distributor_address = rewardDistributors[i]; if (reward_distributor_address != address(0)) { IFraxGaugeFXSRewardsDistributor(reward_distributor_address).distributeReward(address(this)); } } // Ensure the provided reward amount is not more than the balance in the contract. // This keeps the reward rate in the right range, preventing overflows due to // very high values of rewardRate in the earned and rewardsPerToken functions; // Reward + leftover must be less than 2^256 / 10^18 to avoid overflow. uint256 num_periods_elapsed = uint256(block.timestamp - periodFinish) / rewardsDuration; // Floor division to the nearest period // Make sure there are enough tokens to renew the reward period for (uint256 i = 0; i < rewardTokens.length; i++){ require((rewardRates(i) * rewardsDuration * (num_periods_elapsed + 1)) <= IERC20(rewardTokens[i]).balanceOf(address(this)), string(abi.encodePacked("Not enough reward tokens available: ", rewardTokens[i])) ); } // uint256 old_lastUpdateTime = lastUpdateTime; // uint256 new_lastUpdateTime = block.timestamp; // lastUpdateTime = periodFinish; periodFinish = periodFinish + ((num_periods_elapsed + 1) * rewardsDuration); // Update the rewards and time _updateStoredRewardsAndTime(); // Update the fraxPerLPStored fraxPerLPStored = fraxPerLPToken(); // Pull in rewards and set the reward rate for one week, based off of that // If the rewards get messed up for some reason, set this to 0 and it will skip // if (rewardRatesManual[1] != 0 && rewardRatesManual[2] != 0) { // // CRV & CVX // // ==================================== // uint256 crv_before = ERC20(rewardTokens[1]).balanceOf(address(this)); // uint256 cvx_before = ERC20(rewardTokens[2]).balanceOf(address(this)); // IConvexBaseRewardPool(0x329cb014b562d5d42927cfF0dEdF4c13ab0442EF).getReward( // address(this), // true // ); // uint256 crv_after = ERC20(rewardTokens[1]).balanceOf(address(this)); // uint256 cvx_after = ERC20(rewardTokens[2]).balanceOf(address(this)); // // Set the new reward rate // rewardRatesManual[1] = (crv_after - crv_before) / rewardsDuration; // rewardRatesManual[2] = (cvx_after - cvx_before) / rewardsDuration; // } } function _updateStoredRewardsAndTime() internal { // Get the rewards uint256[] memory rewards_per_token = rewardsPerToken(); // Update the rewardsPerTokenStored for (uint256 i = 0; i < rewardsPerTokenStored.length; i++){ rewardsPerTokenStored[i] = rewards_per_token[i]; } // Update the last stored time lastUpdateTime = lastTimeRewardApplicable(); } function sync_gauge_weights(bool force_update) public { // Loop through the gauge controllers for (uint256 i = 0; i < gaugeControllers.length; i++){ address gauge_controller_address = gaugeControllers[i]; if (gauge_controller_address != address(0)) { if (force_update || (block.timestamp > last_gauge_time_totals[i])){ // Update the gauge_relative_weight last_gauge_relative_weights[i] = IFraxGaugeController(gauge_controller_address).gauge_relative_weight_write(address(this), block.timestamp); last_gauge_time_totals[i] = IFraxGaugeController(gauge_controller_address).time_total(); } } } } function sync() public { // Sync the gauge weight, if applicable sync_gauge_weights(false); // Update the fraxPerLPStored fraxPerLPStored = fraxPerLPToken(); if (block.timestamp >= periodFinish) { retroCatchUp(); } else { _updateStoredRewardsAndTime(); } } /* ========== RESTRICTED FUNCTIONS - Curator callable ========== */ // ------ FARM SYNCING ------ // In children... // ------ PAUSES ------ function setPauses( bool _stakingPaused, bool _withdrawalsPaused, bool _rewardsCollectionPaused ) external onlyByOwnGov { stakingPaused = _stakingPaused; withdrawalsPaused = _withdrawalsPaused; rewardsCollectionPaused = _rewardsCollectionPaused; } /* ========== RESTRICTED FUNCTIONS - Owner or timelock only ========== */ function unlockStakes() external onlyByOwnGov { stakesUnlocked = !stakesUnlocked; } // Adds a valid veFXS proxy address function toggleValidVeFXSProxy(address _proxy_addr) external onlyByOwnGov { valid_vefxs_proxies[_proxy_addr] = !valid_vefxs_proxies[_proxy_addr]; } // Added to support recovering LP Rewards and other mistaken tokens from other systems to be distributed to holders function recoverERC20(address tokenAddress, uint256 tokenAmount) external onlyTknMgrs(tokenAddress) { // Check if the desired token is a reward token bool isRewardToken = false; for (uint256 i = 0; i < rewardTokens.length; i++){ if (rewardTokens[i] == tokenAddress) { isRewardToken = true; break; } } // Only the reward managers can take back their reward tokens // Also, other tokens, like the staking token, airdrops, or accidental deposits, can be withdrawn by the owner if ( (isRewardToken && rewardManagers[tokenAddress] == msg.sender) || (!isRewardToken && (msg.sender == owner)) ) { TransferHelper.safeTransfer(tokenAddress, msg.sender, tokenAmount); return; } // If none of the above conditions are true else { revert("No valid tokens to recover"); } } function setMiscVariables( uint256[6] memory _misc_vars // [0]: uint256 _lock_max_multiplier, // [1] uint256 _vefxs_max_multiplier, // [2] uint256 _vefxs_per_frax_for_max_boost, // [3] uint256 _vefxs_boost_scale_factor, // [4] uint256 _lock_time_for_max_multiplier, // [5] uint256 _lock_time_min ) external onlyByOwnGov { require(_misc_vars[0] >= MULTIPLIER_PRECISION, "Must be >= MUL PREC"); require((_misc_vars[1] >= 0) && (_misc_vars[2] >= 0) && (_misc_vars[3] >= 0), "Must be >= 0"); require((_misc_vars[4] >= 1) && (_misc_vars[5] >= 1), "Must be >= 1"); lock_max_multiplier = _misc_vars[0]; vefxs_max_multiplier = _misc_vars[1]; vefxs_per_frax_for_max_boost = _misc_vars[2]; vefxs_boost_scale_factor = _misc_vars[3]; lock_time_for_max_multiplier = _misc_vars[4]; lock_time_min = _misc_vars[5]; } // The owner or the reward token managers can set reward rates function setRewardVars(address reward_token_address, uint256 _new_rate, address _gauge_controller_address, address _rewards_distributor_address) external onlyTknMgrs(reward_token_address) { rewardRatesManual[rewardTokenAddrToIdx[reward_token_address]] = _new_rate; gaugeControllers[rewardTokenAddrToIdx[reward_token_address]] = _gauge_controller_address; rewardDistributors[rewardTokenAddrToIdx[reward_token_address]] = _rewards_distributor_address; } // The owner or the reward token managers can change managers function changeTokenManager(address reward_token_address, address new_manager_address) external onlyTknMgrs(reward_token_address) { rewardManagers[reward_token_address] = new_manager_address; } /* ========== EVENTS ========== */ event RewardPaid(address indexed user, uint256 amount, address token_address, address destination_address); /* ========== A CHICKEN ========== */ // // ,~. // ,-'__ `-, // {,-' `. } ,') // ,( a ) `-.__ ,',')~, // <=.) ( `-.__,==' ' ' '} // ( ) /) // `-'\ , ) // | \ `~. / // \ `._ \ / // \ `._____,' ,' // `-. ,' // `-._ _,-' // 77jj' // //_|| // __//--'/` // ,--'/` ' // // [hjw] https://textart.io/art/vw6Sa3iwqIRGkZsN1BC2vweF/chicken } // File contracts/Misc_AMOs/convex/IConvexStakingWrapperFrax.sol interface IConvexStakingWrapperFrax { function addRewards() external; function allowance(address owner, address spender) external view returns (uint256); function approve(address spender, uint256 amount) external returns (bool); function balanceOf(address account) external view returns (uint256); function collateralVault() external view returns (address); function convexBooster() external view returns (address); function convexPool() external view returns (address); function convexPoolId() external view returns (uint256); function convexToken() external view returns (address); function crv() external view returns (address); function curveToken() external view returns (address); function cvx() external view returns (address); function decimals() external view returns (uint8); function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool); function deposit(uint256 _amount, address _to) external; // function earned(address _account) external view returns (tuple[] memory claimable); function getReward(address _account, address _forwardTo) external; function getReward(address _account) external; function increaseAllowance(address spender, uint256 addedValue) external returns (bool); function initialize(address _curveToken, address _convexToken, address _convexPool, uint256 _poolId, address _vault) external; function isInit() external view returns (bool); function isShutdown() external view returns (bool); function name() external view returns (string memory); function owner() external view returns (address); function registeredRewards(address) external view returns (uint256); function renounceOwnership() external; function rewardLength() external view returns (uint256); function rewards(uint256) external view returns (address reward_token, address reward_pool, uint128 reward_integral, uint128 reward_remaining); function setApprovals() external; function setVault(address _vault) external; function shutdown() external; function stake(uint256 _amount, address _to) external; function symbol() external view returns (string memory); function totalBalanceOf(address _account) external view returns (uint256); function totalSupply() external view returns (uint256); function transfer(address recipient, uint256 amount) external returns (bool); function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); function transferOwnership(address newOwner) external; function user_checkpoint(address[2] memory _accounts) external returns (bool); function withdraw(uint256 _amount) external; function withdrawAndUnwrap(uint256 _amount) external; } // File contracts/Misc_AMOs/convex/IDepositToken.sol interface IDepositToken { function allowance(address owner, address spender) external view returns (uint256); function approve(address spender, uint256 amount) external returns (bool); function balanceOf(address account) external view returns (uint256); function burn(address _from, uint256 _amount) external; function decimals() external view returns (uint8); function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool); function increaseAllowance(address spender, uint256 addedValue) external returns (bool); function mint(address _to, uint256 _amount) external; function name() external view returns (string memory); function operator() external view returns (address); function symbol() external view returns (string memory); function totalSupply() external view returns (uint256); function transfer(address recipient, uint256 amount) external returns (bool); function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); } // File contracts/Misc_AMOs/curve/I2pool.sol interface I2pool { function decimals() external view returns (uint256); function transfer(address _to, uint256 _value) external returns (bool); function transferFrom(address _from, address _to, uint256 _value) external returns (bool); function approve(address _spender, uint256 _value) external returns (bool); function A() external view returns (uint256); function A_precise() external view returns (uint256); function get_virtual_price() external view returns (uint256); function lp_price() external view returns (uint256); function calc_token_amount(uint256[2] memory _amounts, bool _is_deposit) external view returns (uint256); function add_liquidity(uint256[2] memory _amounts, uint256 _min_mint_amount) external returns (uint256); function get_dy(int128 i, int128 j, uint256 _dx) external view returns (uint256); function exchange(int128 i, int128 j, uint256 _dx, uint256 _min_dy) external returns (uint256); function remove_liquidity(uint256 _amount, uint256[2] memory _min_amounts) external returns (uint256[2] memory); function remove_liquidity_imbalance(uint256[2] memory _amounts, uint256 _max_burn_amount) external returns (uint256); function calc_withdraw_one_coin(uint256 _token_amount, int128 i) external view returns (uint256); function remove_liquidity_one_coin(uint256 _token_amount, int128 i, uint256 _min_amount) external returns (uint256); function ramp_A(uint256 _future_A, uint256 _future_time) external; function stop_ramp_A() external; function commit_new_fee(uint256 _new_fee, uint256 _new_admin_fee) external; function apply_new_fee() external; function revert_new_parameters() external; function commit_transfer_ownership(address _owner) external; function apply_transfer_ownership() external; function revert_transfer_ownership() external; function admin_balances(uint256 i) external view returns (uint256); function withdraw_admin_fees() external; function donate_admin_fees() external; function kill_me() external; function unkill_me() external; function coins(uint256 arg0) external view returns (address); function balances(uint256 arg0) external view returns (uint256); function fee() external view returns (uint256); function admin_fee() external view returns (uint256); function owner() external view returns (address); function initial_A() external view returns (uint256); function future_A() external view returns (uint256); function initial_A_time() external view returns (uint256); function future_A_time() external view returns (uint256); function admin_actions_deadline() external view returns (uint256); function transfer_ownership_deadline() external view returns (uint256); function future_fee() external view returns (uint256); function future_admin_fee() external view returns (uint256); function future_owner() external view returns (address); function name() external view returns (string memory); function symbol() external view returns (string memory); function balanceOf(address arg0) external view returns (uint256); function allowance(address arg0, address arg1) external view returns (uint256); function totalSupply() external view returns (uint256); } // File contracts/Misc_AMOs/curve/I2poolToken.sol interface I2poolToken { function decimals() external view returns (uint256); function transfer(address _to, uint256 _value) external returns (bool); function transferFrom(address _from, address _to, uint256 _value) external returns (bool); function approve(address _spender, uint256 _value) external returns (bool); function increaseAllowance(address _spender, uint256 _added_value) external returns (bool); function decreaseAllowance(address _spender, uint256 _subtracted_value) external returns (bool); function mint(address _to, uint256 _value) external returns (bool); function burnFrom(address _to, uint256 _value) external returns (bool); function set_minter(address _minter) external; function set_name(string memory _name, string memory _symbol) external; function name() external view returns (string memory); function symbol() external view returns (string memory); function balanceOf(address arg0) external view returns (uint256); function allowance(address arg0, address arg1) external view returns (uint256); function totalSupply() external view returns (uint256); function minter() external view returns (address); } // File contracts/Staking/FraxUnifiedFarm_ERC20.sol // ==================================================================== // | ______ _______ | // | / _____________ __ __ / ____(_____ ____ _____ ________ | // | / /_ / ___/ __ `| |/_/ / /_ / / __ \/ __ `/ __ \/ ___/ _ \ | // | / __/ / / / /_/ _> < / __/ / / / / / /_/ / / / / /__/ __/ | // | /_/ /_/ \__,_/_/|_| /_/ /_/_/ /_/\__,_/_/ /_/\___/\___/ | // | | // ==================================================================== // ======================= FraxUnifiedFarm_ERC20 ====================== // ==================================================================== // For ERC20 Tokens // Uses FraxUnifiedFarmTemplate.sol // -------------------- VARIES -------------------- // Convex wrappers // Fraxswap // import '../Fraxswap/core/interfaces/IFraxswapPair.sol'; // G-UNI // import "../Misc_AMOs/gelato/IGUniPool.sol"; // mStable // import '../Misc_AMOs/mstable/IFeederPool.sol'; // StakeDAO sdETH-FraxPut // import '../Misc_AMOs/stakedao/IOpynPerpVault.sol'; // StakeDAO Vault // import '../Misc_AMOs/stakedao/IStakeDaoVault.sol'; // Uniswap V2 // import '../Uniswap/Interfaces/IUniswapV2Pair.sol'; // Vesper // import '../Misc_AMOs/vesper/IVPool.sol'; // ------------------------------------------------ contract FraxUnifiedFarm_ERC20 is FraxUnifiedFarmTemplate { /* ========== STATE VARIABLES ========== */ // -------------------- COMMON -------------------- bool internal frax_is_token0; // -------------------- VARIES -------------------- // Convex stkcvxFPIFRAX, stkcvxFRAXBP, etc IConvexStakingWrapperFrax public stakingToken; I2poolToken public curveToken; I2pool public curvePool; // Fraxswap // IFraxswapPair public stakingToken; // G-UNI // IGUniPool public stakingToken; // mStable // IFeederPool public stakingToken; // sdETH-FraxPut Vault // IOpynPerpVault public stakingToken; // StakeDAO Vault // IStakeDaoVault public stakingToken; // Uniswap V2 // IUniswapV2Pair public stakingToken; // Vesper // IVPool public stakingToken; // ------------------------------------------------ // Stake tracking mapping(address => LockedStake[]) public lockedStakes; /* ========== STRUCTS ========== */ // Struct for the stake struct LockedStake { bytes32 kek_id; uint256 start_timestamp; uint256 liquidity; uint256 ending_timestamp; uint256 lock_multiplier; // 6 decimals of precision. 1x = 1000000 } /* ========== CONSTRUCTOR ========== */ constructor ( address _owner, address[] memory _rewardTokens, address[] memory _rewardManagers, uint256[] memory _rewardRatesManual, address[] memory _gaugeControllers, address[] memory _rewardDistributors, address _stakingToken ) FraxUnifiedFarmTemplate(_owner, _rewardTokens, _rewardManagers, _rewardRatesManual, _gaugeControllers, _rewardDistributors) { // -------------------- VARIES -------------------- // Fraxswap // stakingToken = IFraxswapPair(_stakingToken); // address token0 = stakingToken.token0(); // frax_is_token0 = (token0 == frax_address); // G-UNI // stakingToken = IGUniPool(_stakingToken); // address token0 = address(stakingToken.token0()); // frax_is_token0 = (token0 == frax_address); // mStable // stakingToken = IFeederPool(_stakingToken); // StakeDAO sdETH-FraxPut Vault // stakingToken = IOpynPerpVault(_stakingToken); // StakeDAO Vault // stakingToken = IStakeDaoVault(_stakingToken); // Uniswap V2 // stakingToken = IUniswapV2Pair(_stakingToken); // address token0 = stakingToken.token0(); // if (token0 == frax_address) frax_is_token0 = true; // else frax_is_token0 = false; // Vesper // stakingToken = IVPool(_stakingToken); } /* ============= VIEWS ============= */ // ------ FRAX RELATED ------ function fraxPerLPToken() public virtual view override returns (uint256) { // Get the amount of FRAX 'inside' of the lp tokens uint256 frax_per_lp_token; // Convex stkcvxFPIFRAX and stkcvxFRAXBP only // ============================================ // { // // Half of the LP is FRAXBP // // Using 0.5 * virtual price for gas savings // frax_per_lp_token = curvePool.get_virtual_price() / 2; // } // Convex Stable/FRAXBP // ============================================ // { // // Half of the LP is FRAXBP. Half of that should be FRAX. // // Using 0.25 * virtual price for gas savings // frax_per_lp_token = curvePool.get_virtual_price() / 4; // } // Convex Volatile/FRAXBP // ============================================ // { // // Half of the LP is FRAXBP. Half of that should be FRAX. // // Using 0.25 * lp price for gas savings // frax_per_lp_token = curvePool.lp_price() / 4; // } // Fraxswap // ============================================ // { // uint256 total_frax_reserves; // (uint256 _reserve0, uint256 _reserve1, , ,) = (stakingToken.getReserveAfterTwamm(block.timestamp)); // if (frax_is_token0) total_frax_reserves = _reserve0; // else total_frax_reserves = _reserve1; // frax_per_lp_token = (total_frax_reserves * 1e18) / stakingToken.totalSupply(); // } // G-UNI // ============================================ // { // (uint256 reserve0, uint256 reserve1) = stakingToken.getUnderlyingBalances(); // uint256 total_frax_reserves = frax_is_token0 ? reserve0 : reserve1; // frax_per_lp_token = (total_frax_reserves * 1e18) / stakingToken.totalSupply(); // } // mStable // ============================================ // { // uint256 total_frax_reserves; // (, IFeederPool.BassetData memory vaultData) = (stakingToken.getBasset(frax_address)); // total_frax_reserves = uint256(vaultData.vaultBalance); // frax_per_lp_token = (total_frax_reserves * 1e18) / stakingToken.totalSupply(); // } // StakeDAO sdETH-FraxPut Vault // ============================================ // { // uint256 frax3crv_held = stakingToken.totalUnderlyingControlled(); // // Optimistically assume 50/50 FRAX/3CRV ratio in the metapool to save gas // frax_per_lp_token = ((frax3crv_held * 1e18) / stakingToken.totalSupply()) / 2; // } // StakeDAO Vault // ============================================ // { // uint256 frax3crv_held = stakingToken.balance(); // // Optimistically assume 50/50 FRAX/3CRV ratio in the metapool to save gas // frax_per_lp_token = ((frax3crv_held * 1e18) / stakingToken.totalSupply()) / 2; // } // Uniswap V2 // ============================================ // { // uint256 total_frax_reserves; // (uint256 reserve0, uint256 reserve1, ) = (stakingToken.getReserves()); // if (frax_is_token0) total_frax_reserves = reserve0; // else total_frax_reserves = reserve1; // frax_per_lp_token = (total_frax_reserves * 1e18) / stakingToken.totalSupply(); // } // Vesper // ============================================ // frax_per_lp_token = stakingToken.pricePerShare(); return frax_per_lp_token; } // ------ LIQUIDITY AND WEIGHTS ------ function calcCurrLockMultiplier(address account, uint256 stake_idx) public view returns (uint256 midpoint_lock_multiplier) { // Get the stake LockedStake memory thisStake = lockedStakes[account][stake_idx]; // Handles corner case where user never claims for a new stake // Don't want the multiplier going above the max uint256 accrue_start_time; if (lastRewardClaimTime[account] < thisStake.start_timestamp) { accrue_start_time = thisStake.start_timestamp; } else { accrue_start_time = lastRewardClaimTime[account]; } // If the lock is expired if (thisStake.ending_timestamp <= block.timestamp) { // If the lock expired in the time since the last claim, the weight needs to be proportionately averaged this time if (lastRewardClaimTime[account] < thisStake.ending_timestamp){ uint256 time_before_expiry = thisStake.ending_timestamp - accrue_start_time; uint256 time_after_expiry = block.timestamp - thisStake.ending_timestamp; // Average the pre-expiry lock multiplier uint256 pre_expiry_avg_multiplier = lockMultiplier(time_before_expiry / 2); // Get the weighted-average lock_multiplier // uint256 numerator = (pre_expiry_avg_multiplier * time_before_expiry) + (MULTIPLIER_PRECISION * time_after_expiry); uint256 numerator = (pre_expiry_avg_multiplier * time_before_expiry) + (0 * time_after_expiry); midpoint_lock_multiplier = numerator / (time_before_expiry + time_after_expiry); } else { // Otherwise, it needs to just be 1x // midpoint_lock_multiplier = MULTIPLIER_PRECISION; // Otherwise, it needs to just be 0x midpoint_lock_multiplier = 0; } } // If the lock is not expired else { // Decay the lock multiplier based on the time left uint256 avg_time_left; { uint256 time_left_p1 = thisStake.ending_timestamp - accrue_start_time; uint256 time_left_p2 = thisStake.ending_timestamp - block.timestamp; avg_time_left = (time_left_p1 + time_left_p2) / 2; } midpoint_lock_multiplier = lockMultiplier(avg_time_left); } // Sanity check: make sure it never goes above the initial multiplier if (midpoint_lock_multiplier > thisStake.lock_multiplier) midpoint_lock_multiplier = thisStake.lock_multiplier; } // Calculate the combined weight for an account function calcCurCombinedWeight(address account) public override view returns ( uint256 old_combined_weight, uint256 new_vefxs_multiplier, uint256 new_combined_weight ) { // Get the old combined weight old_combined_weight = _combined_weights[account]; // Get the veFXS multipliers // For the calculations, use the midpoint (analogous to midpoint Riemann sum) new_vefxs_multiplier = veFXSMultiplier(account); uint256 midpoint_vefxs_multiplier; if ( (_locked_liquidity[account] == 0 && _combined_weights[account] == 0) || (new_vefxs_multiplier >= _vefxsMultiplierStored[account]) ) { // This is only called for the first stake to make sure the veFXS multiplier is not cut in half // Also used if the user increased or maintained their position midpoint_vefxs_multiplier = new_vefxs_multiplier; } else { // Handles natural decay with a non-increased veFXS position midpoint_vefxs_multiplier = (new_vefxs_multiplier + _vefxsMultiplierStored[account]) / 2; } // Loop through the locked stakes, first by getting the liquidity * lock_multiplier portion new_combined_weight = 0; for (uint256 i = 0; i < lockedStakes[account].length; i++) { LockedStake memory thisStake = lockedStakes[account][i]; // Calculate the midpoint lock multiplier uint256 midpoint_lock_multiplier = calcCurrLockMultiplier(account, i); // Calculate the combined boost uint256 liquidity = thisStake.liquidity; uint256 combined_boosted_amount = liquidity + ((liquidity * (midpoint_lock_multiplier + midpoint_vefxs_multiplier)) / MULTIPLIER_PRECISION); new_combined_weight += combined_boosted_amount; } } // ------ LOCK RELATED ------ // All the locked stakes for a given account function lockedStakesOf(address account) external view returns (LockedStake[] memory) { return lockedStakes[account]; } // Returns the length of the locked stakes for a given account function lockedStakesOfLength(address account) external view returns (uint256) { return lockedStakes[account].length; } // // All the locked stakes for a given account [old-school method] // function lockedStakesOfMultiArr(address account) external view returns ( // bytes32[] memory kek_ids, // uint256[] memory start_timestamps, // uint256[] memory liquidities, // uint256[] memory ending_timestamps, // uint256[] memory lock_multipliers // ) { // for (uint256 i = 0; i < lockedStakes[account].length; i++){ // LockedStake memory thisStake = lockedStakes[account][i]; // kek_ids[i] = thisStake.kek_id; // start_timestamps[i] = thisStake.start_timestamp; // liquidities[i] = thisStake.liquidity; // ending_timestamps[i] = thisStake.ending_timestamp; // lock_multipliers[i] = thisStake.lock_multiplier; // } // } /* =============== MUTATIVE FUNCTIONS =============== */ // ------ STAKING ------ function _getStake(address staker_address, bytes32 kek_id) internal view returns (LockedStake memory locked_stake, uint256 arr_idx) { for (uint256 i = 0; i < lockedStakes[staker_address].length; i++){ if (kek_id == lockedStakes[staker_address][i].kek_id){ locked_stake = lockedStakes[staker_address][i]; arr_idx = i; break; } } require(locked_stake.kek_id == kek_id, "Stake not found"); } // Add additional LPs to an existing locked stake function lockAdditional(bytes32 kek_id, uint256 addl_liq) nonReentrant updateRewardAndBalanceMdf(msg.sender, true) public { // Get the stake and its index (LockedStake memory thisStake, uint256 theArrayIndex) = _getStake(msg.sender, kek_id); // Calculate the new amount uint256 new_amt = thisStake.liquidity + addl_liq; // Checks require(addl_liq >= 0, "Must be positive"); // Pull the tokens from the sender TransferHelper.safeTransferFrom(address(stakingToken), msg.sender, address(this), addl_liq); // Update the stake lockedStakes[msg.sender][theArrayIndex] = LockedStake( kek_id, thisStake.start_timestamp, new_amt, thisStake.ending_timestamp, thisStake.lock_multiplier ); // Update liquidities _total_liquidity_locked += addl_liq; _locked_liquidity[msg.sender] += addl_liq; { address the_proxy = getProxyFor(msg.sender); if (the_proxy != address(0)) proxy_lp_balances[the_proxy] += addl_liq; } // Need to call to update the combined weights updateRewardAndBalance(msg.sender, false); emit LockedAdditional(msg.sender, kek_id, addl_liq); } // Extends the lock of an existing stake function lockLonger(bytes32 kek_id, uint256 new_ending_ts) nonReentrant updateRewardAndBalanceMdf(msg.sender, true) public { // Get the stake and its index (LockedStake memory thisStake, uint256 theArrayIndex) = _getStake(msg.sender, kek_id); // Check require(new_ending_ts > block.timestamp, "Must be in the future"); // Calculate some times uint256 time_left = (thisStake.ending_timestamp > block.timestamp) ? thisStake.ending_timestamp - block.timestamp : 0; uint256 new_secs = new_ending_ts - block.timestamp; // Checks // require(time_left > 0, "Already expired"); require(new_secs > time_left, "Cannot shorten lock time"); require(new_secs >= lock_time_min, "Minimum stake time not met"); require(new_secs <= lock_time_for_max_multiplier, "Trying to lock for too long"); // Update the stake lockedStakes[msg.sender][theArrayIndex] = LockedStake( kek_id, block.timestamp, thisStake.liquidity, new_ending_ts, lockMultiplier(new_secs) ); // Need to call to update the combined weights updateRewardAndBalance(msg.sender, false); emit LockedLonger(msg.sender, kek_id, new_secs, block.timestamp, new_ending_ts); } // Two different stake functions are needed because of delegateCall and msg.sender issues (important for proxies) function stakeLocked(uint256 liquidity, uint256 secs) nonReentrant external returns (bytes32) { return _stakeLocked(msg.sender, msg.sender, liquidity, secs, block.timestamp); } // If this were not internal, and source_address had an infinite approve, this could be exploitable // (pull funds from source_address and stake for an arbitrary staker_address) function _stakeLocked( address staker_address, address source_address, uint256 liquidity, uint256 secs, uint256 start_timestamp ) internal updateRewardAndBalanceMdf(staker_address, true) returns (bytes32) { require(stakingPaused == false, "Staking paused"); require(secs >= lock_time_min, "Minimum stake time not met"); require(secs <= lock_time_for_max_multiplier,"Trying to lock for too long"); // Pull in the required token(s) // Varies per farm TransferHelper.safeTransferFrom(address(stakingToken), source_address, address(this), liquidity); // Get the lock multiplier and kek_id uint256 lock_multiplier = lockMultiplier(secs); bytes32 kek_id = keccak256(abi.encodePacked(staker_address, start_timestamp, liquidity, _locked_liquidity[staker_address])); // Create the locked stake lockedStakes[staker_address].push(LockedStake( kek_id, start_timestamp, liquidity, start_timestamp + secs, lock_multiplier )); // Update liquidities _total_liquidity_locked += liquidity; _locked_liquidity[staker_address] += liquidity; { address the_proxy = getProxyFor(staker_address); if (the_proxy != address(0)) proxy_lp_balances[the_proxy] += liquidity; } // Need to call again to make sure everything is correct updateRewardAndBalance(staker_address, false); emit StakeLocked(staker_address, liquidity, secs, kek_id, source_address); return kek_id; } // ------ WITHDRAWING ------ // Two different withdrawLocked functions are needed because of delegateCall and msg.sender issues (important for proxies) function withdrawLocked(bytes32 kek_id, address destination_address) nonReentrant external returns (uint256) { require(withdrawalsPaused == false, "Withdrawals paused"); return _withdrawLocked(msg.sender, destination_address, kek_id); } // No withdrawer == msg.sender check needed since this is only internally callable and the checks are done in the wrapper function _withdrawLocked( address staker_address, address destination_address, bytes32 kek_id ) internal returns (uint256) { // Collect rewards first and then update the balances _getReward(staker_address, destination_address, true); // Get the stake and its index (LockedStake memory thisStake, uint256 theArrayIndex) = _getStake(staker_address, kek_id); require(block.timestamp >= thisStake.ending_timestamp || stakesUnlocked == true, "Stake is still locked!"); uint256 liquidity = thisStake.liquidity; if (liquidity > 0) { // Give the tokens to the destination_address // Should throw if insufficient balance TransferHelper.safeTransfer(address(stakingToken), destination_address, liquidity); // Update liquidities _total_liquidity_locked -= liquidity; _locked_liquidity[staker_address] -= liquidity; { address the_proxy = getProxyFor(staker_address); if (the_proxy != address(0)) proxy_lp_balances[the_proxy] -= liquidity; } // Remove the stake from the array delete lockedStakes[staker_address][theArrayIndex]; // Need to call again to make sure everything is correct updateRewardAndBalance(staker_address, false); emit WithdrawLocked(staker_address, liquidity, kek_id, destination_address); } return liquidity; } function _getRewardExtraLogic(address rewardee, address destination_address) internal override { // Do nothing } /* ========== RESTRICTED FUNCTIONS - Owner or timelock only ========== */ // Inherited... /* ========== EVENTS ========== */ event LockedAdditional(address indexed user, bytes32 kek_id, uint256 amount); event LockedLonger(address indexed user, bytes32 kek_id, uint256 new_secs, uint256 new_start_ts, uint256 new_end_ts); event StakeLocked(address indexed user, uint256 amount, uint256 secs, bytes32 kek_id, address source_address); event WithdrawLocked(address indexed user, uint256 liquidity, bytes32 kek_id, address destination_address); } // File contracts/Staking/Variants/FraxUnifiedFarm_ERC20_Convex_FRAXBP_Volatile.sol contract FraxUnifiedFarm_ERC20_Convex_FRAXBP_Volatile is FraxUnifiedFarm_ERC20 { constructor ( address _owner, address[] memory _rewardTokens, address[] memory _rewardManagers, uint256[] memory _rewardRates, address[] memory _gaugeControllers, address[] memory _rewardDistributors, address _stakingToken ) FraxUnifiedFarm_ERC20(_owner , _rewardTokens, _rewardManagers, _rewardRates, _gaugeControllers, _rewardDistributors, _stakingToken) { // Convex stkcvxFPIFRAX and stkcvxFRAXBP. Also Volatile/FRAXBP stakingToken = IConvexStakingWrapperFrax(_stakingToken); curveToken = I2poolToken(stakingToken.curveToken()); curvePool = I2pool(curveToken.minter()); address token0 = curvePool.coins(0); frax_is_token0 = (token0 == frax_address); } function fraxPerLPToken() public view override returns (uint256) { // Get the amount of FRAX 'inside' of the lp tokens uint256 frax_per_lp_token; // Convex Volatile/FRAXBP // ============================================ { // Half of the LP is FRAXBP. Half of that should be FRAX. // Using 0.25 * lp price for gas savings frax_per_lp_token = curvePool.lp_price() / 4; } return frax_per_lp_token; } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address[]","name":"_rewardTokens","type":"address[]"},{"internalType":"address[]","name":"_rewardManagers","type":"address[]"},{"internalType":"uint256[]","name":"_rewardRates","type":"uint256[]"},{"internalType":"address[]","name":"_gaugeControllers","type":"address[]"},{"internalType":"address[]","name":"_rewardDistributors","type":"address[]"},{"internalType":"address","name":"_stakingToken","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"bytes32","name":"kek_id","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"LockedAdditional","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"bytes32","name":"kek_id","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"new_secs","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"new_start_ts","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"new_end_ts","type":"uint256"}],"name":"LockedLonger","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerNominated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"token_address","type":"address"},{"indexed":false,"internalType":"address","name":"destination_address","type":"address"}],"name":"RewardPaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"secs","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"kek_id","type":"bytes32"},{"indexed":false,"internalType":"address","name":"source_address","type":"address"}],"name":"StakeLocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"liquidity","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"kek_id","type":"bytes32"},{"indexed":false,"internalType":"address","name":"destination_address","type":"address"}],"name":"WithdrawLocked","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"calcCurCombinedWeight","outputs":[{"internalType":"uint256","name":"old_combined_weight","type":"uint256"},{"internalType":"uint256","name":"new_vefxs_multiplier","type":"uint256"},{"internalType":"uint256","name":"new_combined_weight","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"stake_idx","type":"uint256"}],"name":"calcCurrLockMultiplier","outputs":[{"internalType":"uint256","name":"midpoint_lock_multiplier","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"reward_token_address","type":"address"},{"internalType":"address","name":"new_manager_address","type":"address"}],"name":"changeTokenManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"combinedWeightOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"curvePool","outputs":[{"internalType":"contract I2pool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"curveToken","outputs":[{"internalType":"contract I2poolToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"earned","outputs":[{"internalType":"uint256[]","name":"new_earned","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fraxPerLPStored","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fraxPerLPToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllRewardTokens","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"getProxyFor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"destination_address","type":"address"}],"name":"getReward","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"destination_address","type":"address"},{"internalType":"bool","name":"claim_extra_too","type":"bool"}],"name":"getReward2","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"destination_address","type":"address"}],"name":"getRewardExtraLogic","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getRewardForDuration","outputs":[{"internalType":"uint256[]","name":"rewards_per_duration_arr","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"caller_addr","type":"address"},{"internalType":"address","name":"reward_token_addr","type":"address"}],"name":"isTokenManagerFor","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"lastRewardClaimTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastUpdateTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"kek_id","type":"bytes32"},{"internalType":"uint256","name":"addl_liq","type":"uint256"}],"name":"lockAdditional","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"kek_id","type":"bytes32"},{"internalType":"uint256","name":"new_ending_ts","type":"uint256"}],"name":"lockLonger","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"secs","type":"uint256"}],"name":"lockMultiplier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lock_max_multiplier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lock_time_for_max_multiplier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lock_time_min","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"lockedLiquidityOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"lockedStakes","outputs":[{"internalType":"bytes32","name":"kek_id","type":"bytes32"},{"internalType":"uint256","name":"start_timestamp","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"ending_timestamp","type":"uint256"},{"internalType":"uint256","name":"lock_multiplier","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"lockedStakesOf","outputs":[{"components":[{"internalType":"bytes32","name":"kek_id","type":"bytes32"},{"internalType":"uint256","name":"start_timestamp","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"ending_timestamp","type":"uint256"},{"internalType":"uint256","name":"lock_multiplier","type":"uint256"}],"internalType":"struct FraxUnifiedFarm_ERC20.LockedStake[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"lockedStakesOfLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"maxLPForMaxBoost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"minVeFXSForMaxBoost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"proxy_address","type":"address"}],"name":"minVeFXSForMaxBoostProxy","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"nominateNewOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"nominatedOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"periodFinish","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"proxy_address","type":"address"}],"name":"proxyStakedFrax","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"staker_address","type":"address"}],"name":"proxyToggleStaker","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"proxy_lp_balances","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"recoverERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewardManagers","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"token_idx","type":"uint256"}],"name":"rewardRates","outputs":[{"internalType":"uint256","name":"rwd_rate","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewardTokenAddrToIdx","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsPerToken","outputs":[{"internalType":"uint256[]","name":"newRewardsPerTokenStored","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[6]","name":"_misc_vars","type":"uint256[6]"}],"name":"setMiscVariables","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_stakingPaused","type":"bool"},{"internalType":"bool","name":"_withdrawalsPaused","type":"bool"},{"internalType":"bool","name":"_rewardsCollectionPaused","type":"bool"}],"name":"setPauses","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"reward_token_address","type":"address"},{"internalType":"uint256","name":"_new_rate","type":"uint256"},{"internalType":"address","name":"_gauge_controller_address","type":"address"},{"internalType":"address","name":"_rewards_distributor_address","type":"address"}],"name":"setRewardVars","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"secs","type":"uint256"}],"name":"stakeLocked","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"proxy_address","type":"address"}],"name":"stakerSetVeFXSProxy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"staker_designated_proxies","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakesUnlocked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakingToken","outputs":[{"internalType":"contract IConvexStakingWrapperFrax","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sync","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"force_update","type":"bool"}],"name":"sync_gauge_weights","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_proxy_addr","type":"address"}],"name":"toggleValidVeFXSProxy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalCombinedWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalLiquidityLocked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unlockStakes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bool","name":"sync_too","type":"bool"}],"name":"updateRewardAndBalance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"userStakedFrax","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"veFXSMultiplier","outputs":[{"internalType":"uint256","name":"vefxs_multiplier","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vefxs_boost_scale_factor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vefxs_max_multiplier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vefxs_per_frax_for_max_boost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"kek_id","type":"bytes32"},{"internalType":"address","name":"destination_address","type":"address"}],"name":"withdrawLocked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60c060405273c8418af6358ffdda74e09ca9cc3fe03ca6adc5b060805273853d955acef822db058eb8505911ed77f175b99e60a052671bc16d674ec8000060068190556301e1338060075562091050600855673782dace9d9000006009819055600a91909155600b553480156200007557600080fd5b506040516200581b3803806200581b833981016040819052620000989162000763565b86868686868686868686868686856001600160a01b038116620001015760405162461bcd60e51b815260206004820152601960248201527f4f776e657220616464726573732063616e6e6f74206265203000000000000000604482015260640160405180910390fd5b600080546001600160a01b0319166001600160a01b03831690811782556040805192835260208301919091527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a15060016002558451620001739060109060208801906200053a565b508151620001899060119060208501906200053a565b5080516200019f9060129060208401906200053a565b508251620001b5906013906020860190620005a4565b5060005b855181101562000320578060146000888481518110620001dd57620001dd6200086a565b6020908102919091018101516001600160a01b03168252810191909152604001600090812091909155601580546001810182559082527f55f448fdea98c4d29eb340757ef0a66cd03dbb9538908a6a81d96026b71ec475015584518590829081106200024d576200024d6200086a565b6020026020010151600f60008884815181106200026e576200026e6200086a565b6020908102919091018101516001600160a01b03908116835290820192909252604001600090812080546001600160a01b031916939092169290921790556019805460018181019092557f944998273e477b495144fb8794c914197f3ccb46be2900f4698fd0ef743c969501829055601a8054918201815582527f057c384a7d1c54f3a1b2e5e67b2617b8224fdfd1ea7234eea573a6ff665ff63e015580620003178162000896565b915050620001b9565b506021805460ff19169055426005819055620003419062093a8090620008b2565b6004819055505050505050505050505050505080602160056101000a8154816001600160a01b0302191690836001600160a01b03160217905550602160059054906101000a90046001600160a01b03166001600160a01b0316634f39059c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620003cf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620003f59190620008ce565b602280546001600160a01b0319166001600160a01b03929092169182179055604080516303aa30b960e11b815290516307546172916004808201926020929091908290030181865afa15801562000450573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004769190620008ce565b602380546001600160a01b0319166001600160a01b0392909216918217905560405163c661065760e01b8152600060048201819052919063c661065790602401602060405180830381865afa158015620004d4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004fa9190620008ce565b905060a0516001600160a01b0316816001600160a01b031614602160046101000a81548160ff0219169083151502179055505050505050505050620008f3565b82805482825590600052602060002090810192821562000592579160200282015b828111156200059257825182546001600160a01b0319166001600160a01b039091161782556020909201916001909101906200055b565b50620005a0929150620005e2565b5090565b82805482825590600052602060002090810192821562000592579160200282015b8281111562000592578251825591602001919060010190620005c5565b5b80821115620005a05760008155600101620005e3565b80516001600160a01b03811681146200061157600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171562000657576200065762000616565b604052919050565b60006001600160401b038211156200067b576200067b62000616565b5060051b60200190565b600082601f8301126200069757600080fd5b81516020620006b0620006aa836200065f565b6200062c565b82815260059290921b84018101918181019086841115620006d057600080fd5b8286015b84811015620006f657620006e881620005f9565b8352918301918301620006d4565b509695505050505050565b600082601f8301126200071357600080fd5b8151602062000726620006aa836200065f565b82815260059290921b840181019181810190868411156200074657600080fd5b8286015b84811015620006f657805183529183019183016200074a565b600080600080600080600060e0888a0312156200077f57600080fd5b6200078a88620005f9565b60208901519097506001600160401b0380821115620007a857600080fd5b620007b68b838c0162000685565b975060408a0151915080821115620007cd57600080fd5b620007db8b838c0162000685565b965060608a0151915080821115620007f257600080fd5b620008008b838c0162000701565b955060808a01519150808211156200081757600080fd5b620008258b838c0162000685565b945060a08a01519150808211156200083c57600080fd5b506200084b8a828b0162000685565b9250506200085c60c08901620005f9565b905092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060018201620008ab57620008ab62000880565b5060010190565b80820180821115620008c857620008c862000880565b92915050565b600060208284031215620008e157600080fd5b620008ec82620005f9565b9392505050565b60805160a051614ef06200092b600039600050506000818161103d015281816110f20152818161116c01526120b00152614ef06000f3fe608060405234801561001057600080fd5b50600436106104055760003560e01c80638980f11f1161021a578063d2fbdc0d11610135578063e44b9fa5116100c8578063f2a8d34911610097578063f77e34d11161007c578063f77e34d1146109cd578063facefb64146109e0578063fff6cae9146109f357600080fd5b8063f2a8d349146109b1578063f2caeb1e146109ba57600080fd5b8063e44b9fa514610979578063e7f305821461098c578063ebe2b12b1461099f578063f288baf6146109a857600080fd5b8063d9f96e8d11610104578063d9f96e8d14610920578063de1a655114610956578063e01f62bf14610969578063e1ba95d21461097157600080fd5b8063d2fbdc0d146108d4578063d42fc9b4146108e7578063d5e1a9c6146108fa578063d7400d561461090d57600080fd5b8063b94c4dcb116101ad578063ca6df29d1161017c578063ca6df29d14610879578063cc2abd64146108af578063cdc82e80146108c2578063d2010fb4146108cb57600080fd5b8063b94c4dcb14610841578063c00007b01461084a578063c35438261461085d578063c8f33c911461087057600080fd5b80639637927f116101e95780639637927f14610805578063a0f2347614610812578063aa1d4fce14610825578063b85efd061461082e57600080fd5b80638980f11f146107915780638bad86a7146107a45780638da5cb5b146107d257806391cf600a146107f257600080fd5b80634f39059c116103255780636e27cef9116102b85780637910d17b1161028757806379ba50971161026c57806379ba5097146107565780637d6ef08e1461075e5780637f472e541461077e57600080fd5b80637910d17b146107085780637970833e1461071b57600080fd5b80636e27cef9146106bb57806370641a36146106c457806372f702f3146106cc578063774d4ae7146106f557600080fd5b80635bfd9258116102f45780635bfd92581461066b57806364f2c06014610673578063693392451461067b5780636c430dbb1461069b57600080fd5b80634f39059c146106055780634fd2b5361461062557806353a47bb714610638578063551897731461065857600080fd5b8063218751b21161039d57806336f89af21161036c57806336f89af21461057c578063386a9525146105b2578063387edc86146105bc57806341a16f3f146105cf57600080fd5b8063218751b2146104cc578063231b68dc1461051157806328408bab146105345780632c0c2a0a1461056957600080fd5b806317b18c89116103d957806317b18c891461047e5780631c1f78eb146104915780631e090f01146104995780631face856146104b957600080fd5b80628cc2621461040a5780630d7bac4f1461043357806312edb24c146104545780631627540c14610469575b600080fd5b61041d61041836600461491d565b6109fb565b60405161042a9190614938565b60405180910390f35b61044661044136600461497c565b610b7a565b60405190815260200161042a565b61045c610ba6565b60405161042a9190614995565b61047c61047736600461491d565b610c15565b005b61044661048c3660046149e3565b610d3a565b61041d610dc4565b6104ac6104a736600461491d565b610e65565b60405161042a9190614a05565b6104466104c736600461491d565b610f19565b6023546104ec9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161042a565b61052461051f366004614a73565b610f5f565b604051901515815260200161042a565b6104ec61054236600461491d565b602080526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b61044661057736600461491d565b610fcd565b61044661058a36600461491d565b73ffffffffffffffffffffffffffffffffffffffff166000908152601e602052604090205490565b61044662093a8081565b61047c6105ca36600461491d565b6112e1565b6104ec6105dd36600461491d565b600f6020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b6022546104ec9073ffffffffffffffffffffffffffffffffffffffff1681565b61044661063336600461491d565b6113cb565b6001546104ec9073ffffffffffffffffffffffffffffffffffffffff1681565b61047c610666366004614ab4565b6113ec565b610446611510565b601c54610446565b61044661068936600461491d565b60146020526000908152604090205481565b6104466106a936600461491d565b60186020526000908152604090205481565b61044660085481565b61041d6115a6565b6021546104ec9065010000000000900473ffffffffffffffffffffffffffffffffffffffff1681565b610446610703366004614aeb565b611705565b61041d610716366004614ab4565b611911565b61072e610729366004614aeb565b61198d565b604080519586526020860194909452928401919091526060830152608082015260a00161042a565b61047c6119db565b61044661076c36600461491d565b601f6020526000908152604090205481565b61044661078c36600461491d565b611b26565b61047c61079f366004614aeb565b611b3d565b6107b76107b236600461491d565b611d26565b6040805193845260208401929092529082015260600161042a565b6000546104ec9073ffffffffffffffffffffffffffffffffffffffff1681565b61047c61080036600461491d565b611f5a565b6021546105249060ff1681565b61044661082036600461491d565b61204d565b61044660095481565b61047c61083c3660046149e3565b612125565b61044660075481565b61041d61085836600461491d565b61237e565b6104ec61086b36600461491d565b612406565b61044660055481565b61044661088736600461491d565b73ffffffffffffffffffffffffffffffffffffffff1660009081526024602052604090205490565b61047c6108bd366004614b15565b612468565b61044660065481565b61044660035481565b61047c6108e23660046149e3565b61259e565b6104466108f536600461491d565b612902565b61047c610908366004614b60565b61293e565b61047c61091b36600461491d565b612b2d565b61044661092e36600461491d565b73ffffffffffffffffffffffffffffffffffffffff166000908152601d602052604090205490565b61047c610964366004614a73565b612d48565b601b54610446565b61047c612e2f565b610446610987366004614bad565b612f00565b61047c61099a36600461491d565b612fee565b61044660045481565b610446600a5481565b610446600b5481565b6104466109c836600461497c565b61314c565b61047c6109db366004614bd0565b613263565b61047c6109ee366004614c1c565b613435565b61047c6135f5565b60606000610a076115a6565b60105490915067ffffffffffffffff811115610a2557610a25614bed565b604051908082528060200260200182016040528015610a4e578160200160208202803683370190505b5073ffffffffffffffffffffffffffffffffffffffff84166000908152601e602052604090205490925015610b745760005b601054811015610b725773ffffffffffffffffffffffffffffffffffffffff84166000818152601760209081526040808320858452825280832054938352601682528083208584529091529020548351670de0b6b3a76400009190859085908110610aed57610aed614cc1565b6020026020010151610aff9190614d1f565b73ffffffffffffffffffffffffffffffffffffffff87166000908152601e6020526040902054610b2f9190614d32565b610b399190614d49565b610b439190614d84565b838281518110610b5557610b55614cc1565b602090810291909101015280610b6a81614d97565b915050610a80565b505b50919050565b600654600754600091610ba091610b918286614d32565b610b9b9190614d49565b613625565b92915050565b60606010805480602002602001604051908101604052809291908181526020018280548015610c0b57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610be0575b5050505050905090565b60005473ffffffffffffffffffffffffffffffffffffffff163314610cc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726660448201527f6f726d207468697320616374696f6e000000000000000000000000000000000060648201526084015b60405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229060200160405180910390a150565b60006002805403610da7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610cb8565b60028055610db8338085854261363d565b60016002559392505050565b60135460609067ffffffffffffffff811115610de257610de2614bed565b604051908082528060200260200182016040528015610e0b578160200160208202803683370190505b50905060005b601354811015610e615762093a80610e288261314c565b610e329190614d32565b828281518110610e4457610e44614cc1565b602090810291909101015280610e5981614d97565b915050610e11565b5090565b73ffffffffffffffffffffffffffffffffffffffff81166000908152602460209081526040808320805482518185028101850190935280835260609492939192909184015b82821015610f0e57838290600052602060002090600502016040518060a00160405290816000820154815260200160018201548152602001600282015481526020016003820154815260200160048201548152505081526020019060010190610eaa565b505050509050919050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152601f6020526040812054600354670de0b6b3a764000091610f5591614d32565b610ba09190614d49565b6000805473ffffffffffffffffffffffffffffffffffffffff90811690841603610f8b57506001610ba0565b73ffffffffffffffffffffffffffffffffffffffff8281166000908152600f6020526040902054818516911603610fc457506001610ba0565b50600092915050565b60008080610fda84612406565b905073ffffffffffffffffffffffffffffffffffffffff8116156110ad576040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301527f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611084573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110a89190614dcf565b61115d565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611139573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061115d9190614dcf565b91506000670de0b6b3a76400007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f99190614dcf565b6112039190614d32565b600954600a546112139086614d32565b61121d9190614d32565b6112279190614d49565b905060008073ffffffffffffffffffffffffffffffffffffffff8416156112565761125184611b26565b61125f565b61125f876113cb565b905080156112b15760008161127c670de0b6b3a764000088614d32565b6112869190614d49565b9050670de0b6b3a7640000600a548261129f9190614d32565b6112a99190614d49565b9250506112b6565b600091505b508082116112c457806112c6565b815b9450600a548511156112d857600a5494505b50505050919050565b600280540361134c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610cb8565b6002805560215462010000900460ff16156113c3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f5265776172647320636f6c6c656374696f6e20706175736564000000000000006044820152606401610cb8565b506001600255565b6000670de0b6b3a7640000600b546113e284612902565b610f559190614d32565b80156113fa576113fa6135f5565b73ffffffffffffffffffffffffffffffffffffffff82161561150c57600080600061142485611d26565b92509250925061143385613a45565b73ffffffffffffffffffffffffffffffffffffffff85166000908152600c602052604090208290558281106114b757600061146e8483614d1f565b905080601c5461147e9190614d84565b601c5561148b8185614d84565b73ffffffffffffffffffffffffffffffffffffffff87166000908152601e602052604090205550611508565b60006114c38285614d1f565b905080601c546114d39190614d1f565b601c556114e08185614d1f565b73ffffffffffffffffffffffffffffffffffffffff87166000908152601e6020526040902055505b5050505b5050565b6000806004602360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166354f0f7d56040518163ffffffff1660e01b8152600401602060405180830381865afa158015611582573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f559190614dcf565b6060601b54600014806115b95750601c54155b15611613576015805480602002602001604051908101604052809291908181526020018280548015610c0b57602002820191906000526020600020905b8154815260200190600101908083116115f6575050505050905090565b60105467ffffffffffffffff81111561162e5761162e614bed565b604051908082528060200260200182016040528015611657578160200160208202803683370190505b50905060005b601554811015610e6157601c546116738261314c565b60055461167e613b45565b6116889190614d1f565b6116929190614d32565b6116a490670de0b6b3a7640000614d32565b6116ae9190614d49565b601582815481106116c1576116c1614cc1565b90600052602060002001546116d69190614d84565b8282815181106116e8576116e8614cc1565b6020908102919091010152806116fd81614d97565b91505061165d565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260246020526040812080548291908490811061173f5761173f614cc1565b600091825260208083206040805160a081018252600590940290910180548452600181015484840181905260028201548584015260038201546060860152600490910154608085015273ffffffffffffffffffffffffffffffffffffffff89168552601890925283205491935011156117bd575060208101516117e5565b5073ffffffffffffffffffffffffffffffffffffffff84166000908152601860205260409020545b428260600151116118a557606082015173ffffffffffffffffffffffffffffffffffffffff8616600090815260186020526040902054101561189c5760008183606001516118339190614d1f565b905060008360600151426118479190614d1f565b90506000611859610441600285614d49565b905060006118678382614d32565b6118718584614d32565b61187b9190614d84565b90506118878385614d84565b6118919082614d49565b9650505050506118f5565b600092506118f5565b6000808284606001516118b89190614d1f565b905060004285606001516118cc9190614d1f565b905060026118da8284614d84565b6118e49190614d49565b925050506118f181610b7a565b9350505b816080015183111561190957816080015192505b505092915050565b6060600280540361197e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610cb8565b60028055610db8338484613b58565b602460205281600052604060002081815481106119a957600080fd5b600091825260209091206005909102018054600182015460028301546003840154600490940154929550909350919085565b60015473ffffffffffffffffffffffffffffffffffffffff163314611a82576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7560448201527f2063616e20616363657074206f776e65727368697000000000000000000000006064820152608401610cb8565b6000546001546040805173ffffffffffffffffffffffffffffffffffffffff93841681529290911660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a160018054600080547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff841617909155169055565b6000670de0b6b3a7640000600b546113e284610f19565b600054829073ffffffffffffffffffffffffffffffffffffffff16331480611b6a5750611b6a3382610f5f565b611bd0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610cb8565b6000805b601054811015611c4a578473ffffffffffffffffffffffffffffffffffffffff1660108281548110611c0857611c08614cc1565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1603611c385760019150611c4a565b80611c4281614d97565b915050611bd4565b50808015611c7e575073ffffffffffffffffffffffffffffffffffffffff8481166000908152600f60205260409020541633145b80611ca9575080158015611ca9575060005473ffffffffffffffffffffffffffffffffffffffff1633145b15611cbf57611cb9843385613e24565b50505050565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4e6f2076616c696420746f6b656e7320746f207265636f7665720000000000006044820152606401610cb8565b505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152601e60205260408120549080611d5784610fcd565b73ffffffffffffffffffffffffffffffffffffffff85166000908152601d602052604081205491935090158015611db1575073ffffffffffffffffffffffffffffffffffffffff85166000908152601e6020526040902054155b80611de1575073ffffffffffffffffffffffffffffffffffffffff85166000908152600c60205260409020548310155b15611ded575081611e2d565b73ffffffffffffffffffffffffffffffffffffffff85166000908152600c6020526040902054600290611e209085614d84565b611e2a9190614d49565b90505b6000915060005b73ffffffffffffffffffffffffffffffffffffffff8616600090815260246020526040902054811015611f515773ffffffffffffffffffffffffffffffffffffffff86166000908152602460205260408120805483908110611e9857611e98614cc1565b90600052602060002090600502016040518060a00160405290816000820154815260200160018201548152602001600282015481526020016003820154815260200160048201548152505090506000611ef18884611705565b60408301519091506000670de0b6b3a7640000611f0e8785614d84565b611f189084614d32565b611f229190614d49565b611f2c9083614d84565b9050611f388188614d84565b9650505050508080611f4990614d97565b915050611e34565b50509193909250565b60005473ffffffffffffffffffffffffffffffffffffffff16331480611f935750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b611ff9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610cb8565b73ffffffffffffffffffffffffffffffffffffffff166000908152600d6020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b6000600354600b5461205f9190614d32565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152670de0b6b3a76400009182917f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa1580156120f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061211b9190614dcf565b6113e29190614d32565b6002805403612190576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610cb8565b600280553360016121a182826113ec565b6000806121ae3387613f8d565b9150915060008583604001516121c49190614d84565b90506021546121f49065010000000000900473ffffffffffffffffffffffffffffffffffffffff16333089614152565b6040805160a08101825288815260208581015181830152818301849052606080870151908301526080808701519083015233600090815260249091529190912080548490811061224657612246614cc1565b9060005260206000209060050201600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015590505085601b600082825461229b9190614d84565b9091555050336000908152601d6020526040812080548892906122bf908490614d84565b90915550600090506122d033612406565b905073ffffffffffffffffffffffffffffffffffffffff8116156123295773ffffffffffffffffffffffffffffffffffffffff81166000908152601f602052604081208054899290612323908490614d84565b90915550505b506123353360006113ec565b604080518881526020810188905233917f2640b32e7e5d0fa2a21ea06b22fbd75fda0fda384a895a5fdeef43646de47a0c910160405180910390a2505060016002555050505050565b606060028054036123eb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610cb8565b600280556123fb33836001613b58565b600160025592915050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600d602052604081205460ff1615612438575090565b5073ffffffffffffffffffffffffffffffffffffffff90811660009081526020805260409020541690565b919050565b60005473ffffffffffffffffffffffffffffffffffffffff163314806124a15750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b612507576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610cb8565b6021805491151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff931515610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff951515630100000002959095167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff00ff909316929092179390931791909116179055565b6002805403612609576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610cb8565b6002805533600161261a82826113ec565b6000806126273387613f8d565b91509150428511612694576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d75737420626520696e207468652066757475726500000000000000000000006044820152606401610cb8565b6000428360600151116126a85760006126b8565b4283606001516126b89190614d1f565b905060006126c64288614d1f565b9050818111612731576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616e6e6f742073686f7274656e206c6f636b2074696d6500000000000000006044820152606401610cb8565b60085481101561279d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d696e696d756d207374616b652074696d65206e6f74206d65740000000000006044820152606401610cb8565b600754811115612809576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f547279696e6720746f206c6f636b20666f7220746f6f206c6f6e6700000000006044820152606401610cb8565b6040518060a001604052808981526020014281526020018560400151815260200188815260200161283983610b7a565b905233600090815260246020526040902080548590811061285c5761285c614cc1565b906000526020600020906005020160008201518160000155602082015181600101556040820151816002015560608201518160030155608082015181600401559050506128aa3360006113ec565b6040805189815260208101839052428183015260608101899052905133917fc2cf1aae6decacbc52f96b4e4fec96d4ebab5236e4ed987165537bc463014a43919081900360800190a250506001600255505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152601d6020526040812054600354670de0b6b3a764000091610f5591614d32565b600054849073ffffffffffffffffffffffffffffffffffffffff1633148061296b575061296b3382610f5f565b6129d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610cb8565b73ffffffffffffffffffffffffffffffffffffffff8516600090815260146020526040902054601380548692908110612a0c57612a0c614cc1565b9060005260206000200181905550826011601460008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205481548110612a6d57612a6d614cc1565b600091825260208083209190910180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff948516179055918716815260149091526040902054601280548492908110612ade57612ade614cc1565b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600d602052604090205460ff16612bbc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f496e76616c69642070726f7879000000000000000000000000000000000000006044820152606401610cb8565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600e6020908152604080832033845290915290205460ff16612c56576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f50726f787920686173206e6f7420616c6c6f77656420796f75207965740000006044820152606401610cb8565b33600090815260208052604090205473ffffffffffffffffffffffffffffffffffffffff168015612ccb57336000908152601d602090815260408083205473ffffffffffffffffffffffffffffffffffffffff85168452601f9092528220805491929091612cc5908490614d1f565b90915550505b3360009081526020808052604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8716908117909155601d835281842054908452601f9092528220805491929091612d3f908490614d84565b90915550505050565b600054829073ffffffffffffffffffffffffffffffffffffffff16331480612d755750612d753382610f5f565b612ddb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610cb8565b5073ffffffffffffffffffffffffffffffffffffffff9182166000908152600f6020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001691909216179055565b60005473ffffffffffffffffffffffffffffffffffffffff16331480612e685750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b612ece576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610cb8565b602180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b60006002805403612f6d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610cb8565b60028055602154610100900460ff1615612fe3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f5769746864726177616c732070617573656400000000000000000000000000006044820152606401610cb8565b610db83383856142f0565b336000908152600d602052604090205460ff16613067576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f496e76616c69642070726f7879000000000000000000000000000000000000006044820152606401610cb8565b336000818152600e6020908152604080832073ffffffffffffffffffffffffffffffffffffffff8681168552908352818420805460ff8116157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009091161790559180529091205416036131495773ffffffffffffffffffffffffffffffffffffffff811660009081526020808052604080832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055601d825280832054338452601f9092528220805491929091613143908490614d1f565b90915550505b50565b6000806011838154811061316257613162614cc1565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169050801561323d57670de0b6b3a7640000601984815481106131a8576131a8614cc1565b90600052602060002001548273ffffffffffffffffffffffffffffffffffffffff16630a3be7576040518163ffffffff1660e01b8152600401602060405180830381865afa1580156131fe573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132229190614dcf565b61322c9190614d32565b6132369190614d49565b9150610b74565b6013838154811061325057613250614cc1565b9060005260206000200154915050919050565b60005b60115481101561150c5760006011828154811061328557613285614cc1565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905080156134225782806132d75750601a82815481106132c9576132c9614cc1565b906000526020600020015442115b15613422576040517f6472eee100000000000000000000000000000000000000000000000000000000815230600482015242602482015273ffffffffffffffffffffffffffffffffffffffff821690636472eee1906044016020604051808303816000875af115801561334e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133729190614dcf565b6019838154811061338557613385614cc1565b90600052602060002001819055508073ffffffffffffffffffffffffffffffffffffffff1663513872bd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156133de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134029190614dcf565b601a838154811061341557613415614cc1565b6000918252602090912001555b508061342d81614d97565b915050613266565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061346e5750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b6134d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610cb8565b8051670de0b6b3a76400001115613547576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4d757374206265203e3d204d554c2050524543000000000000000000000000006044820152606401610cb8565b6080810151600111801590613561575060a0810151600111155b6135c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4d757374206265203e3d203100000000000000000000000000000000000000006044820152606401610cb8565b80516006556020810151600a556040810151600b556060810151600955608081015160075560a00151600855565b6135ff6000613263565b613607611510565b600355600454421061361d5761361b614553565b565b61361b614886565b60008183106136345781613636565b825b9392505050565b600085600161364c82826113ec565b6021546301000000900460ff16156136c0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f5374616b696e67207061757365640000000000000000000000000000000000006044820152606401610cb8565b60085485101561372c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d696e696d756d207374616b652074696d65206e6f74206d65740000000000006044820152606401610cb8565b600754851115613798576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f547279696e6720746f206c6f636b20666f7220746f6f206c6f6e6700000000006044820152606401610cb8565b6021546137c69065010000000000900473ffffffffffffffffffffffffffffffffffffffff16883089614152565b60006137d186610b7a565b73ffffffffffffffffffffffffffffffffffffffff8a166000908152601d602090815260408083205490517fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060608f901b169281019290925260348201899052605482018b9052607482015291925090609401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012073ffffffffffffffffffffffffffffffffffffffff8e1660009081526024835283902060a0850184528185529184018a90529183018b905290925090606081016138c48a8a614d84565b815260209081018590528254600181810185556000948552828520845160059093020191825591830151918101919091556040820151600282015560608201516003820155608090910151600490910155601b80548a9290613927908490614d84565b909155505073ffffffffffffffffffffffffffffffffffffffff8a166000908152601d6020526040812080548a9290613961908490614d84565b90915550600090506139728b612406565b905073ffffffffffffffffffffffffffffffffffffffff8116156139cb5773ffffffffffffffffffffffffffffffffffffffff81166000908152601f6020526040812080548b92906139c5908490614d84565b90915550505b506139d78a60006113ec565b604080518981526020810189905290810182905273ffffffffffffffffffffffffffffffffffffffff8a811660608301528b16907ff400e72e69ef4402819dfc57eeddc66f5eb69bf405e0e8098b1946ec1ac14a229060800160405180910390a29998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff811615613149576000613a6c826109fb565b905060005b8151811015613ada57818181518110613a8c57613a8c614cc1565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff85166000908152601783526040808220858352909352919091205580613ad281614d97565b915050613a71565b5060005b8151811015611d215760158181548110613afa57613afa614cc1565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff8616835260168252604080842085855290925291205580613b3d81614d97565b915050613ade565b6000613b5342600454613625565b905090565b6060836001613b6782826113ec565b73ffffffffffffffffffffffffffffffffffffffff8616600090815260186020526040902042905560215462010000900460ff1615613c02576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f5265776172647320636f6c6c656374696f6e20706175736564000000000000006044820152606401610cb8565b60105467ffffffffffffffff811115613c1d57613c1d614bed565b604051908082528060200260200182016040528015613c46578160200160208202803683370190505b50925060005b601054811015613e1a5773ffffffffffffffffffffffffffffffffffffffff871660009081526017602090815260408083208484529091529020548451859083908110613c9b57613c9b614cc1565b60209081029190910181019190915273ffffffffffffffffffffffffffffffffffffffff881660009081526017825260408082208483529092529081208190558451859083908110613cef57613cef614cc1565b60200260200101511115613e0857613d5e60108281548110613d1357613d13614cc1565b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1687868481518110613d5157613d51614cc1565b6020026020010151613e24565b8673ffffffffffffffffffffffffffffffffffffffff167f1d2f2ca53af5d2f333bd32fdd45f9c52ad8ebe31414f7792912077fcb3876dff858381518110613da857613da8614cc1565b602002602001015160108481548110613dc357613dc3614cc1565b600091825260209182902001546040805193845273ffffffffffffffffffffffffffffffffffffffff918216928401929092528a169082015260600160405180910390a25b80613e1281614d97565b915050613c4c565b5050509392505050565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790529151600092839290871691613ebb9190614e0c565b6000604051808303816000865af19150503d8060008114613ef8576040519150601f19603f3d011682016040523d82523d6000602084013e613efd565b606091505b5091509150818015613f27575080511580613f27575080806020019051810190613f279190614e28565b611508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c4544006044820152606401610cb8565b613fc26040518060a0016040528060008019168152602001600081526020016000815260200160008152602001600081525090565b6000805b73ffffffffffffffffffffffffffffffffffffffff85166000908152602460205260409020548110156140e05773ffffffffffffffffffffffffffffffffffffffff8516600090815260246020526040902080548290811061402a5761402a614cc1565b90600052602060002090600502016000015484036140ce5773ffffffffffffffffffffffffffffffffffffffff8516600090815260246020526040902080548290811061407957614079614cc1565b90600052602060002090600502016040518060a00160405290816000820154815260200160018201548152602001600282015481526020016003820154815260200160048201548152505092508091506140e0565b806140d881614d97565b915050613fc6565b508151831461414b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5374616b65206e6f7420666f756e6400000000000000000000000000000000006044820152606401610cb8565b9250929050565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd0000000000000000000000000000000000000000000000000000000017905291516000928392908816916141f19190614e0c565b6000604051808303816000865af19150503d806000811461422e576040519150601f19603f3d011682016040523d82523d6000602084013e614233565b606091505b509150915081801561425d57508051158061425d57508080602001905181019061425d9190614e28565b6142e8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f5472616e7366657248656c7065723a205452414e534645525f46524f4d5f464160448201527f494c4544000000000000000000000000000000000000000000000000000000006064820152608401610cb8565b505050505050565b60006142fe84846001613b58565b5060008061430c8685613f8d565b9150915081606001514210158061432a575060215460ff1615156001145b614390576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616b65206973207374696c6c206c6f636b656421000000000000000000006044820152606401610cb8565b60408201518015614549576021546143c89065010000000000900473ffffffffffffffffffffffffffffffffffffffff168783613e24565b80601b60008282546143da9190614d1f565b909155505073ffffffffffffffffffffffffffffffffffffffff87166000908152601d602052604081208054839290614414908490614d1f565b909155506000905061442588612406565b905073ffffffffffffffffffffffffffffffffffffffff81161561447e5773ffffffffffffffffffffffffffffffffffffffff81166000908152601f602052604081208054849290614478908490614d1f565b90915550505b5073ffffffffffffffffffffffffffffffffffffffff871660009081526024602052604090208054839081106144b6576144b6614cc1565b6000918252602082206005909102018181556001810182905560028101829055600381018290556004018190556144ee9088906113ec565b604080518281526020810187905273ffffffffffffffffffffffffffffffffffffffff888116828401529151918916917f1d9308f6b22a2754a1c622bb30889e8f8f956c83e524d039e9d65d5f052eb9089181900360600190a25b9695505050505050565b60005b6012548110156146445760006012828154811061457557614575614cc1565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1690508015614631576040517f092193ab00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff82169063092193ab9060240160408051808303816000875af115801561460a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061462e9190614e45565b50505b508061463c81614d97565b915050614556565b50600062093a80600454426146599190614d1f565b6146639190614d49565b905060005b601054811015614846576010818154811061468557614685614cc1565b6000918252602090912001546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa1580156146fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147209190614dcf565b61472b836001614d84565b62093a806147388461314c565b6147429190614d32565b61474c9190614d32565b11156010828154811061476157614761614cc1565b60009182526020918290200154604080517f4e6f7420656e6f7567682072657761726420746f6b656e7320617661696c6162938101939093527f6c653a20000000000000000000000000000000000000000000000000000000009083015260601b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016604482015260580160405160208183030381529060405290614833576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cb89190614e69565b508061483e81614d97565b915050614668565b5062093a80614856826001614d84565b6148609190614d32565b60045461486d9190614d84565b600455614878614886565b614880611510565b60035550565b60006148906115a6565b905060005b6015548110156148ea578181815181106148b1576148b1614cc1565b6020026020010151601582815481106148cc576148cc614cc1565b600091825260209091200155806148e281614d97565b915050614895565b506148f3613b45565b60055550565b803573ffffffffffffffffffffffffffffffffffffffff8116811461246357600080fd5b60006020828403121561492f57600080fd5b613636826148f9565b6020808252825182820181905260009190848201906040850190845b8181101561497057835183529284019291840191600101614954565b50909695505050505050565b60006020828403121561498e57600080fd5b5035919050565b6020808252825182820181905260009190848201906040850190845b8181101561497057835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016149b1565b600080604083850312156149f657600080fd5b50508035926020909101359150565b602080825282518282018190526000919060409081850190868401855b82811015614a665781518051855286810151878601528581015186860152606080820151908601526080908101519085015260a09093019290850190600101614a22565b5091979650505050505050565b60008060408385031215614a8657600080fd5b614a8f836148f9565b9150614a9d602084016148f9565b90509250929050565b801515811461314957600080fd5b60008060408385031215614ac757600080fd5b614ad0836148f9565b91506020830135614ae081614aa6565b809150509250929050565b60008060408385031215614afe57600080fd5b614b07836148f9565b946020939093013593505050565b600080600060608486031215614b2a57600080fd5b8335614b3581614aa6565b92506020840135614b4581614aa6565b91506040840135614b5581614aa6565b809150509250925092565b60008060008060808587031215614b7657600080fd5b614b7f856148f9565b935060208501359250614b94604086016148f9565b9150614ba2606086016148f9565b905092959194509250565b60008060408385031215614bc057600080fd5b82359150614a9d602084016148f9565b600060208284031215614be257600080fd5b813561363681614aa6565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600060c08284031215614c2e57600080fd5b82601f830112614c3d57600080fd5b60405160c0810181811067ffffffffffffffff82111715614c87577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040528060c0840185811115614c9c57600080fd5b845b81811015614cb6578035835260209283019201614c9e565b509195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b81810381811115610ba057610ba0614cf0565b8082028115828204841417610ba057610ba0614cf0565b600082614d7f577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820180821115610ba057610ba0614cf0565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614dc857614dc8614cf0565b5060010190565b600060208284031215614de157600080fd5b5051919050565b60005b83811015614e03578181015183820152602001614deb565b50506000910152565b60008251614e1e818460208701614de8565b9190910192915050565b600060208284031215614e3a57600080fd5b815161363681614aa6565b60008060408385031215614e5857600080fd5b505080516020909101519092909150565b6020815260008251806020840152614e88816040850160208701614de8565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fea264697066735822122014c1a22e1cdb68c3efe6ae17cf9f9a6019fd213f84cbe232a6c0ee2c6695275564736f6c63430008110033000000000000000000000000b1748c79709f4ba2dd82834b8c82d4a505003f2700000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000af1b82809296e52a42b3452c52e301369ce2055400000000000000000000000000000000000000000000000000000000000000010000000000000000000000003432b6a60d23ca0dfca7761b7ab56459d9c964d00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000b1748c79709f4ba2dd82834b8c82d4a505003f27000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000a86cc92e3da000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000278dc748eda1d8efef1adfb518542612b49fcd34
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106104055760003560e01c80638980f11f1161021a578063d2fbdc0d11610135578063e44b9fa5116100c8578063f2a8d34911610097578063f77e34d11161007c578063f77e34d1146109cd578063facefb64146109e0578063fff6cae9146109f357600080fd5b8063f2a8d349146109b1578063f2caeb1e146109ba57600080fd5b8063e44b9fa514610979578063e7f305821461098c578063ebe2b12b1461099f578063f288baf6146109a857600080fd5b8063d9f96e8d11610104578063d9f96e8d14610920578063de1a655114610956578063e01f62bf14610969578063e1ba95d21461097157600080fd5b8063d2fbdc0d146108d4578063d42fc9b4146108e7578063d5e1a9c6146108fa578063d7400d561461090d57600080fd5b8063b94c4dcb116101ad578063ca6df29d1161017c578063ca6df29d14610879578063cc2abd64146108af578063cdc82e80146108c2578063d2010fb4146108cb57600080fd5b8063b94c4dcb14610841578063c00007b01461084a578063c35438261461085d578063c8f33c911461087057600080fd5b80639637927f116101e95780639637927f14610805578063a0f2347614610812578063aa1d4fce14610825578063b85efd061461082e57600080fd5b80638980f11f146107915780638bad86a7146107a45780638da5cb5b146107d257806391cf600a146107f257600080fd5b80634f39059c116103255780636e27cef9116102b85780637910d17b1161028757806379ba50971161026c57806379ba5097146107565780637d6ef08e1461075e5780637f472e541461077e57600080fd5b80637910d17b146107085780637970833e1461071b57600080fd5b80636e27cef9146106bb57806370641a36146106c457806372f702f3146106cc578063774d4ae7146106f557600080fd5b80635bfd9258116102f45780635bfd92581461066b57806364f2c06014610673578063693392451461067b5780636c430dbb1461069b57600080fd5b80634f39059c146106055780634fd2b5361461062557806353a47bb714610638578063551897731461065857600080fd5b8063218751b21161039d57806336f89af21161036c57806336f89af21461057c578063386a9525146105b2578063387edc86146105bc57806341a16f3f146105cf57600080fd5b8063218751b2146104cc578063231b68dc1461051157806328408bab146105345780632c0c2a0a1461056957600080fd5b806317b18c89116103d957806317b18c891461047e5780631c1f78eb146104915780631e090f01146104995780631face856146104b957600080fd5b80628cc2621461040a5780630d7bac4f1461043357806312edb24c146104545780631627540c14610469575b600080fd5b61041d61041836600461491d565b6109fb565b60405161042a9190614938565b60405180910390f35b61044661044136600461497c565b610b7a565b60405190815260200161042a565b61045c610ba6565b60405161042a9190614995565b61047c61047736600461491d565b610c15565b005b61044661048c3660046149e3565b610d3a565b61041d610dc4565b6104ac6104a736600461491d565b610e65565b60405161042a9190614a05565b6104466104c736600461491d565b610f19565b6023546104ec9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161042a565b61052461051f366004614a73565b610f5f565b604051901515815260200161042a565b6104ec61054236600461491d565b602080526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b61044661057736600461491d565b610fcd565b61044661058a36600461491d565b73ffffffffffffffffffffffffffffffffffffffff166000908152601e602052604090205490565b61044662093a8081565b61047c6105ca36600461491d565b6112e1565b6104ec6105dd36600461491d565b600f6020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b6022546104ec9073ffffffffffffffffffffffffffffffffffffffff1681565b61044661063336600461491d565b6113cb565b6001546104ec9073ffffffffffffffffffffffffffffffffffffffff1681565b61047c610666366004614ab4565b6113ec565b610446611510565b601c54610446565b61044661068936600461491d565b60146020526000908152604090205481565b6104466106a936600461491d565b60186020526000908152604090205481565b61044660085481565b61041d6115a6565b6021546104ec9065010000000000900473ffffffffffffffffffffffffffffffffffffffff1681565b610446610703366004614aeb565b611705565b61041d610716366004614ab4565b611911565b61072e610729366004614aeb565b61198d565b604080519586526020860194909452928401919091526060830152608082015260a00161042a565b61047c6119db565b61044661076c36600461491d565b601f6020526000908152604090205481565b61044661078c36600461491d565b611b26565b61047c61079f366004614aeb565b611b3d565b6107b76107b236600461491d565b611d26565b6040805193845260208401929092529082015260600161042a565b6000546104ec9073ffffffffffffffffffffffffffffffffffffffff1681565b61047c61080036600461491d565b611f5a565b6021546105249060ff1681565b61044661082036600461491d565b61204d565b61044660095481565b61047c61083c3660046149e3565b612125565b61044660075481565b61041d61085836600461491d565b61237e565b6104ec61086b36600461491d565b612406565b61044660055481565b61044661088736600461491d565b73ffffffffffffffffffffffffffffffffffffffff1660009081526024602052604090205490565b61047c6108bd366004614b15565b612468565b61044660065481565b61044660035481565b61047c6108e23660046149e3565b61259e565b6104466108f536600461491d565b612902565b61047c610908366004614b60565b61293e565b61047c61091b36600461491d565b612b2d565b61044661092e36600461491d565b73ffffffffffffffffffffffffffffffffffffffff166000908152601d602052604090205490565b61047c610964366004614a73565b612d48565b601b54610446565b61047c612e2f565b610446610987366004614bad565b612f00565b61047c61099a36600461491d565b612fee565b61044660045481565b610446600a5481565b610446600b5481565b6104466109c836600461497c565b61314c565b61047c6109db366004614bd0565b613263565b61047c6109ee366004614c1c565b613435565b61047c6135f5565b60606000610a076115a6565b60105490915067ffffffffffffffff811115610a2557610a25614bed565b604051908082528060200260200182016040528015610a4e578160200160208202803683370190505b5073ffffffffffffffffffffffffffffffffffffffff84166000908152601e602052604090205490925015610b745760005b601054811015610b725773ffffffffffffffffffffffffffffffffffffffff84166000818152601760209081526040808320858452825280832054938352601682528083208584529091529020548351670de0b6b3a76400009190859085908110610aed57610aed614cc1565b6020026020010151610aff9190614d1f565b73ffffffffffffffffffffffffffffffffffffffff87166000908152601e6020526040902054610b2f9190614d32565b610b399190614d49565b610b439190614d84565b838281518110610b5557610b55614cc1565b602090810291909101015280610b6a81614d97565b915050610a80565b505b50919050565b600654600754600091610ba091610b918286614d32565b610b9b9190614d49565b613625565b92915050565b60606010805480602002602001604051908101604052809291908181526020018280548015610c0b57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610be0575b5050505050905090565b60005473ffffffffffffffffffffffffffffffffffffffff163314610cc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726660448201527f6f726d207468697320616374696f6e000000000000000000000000000000000060648201526084015b60405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229060200160405180910390a150565b60006002805403610da7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610cb8565b60028055610db8338085854261363d565b60016002559392505050565b60135460609067ffffffffffffffff811115610de257610de2614bed565b604051908082528060200260200182016040528015610e0b578160200160208202803683370190505b50905060005b601354811015610e615762093a80610e288261314c565b610e329190614d32565b828281518110610e4457610e44614cc1565b602090810291909101015280610e5981614d97565b915050610e11565b5090565b73ffffffffffffffffffffffffffffffffffffffff81166000908152602460209081526040808320805482518185028101850190935280835260609492939192909184015b82821015610f0e57838290600052602060002090600502016040518060a00160405290816000820154815260200160018201548152602001600282015481526020016003820154815260200160048201548152505081526020019060010190610eaa565b505050509050919050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152601f6020526040812054600354670de0b6b3a764000091610f5591614d32565b610ba09190614d49565b6000805473ffffffffffffffffffffffffffffffffffffffff90811690841603610f8b57506001610ba0565b73ffffffffffffffffffffffffffffffffffffffff8281166000908152600f6020526040902054818516911603610fc457506001610ba0565b50600092915050565b60008080610fda84612406565b905073ffffffffffffffffffffffffffffffffffffffff8116156110ad576040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301527f000000000000000000000000c8418af6358ffdda74e09ca9cc3fe03ca6adc5b016906370a0823190602401602060405180830381865afa158015611084573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110a89190614dcf565b61115d565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000c8418af6358ffdda74e09ca9cc3fe03ca6adc5b016906370a0823190602401602060405180830381865afa158015611139573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061115d9190614dcf565b91506000670de0b6b3a76400007f000000000000000000000000c8418af6358ffdda74e09ca9cc3fe03ca6adc5b073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f99190614dcf565b6112039190614d32565b600954600a546112139086614d32565b61121d9190614d32565b6112279190614d49565b905060008073ffffffffffffffffffffffffffffffffffffffff8416156112565761125184611b26565b61125f565b61125f876113cb565b905080156112b15760008161127c670de0b6b3a764000088614d32565b6112869190614d49565b9050670de0b6b3a7640000600a548261129f9190614d32565b6112a99190614d49565b9250506112b6565b600091505b508082116112c457806112c6565b815b9450600a548511156112d857600a5494505b50505050919050565b600280540361134c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610cb8565b6002805560215462010000900460ff16156113c3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f5265776172647320636f6c6c656374696f6e20706175736564000000000000006044820152606401610cb8565b506001600255565b6000670de0b6b3a7640000600b546113e284612902565b610f559190614d32565b80156113fa576113fa6135f5565b73ffffffffffffffffffffffffffffffffffffffff82161561150c57600080600061142485611d26565b92509250925061143385613a45565b73ffffffffffffffffffffffffffffffffffffffff85166000908152600c602052604090208290558281106114b757600061146e8483614d1f565b905080601c5461147e9190614d84565b601c5561148b8185614d84565b73ffffffffffffffffffffffffffffffffffffffff87166000908152601e602052604090205550611508565b60006114c38285614d1f565b905080601c546114d39190614d1f565b601c556114e08185614d1f565b73ffffffffffffffffffffffffffffffffffffffff87166000908152601e6020526040902055505b5050505b5050565b6000806004602360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166354f0f7d56040518163ffffffff1660e01b8152600401602060405180830381865afa158015611582573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f559190614dcf565b6060601b54600014806115b95750601c54155b15611613576015805480602002602001604051908101604052809291908181526020018280548015610c0b57602002820191906000526020600020905b8154815260200190600101908083116115f6575050505050905090565b60105467ffffffffffffffff81111561162e5761162e614bed565b604051908082528060200260200182016040528015611657578160200160208202803683370190505b50905060005b601554811015610e6157601c546116738261314c565b60055461167e613b45565b6116889190614d1f565b6116929190614d32565b6116a490670de0b6b3a7640000614d32565b6116ae9190614d49565b601582815481106116c1576116c1614cc1565b90600052602060002001546116d69190614d84565b8282815181106116e8576116e8614cc1565b6020908102919091010152806116fd81614d97565b91505061165d565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260246020526040812080548291908490811061173f5761173f614cc1565b600091825260208083206040805160a081018252600590940290910180548452600181015484840181905260028201548584015260038201546060860152600490910154608085015273ffffffffffffffffffffffffffffffffffffffff89168552601890925283205491935011156117bd575060208101516117e5565b5073ffffffffffffffffffffffffffffffffffffffff84166000908152601860205260409020545b428260600151116118a557606082015173ffffffffffffffffffffffffffffffffffffffff8616600090815260186020526040902054101561189c5760008183606001516118339190614d1f565b905060008360600151426118479190614d1f565b90506000611859610441600285614d49565b905060006118678382614d32565b6118718584614d32565b61187b9190614d84565b90506118878385614d84565b6118919082614d49565b9650505050506118f5565b600092506118f5565b6000808284606001516118b89190614d1f565b905060004285606001516118cc9190614d1f565b905060026118da8284614d84565b6118e49190614d49565b925050506118f181610b7a565b9350505b816080015183111561190957816080015192505b505092915050565b6060600280540361197e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610cb8565b60028055610db8338484613b58565b602460205281600052604060002081815481106119a957600080fd5b600091825260209091206005909102018054600182015460028301546003840154600490940154929550909350919085565b60015473ffffffffffffffffffffffffffffffffffffffff163314611a82576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7560448201527f2063616e20616363657074206f776e65727368697000000000000000000000006064820152608401610cb8565b6000546001546040805173ffffffffffffffffffffffffffffffffffffffff93841681529290911660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a160018054600080547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff841617909155169055565b6000670de0b6b3a7640000600b546113e284610f19565b600054829073ffffffffffffffffffffffffffffffffffffffff16331480611b6a5750611b6a3382610f5f565b611bd0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610cb8565b6000805b601054811015611c4a578473ffffffffffffffffffffffffffffffffffffffff1660108281548110611c0857611c08614cc1565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1603611c385760019150611c4a565b80611c4281614d97565b915050611bd4565b50808015611c7e575073ffffffffffffffffffffffffffffffffffffffff8481166000908152600f60205260409020541633145b80611ca9575080158015611ca9575060005473ffffffffffffffffffffffffffffffffffffffff1633145b15611cbf57611cb9843385613e24565b50505050565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4e6f2076616c696420746f6b656e7320746f207265636f7665720000000000006044820152606401610cb8565b505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152601e60205260408120549080611d5784610fcd565b73ffffffffffffffffffffffffffffffffffffffff85166000908152601d602052604081205491935090158015611db1575073ffffffffffffffffffffffffffffffffffffffff85166000908152601e6020526040902054155b80611de1575073ffffffffffffffffffffffffffffffffffffffff85166000908152600c60205260409020548310155b15611ded575081611e2d565b73ffffffffffffffffffffffffffffffffffffffff85166000908152600c6020526040902054600290611e209085614d84565b611e2a9190614d49565b90505b6000915060005b73ffffffffffffffffffffffffffffffffffffffff8616600090815260246020526040902054811015611f515773ffffffffffffffffffffffffffffffffffffffff86166000908152602460205260408120805483908110611e9857611e98614cc1565b90600052602060002090600502016040518060a00160405290816000820154815260200160018201548152602001600282015481526020016003820154815260200160048201548152505090506000611ef18884611705565b60408301519091506000670de0b6b3a7640000611f0e8785614d84565b611f189084614d32565b611f229190614d49565b611f2c9083614d84565b9050611f388188614d84565b9650505050508080611f4990614d97565b915050611e34565b50509193909250565b60005473ffffffffffffffffffffffffffffffffffffffff16331480611f935750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b611ff9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610cb8565b73ffffffffffffffffffffffffffffffffffffffff166000908152600d6020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b6000600354600b5461205f9190614d32565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152670de0b6b3a76400009182917f000000000000000000000000c8418af6358ffdda74e09ca9cc3fe03ca6adc5b016906370a0823190602401602060405180830381865afa1580156120f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061211b9190614dcf565b6113e29190614d32565b6002805403612190576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610cb8565b600280553360016121a182826113ec565b6000806121ae3387613f8d565b9150915060008583604001516121c49190614d84565b90506021546121f49065010000000000900473ffffffffffffffffffffffffffffffffffffffff16333089614152565b6040805160a08101825288815260208581015181830152818301849052606080870151908301526080808701519083015233600090815260249091529190912080548490811061224657612246614cc1565b9060005260206000209060050201600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015590505085601b600082825461229b9190614d84565b9091555050336000908152601d6020526040812080548892906122bf908490614d84565b90915550600090506122d033612406565b905073ffffffffffffffffffffffffffffffffffffffff8116156123295773ffffffffffffffffffffffffffffffffffffffff81166000908152601f602052604081208054899290612323908490614d84565b90915550505b506123353360006113ec565b604080518881526020810188905233917f2640b32e7e5d0fa2a21ea06b22fbd75fda0fda384a895a5fdeef43646de47a0c910160405180910390a2505060016002555050505050565b606060028054036123eb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610cb8565b600280556123fb33836001613b58565b600160025592915050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600d602052604081205460ff1615612438575090565b5073ffffffffffffffffffffffffffffffffffffffff90811660009081526020805260409020541690565b919050565b60005473ffffffffffffffffffffffffffffffffffffffff163314806124a15750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b612507576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610cb8565b6021805491151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff931515610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff951515630100000002959095167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff00ff909316929092179390931791909116179055565b6002805403612609576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610cb8565b6002805533600161261a82826113ec565b6000806126273387613f8d565b91509150428511612694576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d75737420626520696e207468652066757475726500000000000000000000006044820152606401610cb8565b6000428360600151116126a85760006126b8565b4283606001516126b89190614d1f565b905060006126c64288614d1f565b9050818111612731576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616e6e6f742073686f7274656e206c6f636b2074696d6500000000000000006044820152606401610cb8565b60085481101561279d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d696e696d756d207374616b652074696d65206e6f74206d65740000000000006044820152606401610cb8565b600754811115612809576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f547279696e6720746f206c6f636b20666f7220746f6f206c6f6e6700000000006044820152606401610cb8565b6040518060a001604052808981526020014281526020018560400151815260200188815260200161283983610b7a565b905233600090815260246020526040902080548590811061285c5761285c614cc1565b906000526020600020906005020160008201518160000155602082015181600101556040820151816002015560608201518160030155608082015181600401559050506128aa3360006113ec565b6040805189815260208101839052428183015260608101899052905133917fc2cf1aae6decacbc52f96b4e4fec96d4ebab5236e4ed987165537bc463014a43919081900360800190a250506001600255505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152601d6020526040812054600354670de0b6b3a764000091610f5591614d32565b600054849073ffffffffffffffffffffffffffffffffffffffff1633148061296b575061296b3382610f5f565b6129d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610cb8565b73ffffffffffffffffffffffffffffffffffffffff8516600090815260146020526040902054601380548692908110612a0c57612a0c614cc1565b9060005260206000200181905550826011601460008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205481548110612a6d57612a6d614cc1565b600091825260208083209190910180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff948516179055918716815260149091526040902054601280548492908110612ade57612ade614cc1565b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600d602052604090205460ff16612bbc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f496e76616c69642070726f7879000000000000000000000000000000000000006044820152606401610cb8565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600e6020908152604080832033845290915290205460ff16612c56576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f50726f787920686173206e6f7420616c6c6f77656420796f75207965740000006044820152606401610cb8565b33600090815260208052604090205473ffffffffffffffffffffffffffffffffffffffff168015612ccb57336000908152601d602090815260408083205473ffffffffffffffffffffffffffffffffffffffff85168452601f9092528220805491929091612cc5908490614d1f565b90915550505b3360009081526020808052604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8716908117909155601d835281842054908452601f9092528220805491929091612d3f908490614d84565b90915550505050565b600054829073ffffffffffffffffffffffffffffffffffffffff16331480612d755750612d753382610f5f565b612ddb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f74206f776e6572206f7220746b6e206d67720000000000000000000000006044820152606401610cb8565b5073ffffffffffffffffffffffffffffffffffffffff9182166000908152600f6020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001691909216179055565b60005473ffffffffffffffffffffffffffffffffffffffff16331480612e685750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b612ece576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610cb8565b602180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b60006002805403612f6d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610cb8565b60028055602154610100900460ff1615612fe3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f5769746864726177616c732070617573656400000000000000000000000000006044820152606401610cb8565b610db83383856142f0565b336000908152600d602052604090205460ff16613067576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f496e76616c69642070726f7879000000000000000000000000000000000000006044820152606401610cb8565b336000818152600e6020908152604080832073ffffffffffffffffffffffffffffffffffffffff8681168552908352818420805460ff8116157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009091161790559180529091205416036131495773ffffffffffffffffffffffffffffffffffffffff811660009081526020808052604080832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055601d825280832054338452601f9092528220805491929091613143908490614d1f565b90915550505b50565b6000806011838154811061316257613162614cc1565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169050801561323d57670de0b6b3a7640000601984815481106131a8576131a8614cc1565b90600052602060002001548273ffffffffffffffffffffffffffffffffffffffff16630a3be7576040518163ffffffff1660e01b8152600401602060405180830381865afa1580156131fe573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132229190614dcf565b61322c9190614d32565b6132369190614d49565b9150610b74565b6013838154811061325057613250614cc1565b9060005260206000200154915050919050565b60005b60115481101561150c5760006011828154811061328557613285614cc1565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905080156134225782806132d75750601a82815481106132c9576132c9614cc1565b906000526020600020015442115b15613422576040517f6472eee100000000000000000000000000000000000000000000000000000000815230600482015242602482015273ffffffffffffffffffffffffffffffffffffffff821690636472eee1906044016020604051808303816000875af115801561334e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133729190614dcf565b6019838154811061338557613385614cc1565b90600052602060002001819055508073ffffffffffffffffffffffffffffffffffffffff1663513872bd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156133de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134029190614dcf565b601a838154811061341557613415614cc1565b6000918252602090912001555b508061342d81614d97565b915050613266565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061346e5750738412ebf45bac1b340bbe8f318b928c466c4e39ca33145b6134d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610cb8565b8051670de0b6b3a76400001115613547576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4d757374206265203e3d204d554c2050524543000000000000000000000000006044820152606401610cb8565b6080810151600111801590613561575060a0810151600111155b6135c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4d757374206265203e3d203100000000000000000000000000000000000000006044820152606401610cb8565b80516006556020810151600a556040810151600b556060810151600955608081015160075560a00151600855565b6135ff6000613263565b613607611510565b600355600454421061361d5761361b614553565b565b61361b614886565b60008183106136345781613636565b825b9392505050565b600085600161364c82826113ec565b6021546301000000900460ff16156136c0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f5374616b696e67207061757365640000000000000000000000000000000000006044820152606401610cb8565b60085485101561372c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d696e696d756d207374616b652074696d65206e6f74206d65740000000000006044820152606401610cb8565b600754851115613798576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f547279696e6720746f206c6f636b20666f7220746f6f206c6f6e6700000000006044820152606401610cb8565b6021546137c69065010000000000900473ffffffffffffffffffffffffffffffffffffffff16883089614152565b60006137d186610b7a565b73ffffffffffffffffffffffffffffffffffffffff8a166000908152601d602090815260408083205490517fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060608f901b169281019290925260348201899052605482018b9052607482015291925090609401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012073ffffffffffffffffffffffffffffffffffffffff8e1660009081526024835283902060a0850184528185529184018a90529183018b905290925090606081016138c48a8a614d84565b815260209081018590528254600181810185556000948552828520845160059093020191825591830151918101919091556040820151600282015560608201516003820155608090910151600490910155601b80548a9290613927908490614d84565b909155505073ffffffffffffffffffffffffffffffffffffffff8a166000908152601d6020526040812080548a9290613961908490614d84565b90915550600090506139728b612406565b905073ffffffffffffffffffffffffffffffffffffffff8116156139cb5773ffffffffffffffffffffffffffffffffffffffff81166000908152601f6020526040812080548b92906139c5908490614d84565b90915550505b506139d78a60006113ec565b604080518981526020810189905290810182905273ffffffffffffffffffffffffffffffffffffffff8a811660608301528b16907ff400e72e69ef4402819dfc57eeddc66f5eb69bf405e0e8098b1946ec1ac14a229060800160405180910390a29998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff811615613149576000613a6c826109fb565b905060005b8151811015613ada57818181518110613a8c57613a8c614cc1565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff85166000908152601783526040808220858352909352919091205580613ad281614d97565b915050613a71565b5060005b8151811015611d215760158181548110613afa57613afa614cc1565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff8616835260168252604080842085855290925291205580613b3d81614d97565b915050613ade565b6000613b5342600454613625565b905090565b6060836001613b6782826113ec565b73ffffffffffffffffffffffffffffffffffffffff8616600090815260186020526040902042905560215462010000900460ff1615613c02576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f5265776172647320636f6c6c656374696f6e20706175736564000000000000006044820152606401610cb8565b60105467ffffffffffffffff811115613c1d57613c1d614bed565b604051908082528060200260200182016040528015613c46578160200160208202803683370190505b50925060005b601054811015613e1a5773ffffffffffffffffffffffffffffffffffffffff871660009081526017602090815260408083208484529091529020548451859083908110613c9b57613c9b614cc1565b60209081029190910181019190915273ffffffffffffffffffffffffffffffffffffffff881660009081526017825260408082208483529092529081208190558451859083908110613cef57613cef614cc1565b60200260200101511115613e0857613d5e60108281548110613d1357613d13614cc1565b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1687868481518110613d5157613d51614cc1565b6020026020010151613e24565b8673ffffffffffffffffffffffffffffffffffffffff167f1d2f2ca53af5d2f333bd32fdd45f9c52ad8ebe31414f7792912077fcb3876dff858381518110613da857613da8614cc1565b602002602001015160108481548110613dc357613dc3614cc1565b600091825260209182902001546040805193845273ffffffffffffffffffffffffffffffffffffffff918216928401929092528a169082015260600160405180910390a25b80613e1281614d97565b915050613c4c565b5050509392505050565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790529151600092839290871691613ebb9190614e0c565b6000604051808303816000865af19150503d8060008114613ef8576040519150601f19603f3d011682016040523d82523d6000602084013e613efd565b606091505b5091509150818015613f27575080511580613f27575080806020019051810190613f279190614e28565b611508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c4544006044820152606401610cb8565b613fc26040518060a0016040528060008019168152602001600081526020016000815260200160008152602001600081525090565b6000805b73ffffffffffffffffffffffffffffffffffffffff85166000908152602460205260409020548110156140e05773ffffffffffffffffffffffffffffffffffffffff8516600090815260246020526040902080548290811061402a5761402a614cc1565b90600052602060002090600502016000015484036140ce5773ffffffffffffffffffffffffffffffffffffffff8516600090815260246020526040902080548290811061407957614079614cc1565b90600052602060002090600502016040518060a00160405290816000820154815260200160018201548152602001600282015481526020016003820154815260200160048201548152505092508091506140e0565b806140d881614d97565b915050613fc6565b508151831461414b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5374616b65206e6f7420666f756e6400000000000000000000000000000000006044820152606401610cb8565b9250929050565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd0000000000000000000000000000000000000000000000000000000017905291516000928392908816916141f19190614e0c565b6000604051808303816000865af19150503d806000811461422e576040519150601f19603f3d011682016040523d82523d6000602084013e614233565b606091505b509150915081801561425d57508051158061425d57508080602001905181019061425d9190614e28565b6142e8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f5472616e7366657248656c7065723a205452414e534645525f46524f4d5f464160448201527f494c4544000000000000000000000000000000000000000000000000000000006064820152608401610cb8565b505050505050565b60006142fe84846001613b58565b5060008061430c8685613f8d565b9150915081606001514210158061432a575060215460ff1615156001145b614390576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616b65206973207374696c6c206c6f636b656421000000000000000000006044820152606401610cb8565b60408201518015614549576021546143c89065010000000000900473ffffffffffffffffffffffffffffffffffffffff168783613e24565b80601b60008282546143da9190614d1f565b909155505073ffffffffffffffffffffffffffffffffffffffff87166000908152601d602052604081208054839290614414908490614d1f565b909155506000905061442588612406565b905073ffffffffffffffffffffffffffffffffffffffff81161561447e5773ffffffffffffffffffffffffffffffffffffffff81166000908152601f602052604081208054849290614478908490614d1f565b90915550505b5073ffffffffffffffffffffffffffffffffffffffff871660009081526024602052604090208054839081106144b6576144b6614cc1565b6000918252602082206005909102018181556001810182905560028101829055600381018290556004018190556144ee9088906113ec565b604080518281526020810187905273ffffffffffffffffffffffffffffffffffffffff888116828401529151918916917f1d9308f6b22a2754a1c622bb30889e8f8f956c83e524d039e9d65d5f052eb9089181900360600190a25b9695505050505050565b60005b6012548110156146445760006012828154811061457557614575614cc1565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1690508015614631576040517f092193ab00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff82169063092193ab9060240160408051808303816000875af115801561460a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061462e9190614e45565b50505b508061463c81614d97565b915050614556565b50600062093a80600454426146599190614d1f565b6146639190614d49565b905060005b601054811015614846576010818154811061468557614685614cc1565b6000918252602090912001546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa1580156146fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147209190614dcf565b61472b836001614d84565b62093a806147388461314c565b6147429190614d32565b61474c9190614d32565b11156010828154811061476157614761614cc1565b60009182526020918290200154604080517f4e6f7420656e6f7567682072657761726420746f6b656e7320617661696c6162938101939093527f6c653a20000000000000000000000000000000000000000000000000000000009083015260601b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016604482015260580160405160208183030381529060405290614833576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cb89190614e69565b508061483e81614d97565b915050614668565b5062093a80614856826001614d84565b6148609190614d32565b60045461486d9190614d84565b600455614878614886565b614880611510565b60035550565b60006148906115a6565b905060005b6015548110156148ea578181815181106148b1576148b1614cc1565b6020026020010151601582815481106148cc576148cc614cc1565b600091825260209091200155806148e281614d97565b915050614895565b506148f3613b45565b60055550565b803573ffffffffffffffffffffffffffffffffffffffff8116811461246357600080fd5b60006020828403121561492f57600080fd5b613636826148f9565b6020808252825182820181905260009190848201906040850190845b8181101561497057835183529284019291840191600101614954565b50909695505050505050565b60006020828403121561498e57600080fd5b5035919050565b6020808252825182820181905260009190848201906040850190845b8181101561497057835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016149b1565b600080604083850312156149f657600080fd5b50508035926020909101359150565b602080825282518282018190526000919060409081850190868401855b82811015614a665781518051855286810151878601528581015186860152606080820151908601526080908101519085015260a09093019290850190600101614a22565b5091979650505050505050565b60008060408385031215614a8657600080fd5b614a8f836148f9565b9150614a9d602084016148f9565b90509250929050565b801515811461314957600080fd5b60008060408385031215614ac757600080fd5b614ad0836148f9565b91506020830135614ae081614aa6565b809150509250929050565b60008060408385031215614afe57600080fd5b614b07836148f9565b946020939093013593505050565b600080600060608486031215614b2a57600080fd5b8335614b3581614aa6565b92506020840135614b4581614aa6565b91506040840135614b5581614aa6565b809150509250925092565b60008060008060808587031215614b7657600080fd5b614b7f856148f9565b935060208501359250614b94604086016148f9565b9150614ba2606086016148f9565b905092959194509250565b60008060408385031215614bc057600080fd5b82359150614a9d602084016148f9565b600060208284031215614be257600080fd5b813561363681614aa6565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600060c08284031215614c2e57600080fd5b82601f830112614c3d57600080fd5b60405160c0810181811067ffffffffffffffff82111715614c87577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040528060c0840185811115614c9c57600080fd5b845b81811015614cb6578035835260209283019201614c9e565b509195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b81810381811115610ba057610ba0614cf0565b8082028115828204841417610ba057610ba0614cf0565b600082614d7f577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820180821115610ba057610ba0614cf0565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614dc857614dc8614cf0565b5060010190565b600060208284031215614de157600080fd5b5051919050565b60005b83811015614e03578181015183820152602001614deb565b50506000910152565b60008251614e1e818460208701614de8565b9190910192915050565b600060208284031215614e3a57600080fd5b815161363681614aa6565b60008060408385031215614e5857600080fd5b505080516020909101519092909150565b6020815260008251806020840152614e88816040850160208701614de8565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fea264697066735822122014c1a22e1cdb68c3efe6ae17cf9f9a6019fd213f84cbe232a6c0ee2c6695275564736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000b1748c79709f4ba2dd82834b8c82d4a505003f2700000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000af1b82809296e52a42b3452c52e301369ce2055400000000000000000000000000000000000000000000000000000000000000010000000000000000000000003432b6a60d23ca0dfca7761b7ab56459d9c964d00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000b1748c79709f4ba2dd82834b8c82d4a505003f27000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000a86cc92e3da000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000278dc748eda1d8efef1adfb518542612b49fcd34
-----Decoded View---------------
Arg [0] : _owner (address): 0xB1748C79709f4Ba2Dd82834B8c82D4a505003f27
Arg [1] : _rewardTokens (address[]): 0x3432B6A60D23Ca0dFCa7761B7ab56459D9C964D0
Arg [2] : _rewardManagers (address[]): 0xB1748C79709f4Ba2Dd82834B8c82D4a505003f27
Arg [3] : _rewardRates (uint256[]): 11574074074074
Arg [4] : _gaugeControllers (address[]): 0x0000000000000000000000000000000000000000
Arg [5] : _rewardDistributors (address[]): 0x278dC748edA1d8eFEf1aDFB518542612b49Fcd34
Arg [6] : _stakingToken (address): 0xAF1b82809296E52A42B3452c52e301369Ce20554
-----Encoded View---------------
17 Constructor Arguments found :
Arg [0] : 000000000000000000000000b1748c79709f4ba2dd82834b8c82d4a505003f27
Arg [1] : 00000000000000000000000000000000000000000000000000000000000000e0
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000120
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000160
Arg [4] : 00000000000000000000000000000000000000000000000000000000000001a0
Arg [5] : 00000000000000000000000000000000000000000000000000000000000001e0
Arg [6] : 000000000000000000000000af1b82809296e52a42b3452c52e301369ce20554
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [8] : 0000000000000000000000003432b6a60d23ca0dfca7761b7ab56459d9c964d0
Arg [9] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [10] : 000000000000000000000000b1748c79709f4ba2dd82834b8c82d4a505003f27
Arg [11] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [12] : 00000000000000000000000000000000000000000000000000000a86cc92e3da
Arg [13] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [14] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [15] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [16] : 000000000000000000000000278dc748eda1d8efef1adfb518542612b49fcd34
Deployed Bytecode Sourcemap
88581:1400:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;35403:529;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;37613:477;;;;;;:::i;:::-;;:::i;:::-;;;1374:25:1;;;1362:2;1347:18;37613:477:0;1228:177:1;33682:109:0;;;:::i;:::-;;;;;;;:::i;23028:141::-;;;;;;:::i;:::-;;:::i;:::-;;83546:190;;;;;;:::i;:::-;;:::i;35996:339::-;;;:::i;78801:133::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;38309:179::-;;;;;;:::i;:::-;;:::i;67578:23::-;;;;;;;;;;;;3738:42:1;3726:55;;;3708:74;;3696:2;3681:18;67578:23:0;3547:241:1;33346:298:0;;;;;;:::i;:::-;;:::i;:::-;;;4223:14:1;;4216:22;4198:41;;4186:2;4171:18;33346:298:0;4058:187:1;30722:60:0;;;;;;:::i;:::-;;;;;;;;;;;;;;;;39857:1752;;;;;;:::i;:::-;;:::i;37049:127::-;;;;;;:::i;:::-;37142:26;;37115:7;37142:26;;;:17;:26;;;;;;;37049:127;29662:48;;29704:6;29662:48;;45724:238;;;;;;:::i;:::-;;:::i;29290:49::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;67542:29;;;;;;;;;39009:181;;;;;;:::i;:::-;;:::i;22796:29::-;;;;;;;;;43558:1522;;;;;;:::i;:::-;;:::i;89470:508::-;;;:::i;36763:111::-;36844:22;;36763:111;;29543:55;;;;;;:::i;:::-;;;;;;;;;;;;;;30054:54;;;;;;:::i;:::-;;;;;;;;;;;;;;28564:37;;;;;;34506:681;;;:::i;67490:45::-;;;;;;;;;;;;73992:2692;;;;;;:::i;:::-;;:::i;46431:206::-;;;;;;:::i;:::-;;:::i;68133:53::-;;;;;;:::i;:::-;;:::i;:::-;;;;5958:25:1;;;6014:2;5999:18;;5992:34;;;;6042:18;;;6035:34;;;;6100:2;6085:18;;6078:34;6143:3;6128:19;;6121:35;5945:3;5930:19;68133:53:0;5699:463:1;23177:271:0;;;:::i;30513:52::-;;;;;;:::i;:::-;;;;;;;;;;;;;;39198:199;;;;;;:::i;:::-;;:::i;53429:1013::-;;;;;;:::i;:::-;;:::i;76745:1961::-;;;;;;:::i;:::-;;:::i;:::-;;;;6369:25:1;;;6425:2;6410:18;;6403:34;;;;6453:18;;;6446:34;6357:2;6342:18;76745:1961:0;6167:319:1;22769:20:0;;;;;;;;;53139:161;;;;;;:::i;:::-;;:::i;30913:26::-;;;;;;;;;38591:224;;;;;;:::i;:::-;;:::i;28658:55::-;;;;;;80675:1325;;;;;;:::i;:::-;;:::i;28411:61::-;;;;;;46251:172;;;;;;:::i;:::-;;:::i;39405:444::-;;;;;;:::i;:::-;;:::i;28257:29::-;;;;;;79010:133;;;;;;:::i;:::-;79107:21;;79080:7;79107:21;;;:12;:21;;;;;:28;;79010:133;52589:311;;;;;;:::i;:::-;;:::i;28337:50::-;;;;;;28060:30;;;;;;82054:1357;;;;;;:::i;:::-;;:::i;38135:166::-;;;;;;:::i;:::-;;:::i;55485:483::-;;;;;;:::i;:::-;;:::i;42592:800::-;;;;;;:::i;:::-;;:::i;36597:128::-;;;;;;:::i;:::-;36691:26;;36664:7;36691:26;;;:17;:26;;;;;;;36597:128;56043:207;;;;;;:::i;:::-;;:::i;36433:113::-;36515:23;;36433:113;;52993:97;;;:::i;85809:259::-;;;;;;:::i;:::-;;:::i;41867:610::-;;;;;;:::i;:::-;;:::i;28223:27::-;;;;;;28796:51;;;;;;28872:59;;;;;;33984:452;;;;;;:::i;:::-;;:::i;51279:761::-;;;;;;:::i;:::-;;:::i;54450:958::-;;;;;;:::i;:::-;;:::i;52048:363::-;;;:::i;35403:529::-;35457:27;35497;35527:17;:15;:17::i;:::-;35582:12;:19;35497:47;;-1:-1:-1;35568:34:0;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;35568:34:0;-1:-1:-1;35619:26:0;;;35648:1;35619:26;;;:17;:26;;;;;;35555:47;;-1:-1:-1;35619:30:0;35615:310;;35670:9;35665:249;35689:12;:19;35685:23;;35665:249;;;35879:16;;;;;;;:7;:16;;;;;;;;:19;;;;;;;;;35798:32;;;:23;:32;;;;;:35;;;;;;;;;35782:13;;35838:4;;35798:35;35782:10;;35896:1;;35782:13;;;;;;:::i;:::-;;;;;;;:51;;;;:::i;:::-;35752:26;;;;;;;:17;:26;;;;;;:82;;;;:::i;:::-;35751:91;;;;:::i;:::-;35750:148;;;;:::i;:::-;35734:10;35745:1;35734:13;;;;;;;;:::i;:::-;;;;;;;;;;:164;35710:3;;;;:::i;:::-;;;;35665:249;;;;35615:310;35486:446;35403:529;;;:::o;37613:477::-;37977:19;;38042:28;;37672:7;;37954:127;;38012:26;37977:19;38012:4;:26;:::i;:::-;38011:59;;;;:::i;:::-;37954:8;:127::i;:::-;37947:134;37613:477;-1:-1:-1;;37613:477:0:o;33682:109::-;33735:16;33771:12;33764:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;33682:109;:::o;23028:141::-;23508:5;;;;23494:10;:19;23486:79;;;;;;;10777:2:1;23486:79:0;;;10759:21:1;10816:2;10796:18;;;10789:30;10855:34;10835:18;;;10828:62;10926:17;10906:18;;;10899:45;10961:19;;23486:79:0;;;;;;;;;23100:14:::1;:23:::0;;;::::1;;::::0;::::1;::::0;;::::1;::::0;;;23139:22:::1;::::0;3708:74:1;;;23139:22:0::1;::::0;3696:2:1;3681:18;23139:22:0::1;;;;;;;23028:141:::0;:::o;83546:190::-;83631:7;21703:1;22309:7;;:19;22301:63;;;;;;;11193:2:1;22301:63:0;;;11175:21:1;11232:2;11212:18;;;11205:30;11271:33;11251:18;;;11244:61;11322:18;;22301:63:0;10991:355:1;22301:63:0;21703:1;22442:18;;83658:70:::1;83671:10;::::0;83695:9;83706:4;83712:15:::1;83658:12;:70::i;:::-;21659:1:::0;22621:7;:22;83651:77;83546:190;-1:-1:-1;;;83546:190:0:o;35996:339::-;36146:17;:24;36051:41;;36132:39;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;36132:39:0;;36105:66;;36189:9;36184:144;36208:17;:24;36204:28;;36184:144;;;29704:6;36284:14;36296:1;36284:11;:14::i;:::-;:32;;;;:::i;:::-;36254:24;36279:1;36254:27;;;;;;;;:::i;:::-;;;;;;;;;;:62;36234:3;;;;:::i;:::-;;;;36184:144;;;;35996:339;:::o;78801:133::-;78905:21;;;;;;;:12;:21;;;;;;;;78898:28;;;;;;;;;;;;;;;;;78865:20;;78898:28;;78905:21;;78898:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;78801:133;;;:::o;38309:179::-;38424:32;;;38378:7;38424:32;;;:17;:32;;;;;;38406:15;;28188:4;;38406:50;;;:::i;:::-;38405:75;;;;:::i;33346:298::-;33442:4;33477:5;;;;;;33462:20;;;;33458:136;;-1:-1:-1;33491:4:0;33484:11;;33458:136;33533:48;:33;;;;;;;:14;:33;;;;;;:48;;;:33;;:48;33529:65;;-1:-1:-1;33590:4:0;33583:11;;33529:65;-1:-1:-1;33630:5:0;33346:298;;;;:::o;39857:1752::-;39920:24;;;40081:20;40093:7;40081:11;:20::i;:::-;40061:40;-1:-1:-1;40132:23:0;;;;40131:81;;40186:26;;;;;:15;3726:55:1;;;40186:26:0;;;3708:74:1;40186:5:0;:15;;;;3681:18:1;;40186:26:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;40131:81;;;40159:24;;;;;:15;3726:55:1;;;40159:24:0;;;3708:74:1;40159:5:0;:15;;;;3681:18:1;;40159:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;40112:100;;40318:19;28188:4;40442:5;:17;;;:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:42;;;;:::i;:::-;40383:24;;40360:20;;40341:39;;:16;:39;:::i;:::-;:66;;;;:::i;:::-;40340:145;;;;:::i;:::-;40318:167;-1:-1:-1;40594:19:0;;40809:23;;;;40808:94;;40867:35;40892:9;40867:24;:35::i;:::-;40808:94;;;40836:28;40856:7;40836:19;:28::i;:::-;40779:123;-1:-1:-1;40923:30:0;;40919:323;;40974:27;41048:26;41005:39;28188:4;41005:16;:39;:::i;:::-;41004:70;;;;:::i;:::-;40974:100;;28188:4;41148:20;;41126:19;:42;;;;:::i;:::-;41125:67;;;;:::i;:::-;41111:81;;40954:254;40919:323;;;41241:1;41227:15;;40919:323;40624:699;41410:11;41396;:25;:53;;41438:11;41396:53;;;41424:11;41396:53;41376:74;;41540:20;;41521:16;:39;41517:84;;;41581:20;;41562:39;;41517:84;39946:1663;;;;39857:1752;;;:::o;45724:238::-;21703:1;22309:7;;:19;22301:63;;;;;;;11193:2:1;22301:63:0;;;11175:21:1;11232:2;11212:18;;;11205:30;11271:33;11251:18;;;11244:61;11322:18;;22301:63:0;10991:355:1;22301:63:0;21703:1;22442:18;;45821:23:::1;::::0;;;::::1;;;:32;45813:70;;;::::0;::::1;::::0;;11742:2:1;45813:70:0::1;::::0;::::1;11724:21:1::0;11781:2;11761:18;;;11754:30;11820:27;11800:18;;;11793:55;11865:18;;45813:70:0::1;11540:349:1::0;45813:70:0::1;-1:-1:-1::0;21659:1:0;22621:7;:22;45724:238::o;39009:181::-;39076:7;28188:4;39130:28;;39104:23;39119:7;39104:14;:23::i;:::-;:54;;;;:::i;43558:1522::-;43745:8;43741:46;;;43769:6;:4;:6::i;:::-;43811:21;;;;43807:1266;;44025:27;44071:28;44118:27;44163:30;44185:7;44163:21;:30::i;:::-;44003:190;;;;;;44255:20;44267:7;44255:11;:20::i;:::-;44351:31;;;;;;;:22;:31;;;;;:54;;;44492:42;;;44488:572;;44555:19;44577:41;44599:19;44577;:41;:::i;:::-;44555:63;;44687:11;44662:22;;:36;;;;:::i;:::-;44637:22;:61;44746:33;44768:11;44746:19;:33;:::i;:::-;44717:26;;;;;;;:17;:26;;;;;:62;-1:-1:-1;44488:572:0;;;44820:19;44842:41;44864:19;44842;:41;:::i;:::-;44820:63;;44952:11;44927:22;;:36;;;;:::i;:::-;44902:22;:61;45011:33;45033:11;45011:19;:33;:::i;:::-;44982:26;;;;;;;:17;:26;;;;;:62;-1:-1:-1;44488:572:0;43834:1239;;;43807:1266;43558:1522;;:::o;89470:508::-;89526:7;89607:25;89920:1;89897:9;;;;;;;;;;;:18;;;:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;34506:681::-;34554:41;34612:23;;34639:1;34612:28;:59;;;-1:-1:-1;34644:22:0;;:27;34612:59;34608:572;;;34695:21;34688:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;34506:681;:::o;34608:572::-;34799:12;:19;34785:34;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;34785:34:0;;34758:61;;34839:9;34834:289;34858:21;:28;34854:32;;34834:289;;;35066:22;;35041:14;35053:1;35041:11;:14::i;:::-;35023;;34994:26;:24;:26::i;:::-;:43;;;;:::i;:::-;34993:62;;;;:::i;:::-;:69;;35058:4;34993:69;:::i;:::-;34992:96;;;;:::i;:::-;34942:21;34964:1;34942:24;;;;;;;;:::i;:::-;;;;;;;;;:165;;;;:::i;:::-;34912:24;34937:1;34912:27;;;;;;;;:::i;:::-;;;;;;;;;;:195;34888:3;;;;:::i;:::-;;;;34834:289;;73992:2692;74183:21;;;74081:32;74183:21;;;:12;:21;;;;;:32;;74081;;74183:21;74205:9;;74183:32;;;;;;:::i;:::-;;;;;;;;;74152:63;;;;;;;;74183:32;;;;;;;74152:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;74398:28;;;;;:19;:28;;;;;;74152:63;;-1:-1:-1;;74394:224:0;;;-1:-1:-1;74491:25:0;;;;74394:224;;;-1:-1:-1;74578:28:0;;;;;;;:19;:28;;;;;;74394:224;74707:15;74677:9;:26;;;:45;74673:1802;;74902:26;;;;74871:28;;;;;;;:19;:28;;;;;;:57;74867:1087;;;74948:26;75006:17;74977:9;:26;;;:46;;;;:::i;:::-;74948:75;;75042:25;75088:9;:26;;;75070:15;:44;;;;:::i;:::-;75042:72;-1:-1:-1;75194:33:0;75230:38;75245:22;75266:1;75245:18;:22;:::i;75230:38::-;75194:74;-1:-1:-1;75485:17:0;75557:21;75561:17;75485;75557:21;:::i;:::-;75506:46;75534:18;75506:25;:46;:::i;:::-;75505:74;;;;:::i;:::-;75485:94;-1:-1:-1;75638:38:0;75659:17;75638:18;:38;:::i;:::-;75625:52;;:9;:52;:::i;:::-;75598:79;;74929:764;;;;74673:1802;;74867:1087;75937:1;75910:28;;74673:1802;;;76099:21;76154:20;76206:17;76177:9;:26;;;:46;;;;:::i;:::-;76154:69;;76242:20;76294:15;76265:9;:26;;;:44;;;;:::i;:::-;76242:67;-1:-1:-1;76376:1:0;76345:27;76242:67;76345:12;:27;:::i;:::-;76344:33;;;;:::i;:::-;76328:49;;76135:258;;76434:29;76449:13;76434:14;:29::i;:::-;76407:56;;76019:456;74673:1802;76597:9;:25;;;76570:24;:52;76566:110;;;76651:9;:25;;;76624:52;;76566:110;74115:2569;;73992:2692;;;;:::o;46431:206::-;46533:16;21703:1;22309:7;;:19;22301:63;;;;;;;11193:2:1;22301:63:0;;;11175:21:1;11232:2;11212:18;;;11205:30;11271:33;11251:18;;;11244:61;11322:18;;22301:63:0;10991:355:1;22301:63:0;21703:1;22442:18;;46569:60:::1;46580:10;46592:19:::0;46613:15;46569:10:::1;:60::i;68133:53::-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;68133:53:0;;-1:-1:-1;68133:53:0;;;:::o;23177:271::-;23246:14;;;;23232:10;:28;23224:94;;;;;;;12096:2:1;23224:94:0;;;12078:21:1;12135:2;12115:18;;;12108:30;12174:34;12154:18;;;12147:62;12245:23;12225:18;;;12218:51;12286:19;;23224:94:0;11894:417:1;23224:94:0;23347:5;;;23354:14;23334:35;;;23347:5;;;;12551:34:1;;23354:14:0;;;;12616:2:1;12601:18;;12594:43;23334:35:0;;12463:18:1;23334:35:0;;;;;;;23388:14;;;;23380:22;;;;;;23388:14;;;23380:22;;;;23413:27;;;23177:271::o;39198:199::-;39276:7;28188:4;39337:28;;39304:30;39320:13;39304:15;:30::i;53429:1013::-;31540:5;;53515:12;;31540:5;;31526:10;:19;;:74;;;31549:51;31567:10;31579:20;31549:17;:51::i;:::-;31518:107;;;;;;;12850:2:1;31518:107:0;;;12832:21:1;12889:2;12869:18;;;12862:30;12928:22;12908:18;;;12901:50;12968:18;;31518:107:0;12648:344:1;31518:107:0;53597:18:::1;53639:9:::0;53634:192:::1;53658:12;:19:::0;53654:23;::::1;53634:192;;;53722:12;53703:31;;:12;53716:1;53703:15;;;;;;;;:::i;:::-;;::::0;;;::::1;::::0;;;::::1;::::0;::::1;;:31:::0;53699:116:::1;;53771:4;53755:20;;53794:5;;53699:116;53679:3:::0;::::1;::::0;::::1;:::i;:::-;;;;53634:192;;;;54052:13;:59;;;;-1:-1:-1::0;54069:42:0::1;:28:::0;;::::1;;::::0;;;:14:::1;:28;::::0;;;;;::::1;54101:10;54069:42;54052:59;54051:123;;;;54135:13;54134:14;:39;;;;-1:-1:-1::0;54167:5:0::1;::::0;::::1;;54153:10;:19;54134:39;54029:406;;;54205:66;54233:12;54247:10;54259:11;54205:27;:66::i;:::-;54286:7;53429:1013:::0;;;:::o;54029:406::-:1;54387:36;::::0;::::1;::::0;;13199:2:1;54387:36:0::1;::::0;::::1;13181:21:1::0;13238:2;13218:18;;;13211:30;13277:28;13257:18;;;13250:56;13323:18;;54387:36:0::1;12997:350:1::0;31636:1:0::1;53429:1013:::0;;;:::o;76745:1961::-;77048:26;;;76846:27;77048:26;;;:17;:26;;;;;;;76846:27;77235:24;77066:7;77235:15;:24::i;:::-;77335:26;;;77272:33;77335:26;;;:17;:26;;;;;;77212:47;;-1:-1:-1;77272:33:0;77335:31;:66;;;;-1:-1:-1;77370:26:0;;;;;;;:17;:26;;;;;;:31;77335:66;77334:143;;;-1:-1:-1;77445:31:0;;;;;;;:22;:31;;;;;;77421:55;;;77334:143;77316:638;;;-1:-1:-1;77718:20:0;77316:638;;;77906:31;;;;;;;:22;:31;;;;;;77941:1;;77883:54;;:20;:54;:::i;:::-;77882:60;;;;:::i;:::-;77854:88;;77316:638;78089:1;78067:23;;78106:9;78101:598;78125:21;;;;;;;:12;:21;;;;;:28;78121:32;;78101:598;;;78206:21;;;78175:28;78206:21;;;:12;:21;;;;;:24;;78228:1;;78206:24;;;;;;:::i;:::-;;;;;;;;;;;78175:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;78302:32;78337:34;78360:7;78369:1;78337:22;:34::i;:::-;78453:19;;;;78302:69;;-1:-1:-1;78433:17:0;28188:4;78548:52;78575:25;78302:69;78548:52;:::i;:::-;78535:66;;:9;:66;:::i;:::-;78534:91;;;;:::i;:::-;78521:105;;:9;:105;:::i;:::-;78487:139;-1:-1:-1;78641:46:0;78487:139;78641:46;;:::i;:::-;;;78160:539;;;;78155:3;;;;;:::i;:::-;;;;78101:598;;;;76975:1731;76745:1961;;;;;:::o;53139:161::-;31337:5;;;;31323:10;:19;;:79;;-1:-1:-1;31360:42:0;31346:10;:56;31323:79;31315:113;;;;;;;13554:2:1;31315:113:0;;;13536:21:1;13593:2;13573:18;;;13566:30;13632:23;13612:18;;;13605:51;13673:18;;31315:113:0;13352:345:1;31315:113:0;53260:32:::1;;;::::0;;;:19:::1;:32;::::0;;;;;;53224:68;;::::1;53260:32;::::0;;::::1;53259:33;53224:68;::::0;;53139:161::o;38591:224::-;38657:7;38791:15;;38760:28;;:46;;;;:::i;:::-;38685:24;;;;;:15;3726:55:1;;;38685:24:0;;;3708:74:1;28188:4:0;;;;38685:5;:15;;;;3681:18:1;;38685:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:47;;;;:::i;80675:1325::-;21703:1;22309:7;;:19;22301:63;;;;;;;11193:2:1;22301:63:0;;;11175:21:1;11232:2;11212:18;;;11205:30;11271:33;11251:18;;;11244:61;11322:18;;22301:63:0;10991:355:1;22301:63:0;21703:1;22442:18;;80772:10:::1;80784:4;31731:41;80772:10:::0;80784:4;31731:22:::1;:41::i;:::-;80849:28:::2;80879:21:::0;80904:29:::2;80914:10;80926:6;80904:9;:29::i;:::-;80848:85;;;;80983:15;81023:8;81001:9;:19;;;:30;;;;:::i;:::-;80983:48:::0;-1:-1:-1;81202:12:0::2;::::0;81162:91:::2;::::0;81202:12;;::::2;;;81217:10;81237:4;81244:8:::0;81162:31:::2;:91::i;:::-;81337:186;::::0;;::::2;::::0;::::2;::::0;;;;;::::2;81384:25:::0;;::::2;::::0;81337:186;;::::2;::::0;;;;;;;;81446:26;;::::2;::::0;81337:186;;;;;81487:25;;::::2;::::0;81337:186;;;;81308:10:::2;-1:-1:-1::0;81295:24:0;;;:12:::2;:24:::0;;;;;;;:39;;81320:13;;81295:39;::::2;;;;;:::i;:::-;;;;;;;;;;;:228;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;81594:8;81567:23;;:35;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;81631:10:0::2;81613:29;::::0;;;:17:::2;:29;::::0;;;;:41;;81646:8;;81613:29;:41:::2;::::0;81646:8;;81613:41:::2;:::i;:::-;::::0;;;-1:-1:-1;81680:17:0::2;::::0;-1:-1:-1;81700:23:0::2;81712:10;81700:11;:23::i;:::-;81680:43:::0;-1:-1:-1;81742:23:0::2;::::0;::::2;::::0;81738:69:::2;;81767:28;::::0;::::2;;::::0;;;:17:::2;:28;::::0;;;;:40;;81799:8;;81767:28;:40:::2;::::0;81799:8;;81767:40:::2;:::i;:::-;::::0;;;-1:-1:-1;;81738:69:0::2;81665:154;81887:41;81910:10;81922:5;81887:22;:41::i;:::-;81946:46;::::0;;14221:25:1;;;14277:2;14262:18;;14255:34;;;81963:10:0::2;::::0;81946:46:::2;::::0;14194:18:1;81946:46:0::2;;;;;;;-1:-1:-1::0;;21659:1:0;22621:7;:22;-1:-1:-1;;;;;80675:1325:0:o;46251:172::-;46330:16;21703:1;22309:7;;:19;22301:63;;;;;;;11193:2:1;22301:63:0;;;11175:21:1;11232:2;11212:18;;;11205:30;11271:33;11251:18;;;11244:61;11322:18;;22301:63:0;10991:355:1;22301:63:0;21703:1;22442:18;;46366:49:::1;46377:10;46389:19:::0;46410:4:::1;46366:10;:49::i;:::-;21659:1:::0;22621:7;:22;46359:56;46251:172;-1:-1:-1;;46251:172:0:o;39405:444::-;39484:25;;;39461:7;39484:25;;;:19;:25;;;;;;;;39480:362;;;-1:-1:-1;39687:4:0;39405:444::o;39480:362::-;-1:-1:-1;39799:31:0;;;;;;;;:25;:31;;;;;;;;39405:444::o;39480:362::-;39405:444;;;:::o;52589:311::-;31337:5;;;;31323:10;:19;;:79;;-1:-1:-1;31360:42:0;31346:10;:56;31323:79;31315:113;;;;;;;13554:2:1;31315:113:0;;;13536:21:1;13593:2;13573:18;;;13566:30;13632:23;13612:18;;;13605:51;13673:18;;31315:113:0;13352:345:1;31315:113:0;52752:13:::1;:30:::0;;52842:50;::::1;;::::0;::::1;::::0;52793:38;::::1;;52752:30;52793:38;::::0;52752:30;::::1;;::::0;::::1;52793:38:::0;;;;;;;;;;;;;;;::::1;52842:50:::0;;;::::1;;::::0;;52589:311::o;82054:1357::-;21703:1;22309:7;;:19;22301:63;;;;;;;11193:2:1;22301:63:0;;;11175:21:1;11232:2;11212:18;;;11205:30;11271:33;11251:18;;;11244:61;11322:18;;22301:63:0;10991:355:1;22301:63:0;21703:1;22442:18;;82152:10:::1;82164:4;31731:41;82152:10:::0;82164:4;31731:22:::1;:41::i;:::-;82229:28:::2;82259:21:::0;82284:29:::2;82294:10;82306:6;82284:9;:29::i;:::-;82228:85;;;;82368:15;82352:13;:31;82344:65;;;::::0;::::2;::::0;;14502:2:1;82344:65:0::2;::::0;::::2;14484:21:1::0;14541:2;14521:18;;;14514:30;14580:23;14560:18;;;14553:51;14621:18;;82344:65:0::2;14300:345:1::0;82344:65:0::2;82455:17;82505:15;82476:9;:26;;;:44;82475:97;;82571:1;82475:97;;;82553:15;82524:9;:26;;;:44;;;;:::i;:::-;82455:117:::0;-1:-1:-1;82583:16:0::2;82602:31;82618:15;82602:13:::0;:31:::2;:::i;:::-;82583:50;;82739:9;82728:8;:20;82720:57;;;::::0;::::2;::::0;;14852:2:1;82720:57:0::2;::::0;::::2;14834:21:1::0;14891:2;14871:18;;;14864:30;14930:26;14910:18;;;14903:54;14974:18;;82720:57:0::2;14650:348:1::0;82720:57:0::2;82808:13;;82796:8;:25;;82788:64;;;::::0;::::2;::::0;;15205:2:1;82788:64:0::2;::::0;::::2;15187:21:1::0;15244:2;15224:18;;;15217:30;15283:28;15263:18;;;15256:56;15329:18;;82788:64:0::2;15003:350:1::0;82788:64:0::2;82883:28;;82871:8;:40;;82863:80;;;::::0;::::2;::::0;;15560:2:1;82863:80:0::2;::::0;::::2;15542:21:1::0;15599:2;15579:18;;;15572:30;15638:29;15618:18;;;15611:57;15685:18;;82863:80:0::2;15358:351:1::0;82863:80:0::2;83027:174;;;;;;;;83053:6;83027:174;;;;83074:15;83027:174;;;;83104:9;:19;;;83027:174;;;;83138:13;83027:174;;;;83166:24;83181:8;83166:14;:24::i;:::-;83027:174:::0;;82998:10:::2;82985:24;::::0;;;:12:::2;:24;::::0;;;;:39;;83010:13;;82985:39;::::2;;;;;:::i;:::-;;;;;;;;;;;:216;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;83270:41;83293:10;83305:5;83270:22;:41::i;:::-;83329:74;::::0;;15945:25:1;;;16001:2;15986:18;;15979:34;;;83372:15:0::2;16029:18:1::0;;;16022:34;16087:2;16072:18;;16065:34;;;83329:74:0;;83342:10:::2;::::0;83329:74:::2;::::0;;;;;15932:3:1;83329:74:0;;::::2;-1:-1:-1::0;;21659:1:0;22621:7;:22;-1:-1:-1;;;;;;82054:1357:0:o;38135:166::-;38243:26;;;38197:7;38243:26;;;:17;:26;;;;;;38225:15;;28188:4;;38225:44;;;:::i;55485:483::-;31540:5;;55651:20;;31540:5;;31526:10;:19;;:74;;;31549:51;31567:10;31579:20;31549:17;:51::i;:::-;31518:107;;;;;;;12850:2:1;31518:107:0;;;12832:21:1;12889:2;12869:18;;;12862:30;12928:22;12908:18;;;12901:50;12968:18;;31518:107:0;12648:344:1;31518:107:0;55702:42:::1;::::0;::::1;;::::0;;;:20:::1;:42;::::0;;;;;55684:17:::1;:61:::0;;55748:9;;55702:42;55684:61;::::1;;;;;:::i;:::-;;;;;;;;:73;;;;55831:25;55768:16;55785:20;:42;55806:20;55785:42;;;;;;;;;;;;;;;;55768:60;;;;;;;;:::i;:::-;;::::0;;;::::1;::::0;;;;;;::::1;:88:::0;;;::::1;;::::0;;::::1;;::::0;;55886:42;;::::1;::::0;;:20:::1;:42:::0;;;;;;;55867:18:::1;:62:::0;;55932:28;;55886:42;55867:62;::::1;;;;;:::i;:::-;;;;;;;;;:93;;;;;;;;;;;;;;;;;;55485:483:::0;;;;;:::o;42592:800::-;42672:34;;;;;;;:19;:34;;;;;;;;42664:60;;;;;;;16312:2:1;42664:60:0;;;16294:21:1;16351:2;16331:18;;;16324:30;16390:15;16370:18;;;16363:43;16423:18;;42664:60:0;16110:337:1;42664:60:0;42743:36;;;;;;;:21;:36;;;;;;;;42780:10;42743:48;;;;;;;;;;42735:90;;;;;;;16654:2:1;42735:90:0;;;16636:21:1;16693:2;16673:18;;;16666:30;16732:31;16712:18;;;16705:59;16781:18;;42735:90:0;16452:353:1;42735:90:0;42971:10;42920:22;42945:37;;;:25;:37;;;;;;;;42997:28;;42993:182;;43152:10;43134:29;;;;:17;:29;;;;;;;;;;43097:33;;;;:17;:33;;;;;:66;;43134:29;;43097:33;;:66;;43134:29;;43097:66;:::i;:::-;;;;-1:-1:-1;;42993:182:0;43243:10;43217:37;;;;:25;:37;;;;;;;:53;;;;:37;:53;;;;;;;;43355:17;:29;;;;;;43319:32;;;:17;:32;;;;;:65;;43355:29;;43319:32;;:65;;43355:29;;43319:65;:::i;:::-;;;;-1:-1:-1;;;;42592:800:0:o;56043:207::-;31540:5;;56151:20;;31540:5;;31526:10;:19;;:74;;;31549:51;31567:10;31579:20;31549:17;:51::i;:::-;31518:107;;;;;;;12850:2:1;31518:107:0;;;12832:21:1;12889:2;12869:18;;;12862:30;12928:22;12908:18;;;12901:50;12968:18;;31518:107:0;12648:344:1;31518:107:0;-1:-1:-1;56184:36:0::1;::::0;;::::1;;::::0;;;:14:::1;:36;::::0;;;;:58;;;::::1;::::0;;;::::1;;::::0;;56043:207::o;52993:97::-;31337:5;;;;31323:10;:19;;:79;;-1:-1:-1;31360:42:0;31346:10;:56;31323:79;31315:113;;;;;;;13554:2:1;31315:113:0;;;13536:21:1;13593:2;13573:18;;;13566:30;13632:23;13612:18;;;13605:51;13673:18;;31315:113:0;13352:345:1;31315:113:0;53068:14:::1;::::0;;53050:32;;::::1;53068:14;::::0;;::::1;53067:15;53050:32;::::0;;52993:97::o;85809:259::-;85909:7;21703:1;22309:7;;:19;22301:63;;;;;;;11193:2:1;22301:63:0;;;11175:21:1;11232:2;11212:18;;;11205:30;11271:33;11251:18;;;11244:61;11322:18;;22301:63:0;10991:355:1;22301:63:0;21703:1;22442:18;;85937:17:::1;::::0;::::1;::::0;::::1;;;:26;85929:57;;;::::0;::::1;::::0;;17012:2:1;85929:57:0::1;::::0;::::1;16994:21:1::0;17051:2;17031:18;;;17024:30;17090:20;17070:18;;;17063:48;17128:18;;85929:57:0::1;16810:342:1::0;85929:57:0::1;86004:56;86020:10;86032:19;86053:6;86004:15;:56::i;41867:610::-:0;41966:10;41946:31;;;;:19;:31;;;;;;;;41938:57;;;;;;;16312:2:1;41938:57:0;;;16294:21:1;16351:2;16331:18;;;16324:30;16390:15;16370:18;;;16363:43;16423:18;;41938:57:0;16110:337:1;41938:57:0;42081:10;42059:33;;;;:21;:33;;;;;;;;;:49;;;;;;;;;;;;;;;;42058:50;42006:102;;;;;;;42211:41;;;;;;;;:55;42207:263;;42282:41;;;42334:1;42282:41;;;:25;:41;;;;;;;:54;;;;;;42425:17;:33;;;;;;42410:10;42392:29;;:17;:29;;;;;:66;;42425:33;;42392:29;;:66;;42425:33;;42392:66;:::i;:::-;;;;-1:-1:-1;;42207:263:0;41867:610;:::o;33984:452::-;34045:16;34074:32;34109:16;34126:9;34109:27;;;;;;;;:::i;:::-;;;;;;;;;;;;;;-1:-1:-1;34151:38:0;;34147:282;;34332:4;34290:27;34318:9;34290:38;;;;;;;;:::i;:::-;;;;;;;;;34239:24;34218:67;;;:69;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:110;;;;:::i;:::-;34217:119;;;;:::i;:::-;34206:130;;34147:282;;;34389:17;34407:9;34389:28;;;;;;;;:::i;:::-;;;;;;;;;34378:39;;34063:373;33984:452;;;:::o;51279:761::-;51396:9;51391:642;51415:16;:23;51411:27;;51391:642;;;51460:32;51495:16;51512:1;51495:19;;;;;;;;:::i;:::-;;;;;;;;;;;;;;-1:-1:-1;51533:38:0;;51529:493;;51596:12;:61;;;;51631:22;51654:1;51631:25;;;;;;;;:::i;:::-;;;;;;;;;51613:15;:43;51596:61;51592:415;;;51771:106;;;;;51854:4;51771:106;;;17331:74:1;51861:15:0;17421:18:1;;;17414:34;51771:74:0;;;;;;17304:18:1;;51771:106:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;51738:27;51766:1;51738:30;;;;;;;;:::i;:::-;;;;;;;;:139;;;;51949:24;51928:57;;;:59;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;51900:22;51923:1;51900:25;;;;;;;;:::i;:::-;;;;;;;;;;:87;51592:415;-1:-1:-1;51440:3:0;;;;:::i;:::-;;;;51391:642;;54450:958;31337:5;;;;31323:10;:19;;:79;;-1:-1:-1;31360:42:0;31346:10;:56;31323:79;31315:113;;;;;;;13554:2:1;31315:113:0;;;13536:21:1;13593:2;13573:18;;;13566:30;13632:23;13612:18;;;13605:51;13673:18;;31315:113:0;13352:345:1;31315:113:0;54859:13;;28188:4:::1;-1:-1:-1::0;54859:37:0::1;54851:69;;;::::0;::::1;::::0;;17661:2:1;54851:69:0::1;::::0;::::1;17643:21:1::0;17700:2;17680:18;;;17673:30;17739:21;17719:18;;;17712:49;17778:18;;54851:69:0::1;17459:343:1::0;54851:69:0::1;55044:13:::0;;::::1;::::0;55061:1:::1;-1:-1:-1::0;55044:18:0;::::1;::::0;55043:44:::1;;-1:-1:-1::0;55068:13:0;;::::1;::::0;55085:1:::1;-1:-1:-1::0;55068:18:0::1;55043:44;55035:69;;;::::0;::::1;::::0;;18350:2:1;55035:69:0::1;::::0;::::1;18332:21:1::0;18389:2;18369:18;;;18362:30;18428:14;18408:18;;;18401:42;18460:18;;55035:69:0::1;18148:336:1::0;55035:69:0::1;55139:13:::0;;55117:19:::1;:35:::0;55139:13:::1;55186::::0;::::1;::::0;55163:20:::1;:36:::0;55241:13;;::::1;::::0;55210:28:::1;:44:::0;55292:13;;::::1;::::0;55265:24:::1;:40:::0;55347:13;;::::1;::::0;55316:28:::1;:44:::0;55387:13;::::1;::::0;55371::::1;:29:::0;54450:958::o;52048:363::-;52131:25;52150:5;52131:18;:25::i;:::-;52226:16;:14;:16::i;:::-;52208:15;:34;52278:12;;52259:15;:31;52255:149;;52307:14;:12;:14::i;:::-;52048:363::o;52255:149::-;52363:29;:27;:29::i;594:106::-;652:7;683:1;679;:5;:13;;691:1;679:13;;;687:1;679:13;672:20;594:106;-1:-1:-1;;;594:106:0:o;83932:1705::-;84178:7;84147:14;84163:4;31731:41;31754:7;31763:8;31731:22;:41::i;:::-;84206:13:::1;::::0;;;::::1;;;:22;84198:49;;;::::0;::::1;::::0;;18691:2:1;84198:49:0::1;::::0;::::1;18673:21:1::0;18730:2;18710:18;;;18703:30;18769:16;18749:18;;;18742:44;18803:18;;84198:49:0::1;18489:338:1::0;84198:49:0::1;84274:13;;84266:4;:21;;84258:60;;;::::0;::::1;::::0;;15205:2:1;84258:60:0::1;::::0;::::1;15187:21:1::0;15244:2;15224:18;;;15217:30;15283:28;15263:18;;;15256:56;15329:18;;84258:60:0::1;15003:350:1::0;84258:60:0::1;84345:28;;84337:4;:36;;84329:75;;;::::0;::::1;::::0;;15560:2:1;84329:75:0::1;::::0;::::1;15542:21:1::0;15599:2;15579:18;;;15572:30;15638:29;15618:18;;;15611:57;15685:18;;84329:75:0::1;15358:351:1::0;84329:75:0::1;84527:12;::::0;84487:96:::1;::::0;84527:12;;::::1;;;84542:14:::0;84566:4:::1;84573:9:::0;84487:31:::1;:96::i;:::-;84643:23;84669:20;84684:4;84669:14;:20::i;:::-;84788:33;::::0;::::1;84700:14;84788:33:::0;;;:17:::1;:33;::::0;;;;;;;;84727:95;;19078:66:1;19065:2;19061:15;;;19057:88;84727:95:0;;::::1;19045:101:1::0;;;;19162:12;;;19155:28;;;19199:12;;;19192:28;;;19236:12;;;19229:28;84643:46:0;;-1:-1:-1;84700:14:0;19273:13:1;;84727:95:0::1;::::0;;;;;::::1;::::0;;;;;;84717:106;;84727:95:::1;84717:106:::0;;::::1;::::0;84880:28:::1;::::0;::::1;;::::0;;;:12:::1;:28:::0;;;;;84914:164:::1;::::0;::::1;::::0;;;;;;;::::1;::::0;;;;;;;;;84717:106;;-1:-1:-1;84880:28:0;84914:164;;;85015:22:::1;85033:4:::0;84961:15;85015:22:::1;:::i;:::-;84914:164:::0;;::::1;::::0;;::::1;::::0;;;84880:199;;::::1;::::0;;::::1;::::0;;-1:-1:-1;84880:199:0;;;;;;;;::::1;::::0;;::::1;;::::0;;;;;::::1;::::0;;;::::1;::::0;;;;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;::::1;::::0;;::::1;::::0;85123:23:::1;:36:::0;;85150:9;;-1:-1:-1;85123:36:0::1;::::0;85150:9;;85123:36:::1;:::i;:::-;::::0;;;-1:-1:-1;;85170:33:0::1;::::0;::::1;;::::0;;;:17:::1;:33;::::0;;;;:46;;85207:9;;85170:33;:46:::1;::::0;85207:9;;85170:46:::1;:::i;:::-;::::0;;;-1:-1:-1;85242:17:0::1;::::0;-1:-1:-1;85262:27:0::1;85274:14:::0;85262:11:::1;:27::i;:::-;85242:47:::0;-1:-1:-1;85308:23:0::1;::::0;::::1;::::0;85304:70:::1;;85333:28;::::0;::::1;;::::0;;;:17:::1;:28;::::0;;;;:41;;85365:9;;85333:28;:41:::1;::::0;85365:9;;85333:41:::1;:::i;:::-;::::0;;;-1:-1:-1;;85304:70:0::1;85227:159;85472:45;85495:14;85511:5;85472:22;:45::i;:::-;85535:68;::::0;;19528:25:1;;;19584:2;19569:18;;19562:34;;;19612:18;;;19605:34;;;85535:68:0::1;19675:55:1::0;;;19670:2;19655:18;;19648:83;85535:68:0;::::1;::::0;::::1;::::0;19515:3:1;19500:19;85535:68:0::1;;;;;;;85623:6:::0;83932:1705;-1:-1:-1;;;;;;;;;83932:1705:0:o;45088:585::-;45150:21;;;;45146:520;;45227:27;45257:15;45264:7;45257:6;:15::i;:::-;45227:45;;45335:9;45330:118;45354:10;:17;45350:1;:21;45330:118;;;45419:10;45430:1;45419:13;;;;;;;;:::i;:::-;;;;;;;;;;;;45397:16;;;;;;;:7;:16;;;;;;:19;;;;;;;;;;:35;45414:1;45373:3;45414:1;45373:3;:::i;:::-;;;;45330:118;;;;45515:9;45510:145;45534:10;:17;45530:1;:21;45510:145;;;45615:21;45637:1;45615:24;;;;;;;;:::i;:::-;;;;;;;;;;;;;45577:32;;;;;:23;:32;;;;;;:35;;;;;;;;:62;45610:1;45553:3;45610:1;45553:3;:::i;:::-;;;;45510:145;;33843:133;33902:7;33929:39;33938:15;33955:12;;33929:8;:39::i;:::-;33922:46;;33843:133;:::o;46733:1194::-;46881:31;46856:8;46866:4;31731:41;31754:7;31763:8;31731:22;:41::i;:::-;47011:29:::1;::::0;::::1;;::::0;;;:19:::1;:29;::::0;;;;47043:15:::1;47011:47:::0;;47141:23:::1;::::0;;;::::1;;;:32;47133:70;;;::::0;::::1;::::0;;11742:2:1;47133:70:0::1;::::0;::::1;11724:21:1::0;11781:2;11761:18;;;11754:30;11820:27;11800:18;;;11793:55;11865:18;;47133:70:0::1;11540:349:1::0;47133:70:0::1;47315:12;:19:::0;47301:34:::1;::::0;::::1;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;-1:-1:-1;47301:34:0::1;;47284:51;;47353:9;47348:419;47372:12;:19:::0;47368:23;::::1;47348:419;;;47433:17;::::0;::::1;;::::0;;;:7:::1;:17;::::0;;;;;;;:20;;;;;;;;;47413:17;;:14;;47451:1;;47413:17;::::1;;;;;:::i;:::-;;::::0;;::::1;::::0;;;;;;:40;;;;47468:17:::1;::::0;::::1;47491:1;47468:17:::0;;;:7:::1;:17:::0;;;;;;:20;;;;;;;;;:24;;;47511:17;;:14;;47486:1;;47511:17;::::1;;;;;:::i;:::-;;;;;;;:21;47507:249;;;47553:84;47581:12;47594:1;47581:15;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;47598:19;47619:14;47634:1;47619:17;;;;;;;;:::i;:::-;;;;;;;47553:27;:84::i;:::-;47674:8;47663:77;;;47684:14;47699:1;47684:17;;;;;;;;:::i;:::-;;;;;;;47703:12;47716:1;47703:15;;;;;;;;:::i;:::-;;::::0;;;::::1;::::0;;;;::::1;::::0;47663:77:::1;::::0;;19944:25:1;;;47703:15:0::1;::::0;;::::1;20046:18:1::0;;;20039:43;;;;20118:15;;20098:18;;;20091:43;19932:2;19917:18;47663:77:0::1;;;;;;;47507:249;47393:3:::0;::::1;::::0;::::1;:::i;:::-;;;;47348:419;;;;46733:1194:::0;;;;;;;:::o;19020:361::-;19215:45;;;19204:10;17349:55:1;;;19215:45:0;;;17331:74:1;17421:18;;;;17414:34;;;19215:45:0;;;;;;;;;;17304:18:1;;;;19215:45:0;;;;;;;;;;;;;19204:57;;-1:-1:-1;;;;19204:10:0;;;;:57;;19215:45;19204:57;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19168:93;;;;19280:7;:57;;;;-1:-1:-1;19292:11:0;;:16;;:44;;;19323:4;19312:24;;;;;;;;;;;;:::i;:::-;19272:101;;;;;;;21144:2:1;19272:101:0;;;21126:21:1;21183:2;21163:18;;;21156:30;21222:33;21202:18;;;21195:61;21273:18;;19272:101:0;20942:355:1;80104:508:0;80186:31;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;80186:31:0;80219:15;;80247:280;80271:28;;;;;;;:12;:28;;;;;:35;80267:39;;80247:280;;;80342:28;;;;;;;:12;:28;;;;;:31;;80371:1;;80342:31;;;;;;:::i;:::-;;;;;;;;;;;:38;;;80332:6;:48;80328:188;;80415:28;;;;;;;:12;:28;;;;;:31;;80444:1;;80415:31;;;;;;:::i;:::-;;;;;;;;;;;80400:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;80475:1;80465:11;;80495:5;;80328:188;80308:3;;;;:::i;:::-;;;;80247:280;;;-1:-1:-1;80545:19:0;;:29;;80537:57;;;;;;;21504:2:1;80537:57:0;;;21486:21:1;21543:2;21523:18;;;21516:30;21582:17;21562:18;;;21555:45;21617:18;;80537:57:0;21302:339:1;80537:57:0;80104:508;;;;;:::o;19389:402::-;19614:51;;;19603:10;21927:15:1;;;19614:51:0;;;21909:34:1;21979:15;;;21959:18;;;21952:43;22011:18;;;;22004:34;;;19614:51:0;;;;;;;;;;21821:18:1;;;;19614:51:0;;;;;;;;;;;;;19603:63;;-1:-1:-1;;;;19603:10:0;;;;:63;;19614:51;19603:63;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19567:99;;;;19685:7;:57;;;;-1:-1:-1;19697:11:0;;:16;;:44;;;19728:4;19717:24;;;;;;;;;;;;:::i;:::-;19677:106;;;;;;;22251:2:1;19677:106:0;;;22233:21:1;22290:2;22270:18;;;22263:30;22329:34;22309:18;;;22302:62;22400:6;22380:18;;;22373:34;22424:19;;19677:106:0;22049:400:1;19677:106:0;19477:314;;19389:402;;;;:::o;86203:1555::-;86349:7;86432:53;86443:14;86459:19;86480:4;86432:10;:53::i;:::-;;86539:28;86569:21;86594:33;86604:14;86620:6;86594:9;:33::i;:::-;86538:89;;;;86665:9;:26;;;86646:15;:45;;:71;;;-1:-1:-1;86695:14:0;;;;:22;;:14;:22;86646:71;86638:106;;;;;;;22656:2:1;86638:106:0;;;22638:21:1;22695:2;22675:18;;;22668:30;22734:24;22714:18;;;22707:52;22776:18;;86638:106:0;22454:346:1;86638:106:0;86775:19;;;;86811:13;;86807:915;;86991:12;;86955:82;;86991:12;;;;;87006:19;87027:9;86955:27;:82::i;:::-;87116:9;87089:23;;:36;;;;;;;:::i;:::-;;;;-1:-1:-1;;87140:33:0;;;;;;;:17;:33;;;;;:46;;87177:9;;87140:33;:46;;87177:9;;87140:46;:::i;:::-;;;;-1:-1:-1;87220:17:0;;-1:-1:-1;87240:27:0;87252:14;87240:11;:27::i;:::-;87220:47;-1:-1:-1;87290:23:0;;;;87286:70;;87315:28;;;;;;;:17;:28;;;;;:41;;87347:9;;87315:28;:41;;87347:9;;87315:41;:::i;:::-;;;;-1:-1:-1;;87286:70:0;-1:-1:-1;87443:28:0;;;;;;;:12;:28;;;;;:43;;87472:13;;87443:43;;;;;;:::i;:::-;;;;;;;;;;;;;87436:50;;;;;;;;;;;;;;;;;;;;;;;;;;87573:45;;87596:14;;87573:22;:45::i;:::-;87640:70;;;23007:25:1;;;23063:2;23048:18;;23041:34;;;87640:70:0;23111:55:1;;;23091:18;;;23084:83;87640:70:0;;;;;;;;;;;22995:2:1;87640:70:0;;;86807:915;87741:9;86203:1555;-1:-1:-1;;;;;;86203:1555:0:o;48014:2814::-;48135:9;48130:327;48154:18;:25;48150:29;;48130:327;;;48201:34;48238:18;48257:1;48238:21;;;;;;;;:::i;:::-;;;;;;;;;;;;;;-1:-1:-1;48278:40:0;;48274:172;;48339:91;;;;;48424:4;48339:91;;;3708:74:1;48339:76:0;;;;;;3681:18:1;;48339:91:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;48274:172;-1:-1:-1;48181:3:0;;;;:::i;:::-;;;;48130:327;;;;48817:27;29704:6;48873:12;;48855:15;:30;;;;:::i;:::-;48847:57;;;;:::i;:::-;48817:87;;49043:9;49038:284;49062:12;:19;49058:23;;49038:284;;;49184:12;49197:1;49184:15;;;;;;;;:::i;:::-;;;;;;;;;;;49177:48;;;;;49219:4;49177:48;;;3708:74:1;49184:15:0;;;;;49177:33;;3681:18:1;;49177:48:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;49148:23;:19;49170:1;49148:23;:::i;:::-;29704:6;49112:14;49124:1;49112:11;:14::i;:::-;:32;;;;:::i;:::-;:60;;;;:::i;:::-;49111:114;;49291:12;49304:1;49291:15;;;;;;;;:::i;:::-;;;;;;;;;;;;49234:73;;;23670:34:1;49234:73:0;;;23658:47:1;;;;23735:6;23721:12;;;23714:28;23780:2;23776:15;;;23758:12;;;23751:110;23877:12;;49234:73:0;;;;;;;;;;;;49103:207;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;49083:3:0;;;;:::i;:::-;;;;49038:284;;;-1:-1:-1;29704:6:0;49534:23;:19;49556:1;49534:23;:::i;:::-;49533:43;;;;:::i;:::-;49517:12;;:60;;;;:::i;:::-;49502:12;:75;49630:29;:27;:29::i;:::-;49729:16;:14;:16::i;:::-;49711:15;:34;-1:-1:-1;48014:2814:0:o;50836:435::-;50923:34;50960:17;:15;:17::i;:::-;50923:54;;51040:9;51035:133;51059:21;:28;51055:32;;51035:133;;;51136:17;51154:1;51136:20;;;;;;;;:::i;:::-;;;;;;;51109:21;51131:1;51109:24;;;;;;;;:::i;:::-;;;;;;;;;;:47;51089:3;;;;:::i;:::-;;;;51035:133;;;;51237:26;:24;:26::i;:::-;51220:14;:43;-1:-1:-1;50836:435:0:o;14:196:1:-;82:20;;142:42;131:54;;121:65;;111:93;;200:1;197;190:12;215:186;274:6;327:2;315:9;306:7;302:23;298:32;295:52;;;343:1;340;333:12;295:52;366:29;385:9;366:29;:::i;406:632::-;577:2;629:21;;;699:13;;602:18;;;721:22;;;548:4;;577:2;800:15;;;;774:2;759:18;;;548:4;843:169;857:6;854:1;851:13;843:169;;;918:13;;906:26;;987:15;;;;952:12;;;;879:1;872:9;843:169;;;-1:-1:-1;1029:3:1;;406:632;-1:-1:-1;;;;;;406:632:1:o;1043:180::-;1102:6;1155:2;1143:9;1134:7;1130:23;1126:32;1123:52;;;1171:1;1168;1161:12;1123:52;-1:-1:-1;1194:23:1;;1043:180;-1:-1:-1;1043:180:1:o;1410:681::-;1581:2;1633:21;;;1703:13;;1606:18;;;1725:22;;;1552:4;;1581:2;1804:15;;;;1778:2;1763:18;;;1552:4;1847:218;1861:6;1858:1;1855:13;1847:218;;;1926:13;;1941:42;1922:62;1910:75;;2040:15;;;;2005:12;;;;1883:1;1876:9;1847:218;;2096:248;2164:6;2172;2225:2;2213:9;2204:7;2200:23;2196:32;2193:52;;;2241:1;2238;2231:12;2193:52;-1:-1:-1;;2264:23:1;;;2334:2;2319:18;;;2306:32;;-1:-1:-1;2096:248:1:o;2531:1011::-;2760:2;2812:21;;;2882:13;;2785:18;;;2904:22;;;2731:4;;2760:2;2945;;2963:18;;;;3004:15;;;2731:4;3047:469;3061:6;3058:1;3055:13;3047:469;;;3120:13;;3158:9;;3146:22;;3208:11;;;3202:18;3188:12;;;3181:40;3261:11;;;3255:18;3241:12;;;3234:40;3297:4;3341:11;;;3335:18;3321:12;;;3314:40;3377:4;3421:11;;;3415:18;3401:12;;;3394:40;3463:4;3454:14;;;;3491:15;;;;3083:1;3076:9;3047:469;;;-1:-1:-1;3533:3:1;;2531:1011;-1:-1:-1;;;;;;;2531:1011:1:o;3793:260::-;3861:6;3869;3922:2;3910:9;3901:7;3897:23;3893:32;3890:52;;;3938:1;3935;3928:12;3890:52;3961:29;3980:9;3961:29;:::i;:::-;3951:39;;4009:38;4043:2;4032:9;4028:18;4009:38;:::i;:::-;3999:48;;3793:260;;;;;:::o;4732:118::-;4818:5;4811:13;4804:21;4797:5;4794:32;4784:60;;4840:1;4837;4830:12;4855:315;4920:6;4928;4981:2;4969:9;4960:7;4956:23;4952:32;4949:52;;;4997:1;4994;4987:12;4949:52;5020:29;5039:9;5020:29;:::i;:::-;5010:39;;5099:2;5088:9;5084:18;5071:32;5112:28;5134:5;5112:28;:::i;:::-;5159:5;5149:15;;;4855:315;;;;;:::o;5440:254::-;5508:6;5516;5569:2;5557:9;5548:7;5544:23;5540:32;5537:52;;;5585:1;5582;5575:12;5537:52;5608:29;5627:9;5608:29;:::i;:::-;5598:39;5684:2;5669:18;;;;5656:32;;-1:-1:-1;;;5440:254:1:o;6744:511::-;6812:6;6820;6828;6881:2;6869:9;6860:7;6856:23;6852:32;6849:52;;;6897:1;6894;6887:12;6849:52;6936:9;6923:23;6955:28;6977:5;6955:28;:::i;:::-;7002:5;-1:-1:-1;7059:2:1;7044:18;;7031:32;7072:30;7031:32;7072:30;:::i;:::-;7121:7;-1:-1:-1;7180:2:1;7165:18;;7152:32;7193:30;7152:32;7193:30;:::i;:::-;7242:7;7232:17;;;6744:511;;;;;:::o;7260:403::-;7346:6;7354;7362;7370;7423:3;7411:9;7402:7;7398:23;7394:33;7391:53;;;7440:1;7437;7430:12;7391:53;7463:29;7482:9;7463:29;:::i;:::-;7453:39;;7539:2;7528:9;7524:18;7511:32;7501:42;;7562:38;7596:2;7585:9;7581:18;7562:38;:::i;:::-;7552:48;;7619:38;7653:2;7642:9;7638:18;7619:38;:::i;:::-;7609:48;;7260:403;;;;;;;:::o;7668:254::-;7736:6;7744;7797:2;7785:9;7776:7;7772:23;7768:32;7765:52;;;7813:1;7810;7803:12;7765:52;7849:9;7836:23;7826:33;;7878:38;7912:2;7901:9;7897:18;7878:38;:::i;7927:241::-;7983:6;8036:2;8024:9;8015:7;8011:23;8007:32;8004:52;;;8052:1;8049;8042:12;8004:52;8091:9;8078:23;8110:28;8132:5;8110:28;:::i;8173:184::-;8225:77;8222:1;8215:88;8322:4;8319:1;8312:15;8346:4;8343:1;8336:15;8362:915;8444:6;8497:3;8485:9;8476:7;8472:23;8468:33;8465:53;;;8514:1;8511;8504:12;8465:53;8563:7;8556:4;8545:9;8541:20;8537:34;8527:62;;8585:1;8582;8575:12;8527:62;8618:2;8612:9;8660:3;8652:6;8648:16;8730:6;8718:10;8715:22;8694:18;8682:10;8679:34;8676:62;8673:242;;;8771:77;8768:1;8761:88;8872:4;8869:1;8862:15;8900:4;8897:1;8890:15;8673:242;8931:2;8924:22;8966:6;9010:3;8995:19;;9026;;;9023:39;;;9058:1;9055;9048:12;9023:39;9082:9;9100:146;9116:6;9111:3;9108:15;9100:146;;;9184:17;;9172:30;;9231:4;9222:14;;;;9133;9100:146;;;-1:-1:-1;9265:6:1;;8362:915;-1:-1:-1;;;;;8362:915:1:o;9282:184::-;9334:77;9331:1;9324:88;9431:4;9428:1;9421:15;9455:4;9452:1;9445:15;9471:184;9523:77;9520:1;9513:88;9620:4;9617:1;9610:15;9644:4;9641:1;9634:15;9660:128;9727:9;;;9748:11;;;9745:37;;;9762:18;;:::i;9793:168::-;9866:9;;;9897;;9914:15;;;9908:22;;9894:37;9884:71;;9935:18;;:::i;9966:274::-;10006:1;10032;10022:189;;10067:77;10064:1;10057:88;10168:4;10165:1;10158:15;10196:4;10193:1;10186:15;10022:189;-1:-1:-1;10225:9:1;;9966:274::o;10245:125::-;10310:9;;;10331:10;;;10328:36;;;10344:18;;:::i;10375:195::-;10414:3;10445:66;10438:5;10435:77;10432:103;;10515:18;;:::i;:::-;-1:-1:-1;10562:1:1;10551:13;;10375:195::o;11351:184::-;11421:6;11474:2;11462:9;11453:7;11449:23;11445:32;11442:52;;;11490:1;11487;11480:12;11442:52;-1:-1:-1;11513:16:1;;11351:184;-1:-1:-1;11351:184:1:o;20145:250::-;20230:1;20240:113;20254:6;20251:1;20248:13;20240:113;;;20330:11;;;20324:18;20311:11;;;20304:39;20276:2;20269:10;20240:113;;;-1:-1:-1;;20387:1:1;20369:16;;20362:27;20145:250::o;20400:287::-;20529:3;20567:6;20561:13;20583:66;20642:6;20637:3;20630:4;20622:6;20618:17;20583:66;:::i;:::-;20665:16;;;;;20400:287;-1:-1:-1;;20400:287:1:o;20692:245::-;20759:6;20812:2;20800:9;20791:7;20787:23;20783:32;20780:52;;;20828:1;20825;20818:12;20780:52;20860:9;20854:16;20879:28;20901:5;20879:28;:::i;23178:245::-;23257:6;23265;23318:2;23306:9;23297:7;23293:23;23289:32;23286:52;;;23334:1;23331;23324:12;23286:52;-1:-1:-1;;23357:16:1;;23413:2;23398:18;;;23392:25;23357:16;;23392:25;;-1:-1:-1;23178:245:1:o;23900:455::-;24049:2;24038:9;24031:21;24012:4;24081:6;24075:13;24124:6;24119:2;24108:9;24104:18;24097:34;24140:79;24212:6;24207:2;24196:9;24192:18;24187:2;24179:6;24175:15;24140:79;:::i;:::-;24271:2;24259:15;24276:66;24255:88;24240:104;;;;24346:2;24236:113;;23900:455;-1:-1:-1;;23900:455:1:o
Swarm Source
ipfs://14c1a22e1cdb68c3efe6ae17cf9f9a6019fd213f84cbe232a6c0ee2c66952755
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | 100.00% | $3.79 | 3,441.9764 | $13,045.09 |
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.